Version 3.9.0-65.0.dev

Merge 7a83c82b4f483b72a2467a6440f187384508ebd8 into dev
diff --git a/pkg/front_end/lib/src/builder/library_builder.dart b/pkg/front_end/lib/src/builder/library_builder.dart
index b30555f..a8bbbe6 100644
--- a/pkg/front_end/lib/src/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/builder/library_builder.dart
@@ -228,8 +228,9 @@
       {required bool allowPartInParts});
 
   void buildOutlineExpressions(
-      Annotatable annotatable, BodyBuilderContext bodyBuilderContext,
-      {required bool createFileUriExpression});
+      {required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required BodyBuilderContext bodyBuilderContext});
 
   /// Reports that [feature] is not enabled, using [charOffset] and
   /// [length] for the location of the message.
diff --git a/pkg/front_end/lib/src/builder/metadata_builder.dart b/pkg/front_end/lib/src/builder/metadata_builder.dart
index a061429..e2e79e2 100644
--- a/pkg/front_end/lib/src/builder/metadata_builder.dart
+++ b/pkg/front_end/lib/src/builder/metadata_builder.dart
@@ -32,7 +32,9 @@
   /// Expression for an already parsed annotation.
   Expression? _expression;
 
-  MetadataBuilder(Token this._atToken)
+  final Uri fileUri;
+
+  MetadataBuilder(Token this._atToken, this.fileUri)
       : atOffset = _atToken.charOffset,
         hasPatch = _atToken.next?.lexeme == 'patch';
 
@@ -51,13 +53,12 @@
       _unresolvedSharedExpressionForTesting;
 
   static void buildAnnotations(
-      Annotatable parent,
-      List<MetadataBuilder>? metadata,
-      BodyBuilderContext bodyBuilderContext,
-      SourceLibraryBuilder library,
-      Uri fileUri,
-      LookupScope scope,
-      {bool createFileUriExpression = false}) {
+      {required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required List<MetadataBuilder>? metadata,
+      required BodyBuilderContext bodyBuilderContext,
+      required SourceLibraryBuilder libraryBuilder,
+      required LookupScope scope}) {
     if (metadata == null) return;
 
     // [BodyBuilder] used to build annotations from [Token]s.
@@ -74,33 +75,42 @@
 
     for (int i = 0; i < metadata.length; ++i) {
       MetadataBuilder annotationBuilder = metadata[i];
+      bool createFileUriExpression =
+          annotatableFileUri != annotationBuilder.fileUri;
       Token? beginToken = annotationBuilder._atToken;
       if (beginToken != null) {
         if (computeSharedExpressionForTesting) {
           // Coverage-ignore-block(suite): Not run.
           annotationBuilder._sharedExpression = _parseSharedExpression(
-              library.loader, beginToken, library.importUri, fileUri, scope);
+              libraryBuilder.loader,
+              beginToken,
+              libraryBuilder.importUri,
+              annotationBuilder.fileUri,
+              scope);
           if (delaySharedExpressionLookupForTesting) {
             annotationBuilder._unresolvedSharedExpressionForTesting =
-                _parseSharedExpression(library.loader, beginToken,
-                    library.importUri, fileUri, scope,
+                _parseSharedExpression(libraryBuilder.loader, beginToken,
+                    libraryBuilder.importUri, annotationBuilder.fileUri, scope,
                     delayLookupForTesting: true);
           }
         }
 
-        bodyBuilder ??= library.loader.createBodyBuilderForOutlineExpression(
-            library, bodyBuilderContext, scope, fileUri);
+        bodyBuilder ??= libraryBuilder.loader
+            .createBodyBuilderForOutlineExpression(libraryBuilder,
+                bodyBuilderContext, scope, annotationBuilder.fileUri);
         Expression annotation = bodyBuilder.parseAnnotation(beginToken);
         annotationBuilder._atToken = null;
         if (createFileUriExpression) {
-          annotation = new FileUriExpression(annotation, fileUri)
-            ..fileOffset = annotationBuilder.atOffset;
+          annotation =
+              new FileUriExpression(annotation, annotationBuilder.fileUri)
+                ..fileOffset = annotationBuilder.atOffset;
         }
         // Record the index of [annotation] in `parent.annotations`.
-        parsedAnnotationBuilders[annotationBuilder] = parent.annotations.length;
+        parsedAnnotationBuilders[annotationBuilder] =
+            annotatable.annotations.length;
         // It is important for the inference and backlog computations that the
         // annotation is already a child of [parent].
-        parent.addAnnotation(annotation);
+        annotatable.addAnnotation(annotation);
       } else {
         // The annotation is needed for multiple declarations so we need to
         // clone the expression to use it more than once. For instance
@@ -124,22 +134,23 @@
             cloner.cloneInContext(annotationBuilder._expression!);
         // Coverage-ignore(suite): Not run.
         if (createFileUriExpression && annotation is! FileUriExpression) {
-          annotation = new FileUriExpression(annotation, fileUri)
-            ..fileOffset = annotationBuilder.atOffset;
+          annotation =
+              new FileUriExpression(annotation, annotationBuilder.fileUri)
+                ..fileOffset = annotationBuilder.atOffset;
         }
-        parent.addAnnotation(annotation);
+        annotatable.addAnnotation(annotation);
       }
     }
     if (bodyBuilder != null) {
       // TODO(johnniwinther): Avoid potentially inferring annotations multiple
       // times.
-      bodyBuilder.inferAnnotations(parent, parent.annotations);
+      bodyBuilder.inferAnnotations(annotatable, annotatable.annotations);
       bodyBuilder.performBacklogComputations();
       for (MapEntry<MetadataBuilder, int> entry
           in parsedAnnotationBuilders.entries) {
         MetadataBuilder annotationBuilder = entry.key;
         int index = entry.value;
-        annotationBuilder._expression = parent.annotations[index];
+        annotationBuilder._expression = annotatable.annotations[index];
       }
     }
   }
diff --git a/pkg/front_end/lib/src/fragment/class/declaration.dart b/pkg/front_end/lib/src/fragment/class/declaration.dart
index 3f105ba..52fba67 100644
--- a/pkg/front_end/lib/src/fragment/class/declaration.dart
+++ b/pkg/front_end/lib/src/fragment/class/declaration.dart
@@ -20,6 +20,7 @@
 
   void buildOutlineExpressions(
       {required Annotatable annotatable,
+      required Uri annotatableFileUri,
       required SourceLibraryBuilder libraryBuilder,
       required ClassHierarchy classHierarchy,
       required BodyBuilderContext bodyBuilderContext,
@@ -69,18 +70,18 @@
   @override
   void buildOutlineExpressions(
       {required Annotatable annotatable,
+      required Uri annotatableFileUri,
       required SourceLibraryBuilder libraryBuilder,
       required ClassHierarchy classHierarchy,
       required BodyBuilderContext bodyBuilderContext,
       required bool createFileUriExpression}) {
     MetadataBuilder.buildAnnotations(
-        annotatable,
-        _fragment.metadata,
-        bodyBuilderContext,
-        libraryBuilder,
-        _fragment.fileUri,
-        _fragment.enclosingScope,
-        createFileUriExpression: createFileUriExpression);
+        annotatable: annotatable,
+        annotatableFileUri: annotatableFileUri,
+        metadata: _fragment.metadata,
+        bodyBuilderContext: bodyBuilderContext,
+        libraryBuilder: libraryBuilder,
+        scope: _fragment.enclosingScope);
   }
 
   @override
@@ -133,18 +134,18 @@
   @override
   void buildOutlineExpressions(
       {required Annotatable annotatable,
+      required Uri annotatableFileUri,
       required SourceLibraryBuilder libraryBuilder,
       required ClassHierarchy classHierarchy,
       required BodyBuilderContext bodyBuilderContext,
       required bool createFileUriExpression}) {
     MetadataBuilder.buildAnnotations(
-        annotatable,
-        _fragment.metadata,
-        bodyBuilderContext,
-        libraryBuilder,
-        _fragment.fileUri,
-        _fragment.enclosingScope,
-        createFileUriExpression: createFileUriExpression);
+        annotatable: annotatable,
+        annotatableFileUri: annotatableFileUri,
+        metadata: _fragment.metadata,
+        bodyBuilderContext: bodyBuilderContext,
+        libraryBuilder: libraryBuilder,
+        scope: _fragment.enclosingScope);
   }
 
   @override
@@ -198,18 +199,18 @@
   @override
   void buildOutlineExpressions(
       {required Annotatable annotatable,
+      required Uri annotatableFileUri,
       required SourceLibraryBuilder libraryBuilder,
       required ClassHierarchy classHierarchy,
       required BodyBuilderContext bodyBuilderContext,
       required bool createFileUriExpression}) {
     MetadataBuilder.buildAnnotations(
-        annotatable,
-        _fragment.metadata,
-        bodyBuilderContext,
-        libraryBuilder,
-        _fragment.fileUri,
-        _fragment.enclosingScope,
-        createFileUriExpression: createFileUriExpression);
+        annotatable: annotatable,
+        annotatableFileUri: annotatableFileUri,
+        metadata: _fragment.metadata,
+        bodyBuilderContext: bodyBuilderContext,
+        libraryBuilder: libraryBuilder,
+        scope: _fragment.enclosingScope);
   }
 
   @override
@@ -266,6 +267,7 @@
   @override
   void buildOutlineExpressions(
       {required Annotatable annotatable,
+      required Uri annotatableFileUri,
       required SourceLibraryBuilder libraryBuilder,
       required ClassHierarchy classHierarchy,
       required BodyBuilderContext bodyBuilderContext,
@@ -319,18 +321,18 @@
   @override
   void buildOutlineExpressions(
       {required Annotatable annotatable,
+      required Uri annotatableFileUri,
       required SourceLibraryBuilder libraryBuilder,
       required ClassHierarchy classHierarchy,
       required BodyBuilderContext bodyBuilderContext,
       required bool createFileUriExpression}) {
     MetadataBuilder.buildAnnotations(
-        annotatable,
-        _fragment.metadata,
-        bodyBuilderContext,
-        libraryBuilder,
-        _fragment.fileUri,
-        _fragment.enclosingScope,
-        createFileUriExpression: createFileUriExpression);
+        annotatable: annotatable,
+        annotatableFileUri: annotatableFileUri,
+        metadata: _fragment.metadata,
+        bodyBuilderContext: bodyBuilderContext,
+        libraryBuilder: libraryBuilder,
+        scope: _fragment.enclosingScope);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fragment/constructor/declaration.dart b/pkg/front_end/lib/src/fragment/constructor/declaration.dart
index 65d77af..7f87320 100644
--- a/pkg/front_end/lib/src/fragment/constructor/declaration.dart
+++ b/pkg/front_end/lib/src/fragment/constructor/declaration.dart
@@ -82,11 +82,11 @@
 
   void buildOutlineExpressions({
     required Iterable<Annotatable> annotatables,
+    required Uri annotatablesFileUri,
     required SourceLibraryBuilder libraryBuilder,
     required DeclarationBuilder declarationBuilder,
     required SourceConstructorBuilderImpl constructorBuilder,
     required ClassHierarchy classHierarchy,
-    required bool createFileUriExpression,
     required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
   });
 
@@ -531,12 +531,12 @@
 
   void _buildMetadataForOutlineExpressions({
     required Iterable<Annotatable> annotatables,
+    required Uri annotatablesFileUri,
     required SourceLibraryBuilder libraryBuilder,
     required DeclarationBuilder declarationBuilder,
     required SourceConstructorBuilderImpl constructorBuilder,
     required BodyBuilderContext bodyBuilderContext,
     required ClassHierarchy classHierarchy,
-    required bool createFileUriExpression,
   });
 
   void _buildTypeParametersAndFormalsForOutlineExpressions({
@@ -549,11 +549,11 @@
   @override
   void buildOutlineExpressions({
     required Iterable<Annotatable> annotatables,
+    required Uri annotatablesFileUri,
     required SourceLibraryBuilder libraryBuilder,
     required DeclarationBuilder declarationBuilder,
     required SourceConstructorBuilderImpl constructorBuilder,
     required ClassHierarchy classHierarchy,
-    required bool createFileUriExpression,
     required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
   }) {
     formals?.infer(classHierarchy);
@@ -561,12 +561,12 @@
         createBodyBuilderContext(constructorBuilder);
     _buildMetadataForOutlineExpressions(
         annotatables: annotatables,
+        annotatablesFileUri: annotatablesFileUri,
         libraryBuilder: libraryBuilder,
         declarationBuilder: declarationBuilder,
         constructorBuilder: constructorBuilder,
         bodyBuilderContext: bodyBuilderContext,
-        classHierarchy: classHierarchy,
-        createFileUriExpression: createFileUriExpression);
+        classHierarchy: classHierarchy);
     _buildTypeParametersAndFormalsForOutlineExpressions(
         libraryBuilder: libraryBuilder,
         declarationBuilder: declarationBuilder,
@@ -845,21 +845,20 @@
   @override
   void _buildMetadataForOutlineExpressions(
       {required Iterable<Annotatable> annotatables,
+      required Uri annotatablesFileUri,
       required SourceLibraryBuilder libraryBuilder,
       required DeclarationBuilder declarationBuilder,
       required SourceConstructorBuilderImpl constructorBuilder,
       required BodyBuilderContext bodyBuilderContext,
-      required ClassHierarchy classHierarchy,
-      required bool createFileUriExpression}) {
+      required ClassHierarchy classHierarchy}) {
     for (Annotatable annotatable in annotatables) {
       MetadataBuilder.buildAnnotations(
-          annotatable,
-          _fragment.metadata,
-          bodyBuilderContext,
-          libraryBuilder,
-          _fragment.fileUri,
-          _fragment.enclosingScope,
-          createFileUriExpression: createFileUriExpression);
+          annotatable: annotatable,
+          annotatableFileUri: annotatablesFileUri,
+          metadata: _fragment.metadata,
+          bodyBuilderContext: bodyBuilderContext,
+          libraryBuilder: libraryBuilder,
+          scope: _fragment.enclosingScope);
     }
   }
 
@@ -975,12 +974,12 @@
   @override
   void _buildMetadataForOutlineExpressions(
       {required Iterable<Annotatable> annotatables,
+      required Uri annotatablesFileUri,
       required SourceLibraryBuilder libraryBuilder,
       required DeclarationBuilder declarationBuilder,
       required SourceConstructorBuilderImpl constructorBuilder,
       required BodyBuilderContext bodyBuilderContext,
-      required ClassHierarchy classHierarchy,
-      required bool createFileUriExpression}) {
+      required ClassHierarchy classHierarchy}) {
     // There is no metadata on a primary constructor.
   }
 
@@ -1109,12 +1108,12 @@
   @override
   void _buildMetadataForOutlineExpressions(
       {required Iterable<Annotatable> annotatables,
+      required Uri annotatablesFileUri,
       required SourceLibraryBuilder libraryBuilder,
       required DeclarationBuilder declarationBuilder,
       required SourceConstructorBuilderImpl constructorBuilder,
       required BodyBuilderContext bodyBuilderContext,
-      required ClassHierarchy classHierarchy,
-      required bool createFileUriExpression}) {
+      required ClassHierarchy classHierarchy}) {
     // There is no metadata on a default enum constructor.
   }
 
@@ -1380,21 +1379,20 @@
   @override
   void _buildMetadataForOutlineExpressions(
       {required Iterable<Annotatable> annotatables,
+      required Uri annotatablesFileUri,
       required SourceLibraryBuilder libraryBuilder,
       required DeclarationBuilder declarationBuilder,
       required SourceConstructorBuilderImpl constructorBuilder,
       required BodyBuilderContext bodyBuilderContext,
-      required ClassHierarchy classHierarchy,
-      required bool createFileUriExpression}) {
+      required ClassHierarchy classHierarchy}) {
     for (Annotatable annotatable in annotatables) {
       MetadataBuilder.buildAnnotations(
-          annotatable,
-          _fragment.metadata,
-          bodyBuilderContext,
-          libraryBuilder,
-          _fragment.fileUri,
-          _fragment.enclosingScope,
-          createFileUriExpression: createFileUriExpression);
+          annotatable: annotatable,
+          annotatableFileUri: annotatablesFileUri,
+          metadata: _fragment.metadata,
+          bodyBuilderContext: bodyBuilderContext,
+          libraryBuilder: libraryBuilder,
+          scope: _fragment.enclosingScope);
     }
   }
 
@@ -1505,12 +1503,12 @@
   @override
   void _buildMetadataForOutlineExpressions(
       {required Iterable<Annotatable> annotatables,
+      required Uri annotatablesFileUri,
       required SourceLibraryBuilder libraryBuilder,
       required DeclarationBuilder declarationBuilder,
       required SourceConstructorBuilderImpl constructorBuilder,
       required BodyBuilderContext bodyBuilderContext,
-      required ClassHierarchy classHierarchy,
-      required bool createFileUriExpression}) {
+      required ClassHierarchy classHierarchy}) {
     // There is no metadata on a primary constructor.
   }
 
diff --git a/pkg/front_end/lib/src/fragment/enum_element.dart b/pkg/front_end/lib/src/fragment/enum_element.dart
index 7e397bf..ee7eb68 100644
--- a/pkg/front_end/lib/src/fragment/enum_element.dart
+++ b/pkg/front_end/lib/src/fragment/enum_element.dart
@@ -328,17 +328,21 @@
 
   @override
   void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      List<Annotatable> annotatables,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression}) {
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required List<Annotatable> annotatables,
+      required Uri annotatablesFileUri,
+      required bool isClassInstanceMember}) {
     BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
     for (Annotatable annotatable in annotatables) {
-      buildMetadataForOutlineExpressions(libraryBuilder,
-          _fragment.enclosingScope, bodyBuilderContext, annotatable, metadata,
-          fileUri: fileUri, createFileUriExpression: createFileUriExpression);
+      buildMetadataForOutlineExpressions(
+          libraryBuilder: libraryBuilder,
+          scope: _fragment.enclosingScope,
+          bodyBuilderContext: bodyBuilderContext,
+          annotatable: annotatable,
+          annotatableFileUri: annotatablesFileUri,
+          metadata: metadata);
     }
   }
 
@@ -574,19 +578,19 @@
 
   @override
   // Coverage-ignore(suite): Not run.
-  DartType get _fieldTypeInternal => _type;
+  DartType get fieldTypeInternal => _type;
 
   @override
   bool get isConst => true;
 
   @override
   // Coverage-ignore(suite): Not run.
-  void _setCovariantByClassInternal() {
+  void setCovariantByClassInternal() {
     _field!.isCovariantByClass = true;
   }
 
   @override
-  void set _fieldTypeInternal(DartType value) {
+  void set fieldTypeInternal(DartType value) {
     _type = value;
     _field?.type = value;
   }
diff --git a/pkg/front_end/lib/src/fragment/factory/declaration.dart b/pkg/front_end/lib/src/fragment/factory/declaration.dart
index ddcc9b5..9075dab 100644
--- a/pkg/front_end/lib/src/fragment/factory/declaration.dart
+++ b/pkg/front_end/lib/src/fragment/factory/declaration.dart
@@ -44,11 +44,12 @@
   Procedure? get tearOff;
 
   void buildOutlineExpressions(
-      {required SourceLibraryBuilder libraryBuilder,
+      {required Iterable<Annotatable> annotatables,
+      required Uri annotatablesFileUri,
+      required SourceLibraryBuilder libraryBuilder,
       required SourceFactoryBuilder factoryBuilder,
       required ClassHierarchy classHierarchy,
-      required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
-      required bool createFileUriExpression});
+      required List<DelayedDefaultValueCloner> delayedDefaultValueCloners});
 
   void buildOutlineNodes(
       {required SourceLibraryBuilder libraryBuilder,
@@ -107,6 +108,7 @@
   int get fileOffset => _fragment.fullNameOffset;
 
   @override
+  // Coverage-ignore(suite): Not run.
   Uri get fileUri => _fragment.fileUri;
 
   @override
@@ -146,25 +148,25 @@
 
   @override
   void buildOutlineExpressions(
-      {required SourceLibraryBuilder libraryBuilder,
+      {required Iterable<Annotatable> annotatables,
+      required Uri annotatablesFileUri,
+      required SourceLibraryBuilder libraryBuilder,
       required SourceFactoryBuilder factoryBuilder,
       required ClassHierarchy classHierarchy,
-      required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
-      required bool createFileUriExpression}) {
+      required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
     _fragment.formals?.infer(classHierarchy);
 
     BodyBuilderContext bodyBuilderContext =
         createBodyBuilderContext(factoryBuilder);
 
-    for (Annotatable annotatable in factoryBuilder.annotatables) {
+    for (Annotatable annotatable in annotatables) {
       MetadataBuilder.buildAnnotations(
-          annotatable,
-          _fragment.metadata,
-          bodyBuilderContext,
-          libraryBuilder,
-          _fragment.fileUri,
-          _fragment.enclosingScope,
-          createFileUriExpression: createFileUriExpression);
+          annotatable: annotatable,
+          annotatableFileUri: annotatablesFileUri,
+          metadata: _fragment.metadata,
+          bodyBuilderContext: bodyBuilderContext,
+          libraryBuilder: libraryBuilder,
+          scope: _fragment.enclosingScope);
     }
     if (typeParameters != null) {
       for (int i = 0; i < typeParameters!.length; i++) {
diff --git a/pkg/front_end/lib/src/fragment/field.dart b/pkg/front_end/lib/src/fragment/field.dart
index bc8eb2b..5efeaa4 100644
--- a/pkg/front_end/lib/src/fragment/field.dart
+++ b/pkg/front_end/lib/src/fragment/field.dart
@@ -4,462 +4,6 @@
 
 part of 'fragment.dart';
 
-class FieldDeclarationImpl
-    with FieldDeclarationMixin
-    implements
-        FieldDeclaration,
-        FieldFragmentDeclaration,
-        Inferable,
-        InferredTypeListener {
-  final FieldFragment _fragment;
-
-  late final _FieldEncoding _encoding;
-
-  shared.Expression? _initializerExpression;
-
-  /// Whether the body of this field has been built.
-  ///
-  /// Constant fields have their initializer built in the outline so we avoid
-  /// building them twice as part of the non-outline build.
-  bool hasBodyBeenBuilt = false;
-
-  FieldDeclarationImpl(this._fragment) {
-    _fragment.declaration = this;
-  }
-
-  @override
-  SourcePropertyBuilder get builder => _fragment.builder;
-
-  @override
-  FieldQuality get fieldQuality => _fragment.modifiers.isAbstract
-      ? FieldQuality.Abstract
-      : _fragment.modifiers.isExternal
-          ? FieldQuality.External
-          : FieldQuality.Concrete;
-
-  @override
-  DartType get fieldType => _encoding.type;
-
-  @override
-  Uri get fileUri => _fragment.fileUri;
-
-  @override
-  GetterQuality get getterQuality => _fragment.modifiers.isAbstract
-      ? GetterQuality.ImplicitAbstract
-      : _fragment.modifiers.isExternal
-          ? GetterQuality.ImplicitExternal
-          : GetterQuality.Implicit;
-
-  @override
-  bool get hasInitializer => _fragment.modifiers.hasInitializer;
-
-  @override
-  bool get hasSetter => _fragment.hasSetter;
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  shared.Expression? get initializerExpression => _initializerExpression;
-
-  @override
-  bool get isConst => _fragment.modifiers.isConst;
-
-  @override
-  bool get isEnumElement => false;
-
-  @override
-  bool get isExtensionTypeDeclaredInstanceField =>
-      builder.isExtensionTypeInstanceMember &&
-      !_fragment.isPrimaryConstructorField;
-
-  @override
-  bool get isFinal => _fragment.modifiers.isFinal;
-
-  @override
-  bool get isLate => _fragment.modifiers.isLate;
-
-  @override
-  bool get isStatic =>
-      _fragment.modifiers.isStatic || builder.declarationBuilder == null;
-
-  @override
-  List<ClassMember> get localMembers => _encoding.localMembers;
-
-  @override
-  List<ClassMember> get localSetters => _encoding.localSetters;
-
-  @override
-  List<MetadataBuilder>? get metadata => _fragment.metadata;
-
-  @override
-  int get nameOffset => _fragment.nameOffset;
-
-  @override
-  Member get readTarget => _encoding.readTarget;
-
-  @override
-  SetterQuality get setterQuality => !hasSetter
-      ? SetterQuality.Absent
-      : _fragment.modifiers.isAbstract
-          ? SetterQuality.ImplicitAbstract
-          : _fragment.modifiers.isExternal
-              ? SetterQuality.ImplicitExternal
-              : SetterQuality.Implicit;
-
-  @override
-  TypeBuilder get type => _fragment.type;
-
-  @override
-  Member? get writeTarget => _encoding.writeTarget;
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  DartType get _fieldTypeInternal => _encoding.type;
-
-  @override
-  void set _fieldTypeInternal(DartType value) {
-    _encoding.type = value;
-  }
-
-  /// Builds the body of this field using [initializer] as the initializer
-  /// expression.
-  void buildBody(CoreTypes coreTypes, Expression? initializer) {
-    assert(!hasBodyBeenBuilt, "Body has already been built for $this.");
-    hasBodyBeenBuilt = true;
-    if (!_fragment.modifiers.hasInitializer &&
-        initializer != null &&
-        initializer is! NullLiteral &&
-        // Coverage-ignore(suite): Not run.
-        !_fragment.modifiers.isConst &&
-        // Coverage-ignore(suite): Not run.
-        !_fragment.modifiers.isFinal) {
-      internalProblem(
-          messageInternalProblemAlreadyInitialized, nameOffset, fileUri);
-    }
-    _encoding.createBodies(coreTypes, initializer);
-  }
-
-  @override
-  Initializer buildErroneousInitializer(Expression effect, Expression value,
-      {required int fileOffset}) {
-    return _encoding.buildErroneousInitializer(effect, value,
-        fileOffset: fileOffset);
-  }
-
-  @override
-  void buildFieldInitializer(InferenceHelper helper, TypeInferrer typeInferrer,
-      CoreTypes coreTypes, Expression? initializer) {
-    if (initializer != null) {
-      if (!hasBodyBeenBuilt) {
-        initializer = typeInferrer
-            .inferFieldInitializer(helper, fieldType, initializer)
-            .expression;
-        buildBody(coreTypes, initializer);
-      }
-    } else if (!hasBodyBeenBuilt) {
-      buildBody(coreTypes, null);
-    }
-  }
-
-  @override
-  void buildImplicitDefaultValue() {
-    _encoding.buildImplicitDefaultValue();
-  }
-
-  @override
-  Initializer buildImplicitInitializer() {
-    return _encoding.buildImplicitInitializer();
-  }
-
-  @override
-  List<Initializer> buildInitializer(int fileOffset, Expression value,
-      {required bool isSynthetic}) {
-    return _encoding.createInitializer(fileOffset, value,
-        isSynthetic: isSynthetic);
-  }
-
-  @override
-  void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      List<Annotatable> annotatables,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression}) {
-    BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
-    for (Annotatable annotatable in annotatables) {
-      buildMetadataForOutlineExpressions(libraryBuilder,
-          _fragment.enclosingScope, bodyBuilderContext, annotatable, metadata,
-          fileUri: fileUri, createFileUriExpression: createFileUriExpression);
-    }
-    // For modular compilation we need to include initializers of all const
-    // fields and all non-static final fields in classes with const constructors
-    // into the outline.
-    Token? token = _fragment.constInitializerToken;
-    if ((_fragment.modifiers.isConst ||
-            (isFinal &&
-                isClassInstanceMember &&
-                (declarationBuilder as SourceClassBuilder)
-                    .declaresConstConstructor)) &&
-        token != null) {
-      LookupScope scope = _fragment.enclosingScope;
-      BodyBuilder bodyBuilder = libraryBuilder.loader
-          .createBodyBuilderForOutlineExpression(
-              libraryBuilder, createBodyBuilderContext(), scope, fileUri);
-      bodyBuilder.constantContext = _fragment.modifiers.isConst
-          ? ConstantContext.inferred
-          : ConstantContext.required;
-      Expression initializer = bodyBuilder.typeInferrer
-          .inferFieldInitializer(
-              bodyBuilder, fieldType, bodyBuilder.parseFieldInitializer(token))
-          .expression;
-      buildBody(classHierarchy.coreTypes, initializer);
-      bodyBuilder.performBacklogComputations();
-      if (computeSharedExpressionForTesting) {
-        // Coverage-ignore-block(suite): Not run.
-        _initializerExpression = parseFieldInitializer(libraryBuilder.loader,
-            token, libraryBuilder.importUri, fileUri, scope);
-      }
-    }
-  }
-
-  @override
-  void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
-      NameScheme nameScheme, BuildNodesCallback f, FieldReference references,
-      {required List<TypeParameter>? classTypeParameters}) {
-    _encoding.buildOutlineNode(libraryBuilder, nameScheme, references,
-        isAbstractOrExternal:
-            _fragment.modifiers.isAbstract || _fragment.modifiers.isExternal,
-        classTypeParameters: classTypeParameters);
-    if (type is! InferableTypeBuilder) {
-      fieldType = type.build(libraryBuilder, TypeUse.fieldType);
-    }
-    _encoding.registerMembers(f);
-  }
-
-  @override
-  void checkTypes(SourceLibraryBuilder libraryBuilder,
-      TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder) {
-    libraryBuilder.checkTypesInField(typeEnvironment,
-        isInstanceMember: builder.isDeclarationInstanceMember,
-        isLate: isLate,
-        isExternal: _fragment.modifiers.isExternal,
-        hasInitializer: hasInitializer,
-        fieldType: fieldType,
-        name: _fragment.name,
-        nameLength: _fragment.name.length,
-        nameOffset: nameOffset,
-        fileUri: fileUri);
-  }
-
-  @override
-  void checkVariance(
-      SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
-    sourceClassBuilder.checkVarianceInField(typeEnvironment,
-        fieldType: fieldType,
-        isInstanceMember: !isStatic,
-        hasSetter: hasSetter,
-        isCovariantByDeclaration: _fragment.modifiers.isCovariant,
-        fileUri: fileUri,
-        fileOffset: nameOffset);
-  }
-
-  @override
-  int computeDefaultTypes(ComputeDefaultTypeContext context) {
-    if (type is! OmittedTypeBuilder) {
-      context.reportInboundReferenceIssuesForType(type);
-      context.recursivelyReportGenericFunctionTypesAsBoundsForType(type);
-    }
-    return 0;
-  }
-
-  @override
-  BodyBuilderContext createBodyBuilderContext() {
-    return new _FieldFragmentBodyBuilderContext(
-        this, _fragment, builder.libraryBuilder, builder.declarationBuilder,
-        isDeclarationInstanceMember: builder.isDeclarationInstanceMember);
-  }
-
-  void createEncoding(SourcePropertyBuilder builder) {
-    SourceLibraryBuilder libraryBuilder = builder.libraryBuilder;
-
-    bool isAbstract = _fragment.modifiers.isAbstract;
-    bool isExternal = _fragment.modifiers.isExternal;
-    bool isInstanceMember = builder.isDeclarationInstanceMember;
-    bool isExtensionMember = builder.isExtensionMember;
-    bool isExtensionTypeMember = builder.isExtensionTypeMember;
-
-    // If in mixed mode, late lowerings cannot use `null` as a sentinel on
-    // non-nullable fields since they can be assigned from legacy code.
-    late_lowering.IsSetStrategy isSetStrategy =
-        late_lowering.computeIsSetStrategy(libraryBuilder);
-    if (isAbstract || isExternal) {
-      _encoding = new AbstractOrExternalFieldEncoding(_fragment,
-          isExtensionInstanceMember: isExtensionMember && isInstanceMember,
-          isExtensionTypeInstanceMember:
-              isExtensionTypeMember && isInstanceMember,
-          isAbstract: isAbstract,
-          isExternal: isExternal);
-    } else if (isExtensionTypeMember && isInstanceMember) {
-      if (_fragment.isPrimaryConstructorField) {
-        _encoding = new RepresentationFieldEncoding(_fragment);
-      } else {
-        // Field on a extension type. Encode as abstract.
-        // TODO(johnniwinther): Should we have an erroneous flag on such
-        // members?
-        _encoding = new AbstractOrExternalFieldEncoding(_fragment,
-            isExtensionInstanceMember: isExtensionMember && isInstanceMember,
-            isExtensionTypeInstanceMember:
-                isExtensionTypeMember && isInstanceMember,
-            isAbstract: true,
-            isExternal: false,
-            isForcedExtension: true);
-      }
-    } else if (isLate &&
-        libraryBuilder.loader.target.backendTarget.isLateFieldLoweringEnabled(
-            hasInitializer: hasInitializer,
-            isFinal: isFinal,
-            isStatic: !isInstanceMember)) {
-      if (hasInitializer) {
-        if (isFinal) {
-          _encoding = new LateFinalFieldWithInitializerEncoding(_fragment,
-              isSetStrategy: isSetStrategy);
-        } else {
-          _encoding = new LateFieldWithInitializerEncoding(_fragment,
-              isSetStrategy: isSetStrategy);
-        }
-      } else {
-        if (isFinal) {
-          _encoding = new LateFinalFieldWithoutInitializerEncoding(_fragment,
-              isSetStrategy: isSetStrategy);
-        } else {
-          _encoding = new LateFieldWithoutInitializerEncoding(_fragment,
-              isSetStrategy: isSetStrategy);
-        }
-      }
-    } else if (libraryBuilder
-            .loader.target.backendTarget.useStaticFieldLowering &&
-        !isInstanceMember &&
-        !_fragment.modifiers.isConst &&
-        hasInitializer) {
-      if (isFinal) {
-        _encoding = new LateFinalFieldWithInitializerEncoding(_fragment,
-            isSetStrategy: isSetStrategy);
-      } else {
-        _encoding = new LateFieldWithInitializerEncoding(_fragment,
-            isSetStrategy: isSetStrategy);
-      }
-    } else {
-      _encoding = new RegularFieldEncoding(_fragment, isEnumElement: false);
-    }
-
-    type.registerInferredTypeListener(this);
-    Token? token = _fragment.initializerToken;
-    if (type is InferableTypeBuilder) {
-      if (!_fragment.modifiers.hasInitializer && isStatic) {
-        // A static field without type and initializer will always be inferred
-        // to have type `dynamic`.
-        type.registerInferredType(const DynamicType());
-      } else {
-        // A field with no type and initializer or an instance field without
-        // type and initializer need to have the type inferred.
-        _encoding.type = new InferredType(
-            libraryBuilder: libraryBuilder,
-            typeBuilder: type,
-            inferType: inferType,
-            computeType: _computeInferredType,
-            fileUri: fileUri,
-            name: _fragment.name,
-            nameOffset: nameOffset,
-            nameLength: _fragment.name.length,
-            token: token);
-        type.registerInferable(this);
-      }
-    }
-  }
-
-  @override
-  void ensureTypes(
-      ClassMembersBuilder membersBuilder,
-      Set<ClassMember>? getterOverrideDependencies,
-      Set<ClassMember>? setterOverrideDependencies) {
-    if (getterOverrideDependencies != null ||
-        setterOverrideDependencies != null) {
-      membersBuilder.inferFieldType(
-          builder.declarationBuilder as SourceClassBuilder,
-          type,
-          [...?getterOverrideDependencies, ...?setterOverrideDependencies],
-          name: _fragment.name,
-          fileUri: fileUri,
-          nameOffset: nameOffset,
-          nameLength: _fragment.name.length,
-          isAssignable: hasSetter);
-    } else {
-      // Coverage-ignore-block(suite): Not run.
-      type.build(builder.libraryBuilder, TypeUse.fieldType,
-          hierarchy: membersBuilder.hierarchyBuilder);
-    }
-  }
-
-  @override
-  Iterable<Reference> getExportedMemberReferences(FieldReference references) {
-    return [
-      references.getterReference!,
-      if (hasSetter) references.setterReference!
-    ];
-  }
-
-  @override
-  void registerSuperCall() {
-    _encoding.registerSuperCall();
-  }
-
-  DartType _computeInferredType(
-      ClassHierarchyBase classHierarchy, Token? token) {
-    DartType? inferredType;
-    SourceLibraryBuilder libraryBuilder = builder.libraryBuilder;
-    DeclarationBuilder? declarationBuilder = builder.declarationBuilder;
-    if (token != null) {
-      InterfaceType? enclosingClassThisType = declarationBuilder
-              is SourceClassBuilder
-          ? libraryBuilder.loader.typeInferenceEngine.coreTypes
-              .thisInterfaceType(
-                  declarationBuilder.cls, libraryBuilder.library.nonNullable)
-          : null;
-      LookupScope scope = _fragment.enclosingScope;
-      TypeInferrer typeInferrer =
-          libraryBuilder.loader.typeInferenceEngine.createTopLevelTypeInferrer(
-              fileUri,
-              enclosingClassThisType,
-              libraryBuilder,
-              scope,
-              builder
-                  .dataForTesting
-                  // Coverage-ignore(suite): Not run.
-                  ?.inferenceData);
-      BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
-      BodyBuilder bodyBuilder = libraryBuilder.loader.createBodyBuilderForField(
-          libraryBuilder, bodyBuilderContext, scope, typeInferrer, fileUri);
-      bodyBuilder.constantContext = _fragment.modifiers.isConst
-          ? ConstantContext.inferred
-          : ConstantContext.none;
-      bodyBuilder.inFieldInitializer = true;
-      bodyBuilder.inLateFieldInitializer = _fragment.modifiers.isLate;
-      Expression initializer = bodyBuilder.parseFieldInitializer(token);
-
-      inferredType =
-          typeInferrer.inferImplicitFieldType(bodyBuilder, initializer);
-    } else {
-      inferredType = const DynamicType();
-    }
-    return inferredType;
-  }
-
-  @override
-  void _setCovariantByClassInternal() {
-    _encoding.setCovariantByClass();
-  }
-}
-
 class FieldFragment implements Fragment {
   @override
   final String name;
@@ -573,16 +117,3 @@
   @override
   String toString() => '$runtimeType($name,$fileUri,$nameOffset)';
 }
-
-abstract class FieldFragmentDeclaration {
-  bool get isStatic;
-
-  void buildFieldInitializer(InferenceHelper helper, TypeInferrer typeInferrer,
-      CoreTypes coreTypes, Expression? initializer);
-
-  BodyBuilderContext createBodyBuilderContext();
-
-  /// Registers that a `super` call has occurred in the initializer of this
-  /// field.
-  void registerSuperCall();
-}
diff --git a/pkg/front_end/lib/src/fragment/field/body_builder_context.dart b/pkg/front_end/lib/src/fragment/field/body_builder_context.dart
index d9027f3..f666aa1 100644
--- a/pkg/front_end/lib/src/fragment/field/body_builder_context.dart
+++ b/pkg/front_end/lib/src/fragment/field/body_builder_context.dart
@@ -4,11 +4,11 @@
 
 part of '../fragment.dart';
 
-class _FieldFragmentBodyBuilderContext extends BodyBuilderContext {
+class FieldFragmentBodyBuilderContext extends BodyBuilderContext {
   final FieldFragmentDeclaration _declaration;
   final FieldFragment _fragment;
 
-  _FieldFragmentBodyBuilderContext(
+  FieldFragmentBodyBuilderContext(
       this._declaration,
       this._fragment,
       SourceLibraryBuilder libraryBuilder,
diff --git a/pkg/front_end/lib/src/fragment/field/declaration.dart b/pkg/front_end/lib/src/fragment/field/declaration.dart
new file mode 100644
index 0000000..3a235b4
--- /dev/null
+++ b/pkg/front_end/lib/src/fragment/field/declaration.dart
@@ -0,0 +1,716 @@
+// Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/metadata/expressions.dart' as shared;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/type_environment.dart';
+
+import '../../base/constant_context.dart';
+import '../../base/messages.dart';
+import '../../base/problems.dart';
+import '../../base/scope.dart';
+import '../../builder/declaration_builders.dart';
+import '../../builder/metadata_builder.dart';
+import '../../builder/omitted_type_builder.dart';
+import '../../builder/property_builder.dart';
+import '../../builder/type_builder.dart';
+import '../../kernel/body_builder.dart';
+import '../../kernel/body_builder_context.dart';
+import '../../kernel/hierarchy/class_member.dart';
+import '../../kernel/hierarchy/members_builder.dart';
+import '../../kernel/implicit_field_type.dart';
+import '../../kernel/late_lowering.dart' as late_lowering;
+import '../../kernel/macro/metadata.dart';
+import '../../kernel/type_algorithms.dart';
+import '../../source/name_scheme.dart';
+import '../../source/source_class_builder.dart';
+import '../../source/source_library_builder.dart';
+import '../../source/source_member_builder.dart';
+import '../../source/source_property_builder.dart';
+import '../../type_inference/inference_helper.dart';
+import '../../type_inference/type_inference_engine.dart';
+import '../../type_inference/type_inferrer.dart';
+import '../fragment.dart';
+
+/// Common interface for fragments that can declare a field.
+abstract class FieldDeclaration {
+  FieldQuality get fieldQuality;
+
+  GetterQuality get getterQuality;
+
+  SetterQuality get setterQuality;
+
+  /// The metadata declared on this fragment.
+  List<MetadataBuilder>? get metadata;
+
+  /// Builds the core AST structures for this field declaration as needed for
+  /// the outline.
+  void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+      NameScheme nameScheme, BuildNodesCallback f, FieldReference references,
+      {required List<TypeParameter>? classTypeParameters});
+
+  void buildOutlineExpressions(
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required List<Annotatable> annotatables,
+      required Uri annotatablesFileUri,
+      required bool isClassInstanceMember});
+
+  int computeDefaultTypes(ComputeDefaultTypeContext context);
+
+  void checkTypes(SourceLibraryBuilder libraryBuilder,
+      TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder);
+
+  /// Checks the variance of type parameters [sourceClassBuilder] used in the
+  /// type of this field declaration.
+  void checkVariance(
+      SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment);
+
+  /// The references to the members from this field declaration that are
+  /// accessible in exports through the name of the builder.
+  Iterable<Reference> getExportedMemberReferences(FieldReference references);
+
+  /// Return `true` if the declaration introduces a setter.
+  bool get hasSetter;
+
+  /// Return `true` if the declaration has an initializer.
+  bool get hasInitializer;
+
+  /// Return `true` if the declaration is final.
+  bool get isFinal;
+
+  /// Return `true` if the declaration is late.
+  bool get isLate;
+
+  /// Return `true` if the declaration is in instance field declared in an
+  /// extension type.
+  bool get isExtensionTypeDeclaredInstanceField;
+
+  /// Returns `true` if this field is declared by an enum element.
+  bool get isEnumElement;
+
+  /// The [ClassMember]s for the getter introduced by this field declaration.
+  List<ClassMember> get localMembers;
+
+  /// The [ClassMember]s for the setter introduced by this field declaration,
+  /// if any.
+  List<ClassMember> get localSetters;
+
+  /// The [Member] uses as the target for reading from this field declaration.
+  Member get readTarget;
+
+  /// The [Member] uses as the target for writing to this field declaration, or
+  /// `null` if this field declaration has no setter.
+  Member? get writeTarget;
+
+  /// The [DartType] of this field declaration.
+  abstract DartType fieldType;
+
+  /// Creates the [Initializer] for the invalid initialization of this field.
+  ///
+  /// This is only used for instance fields.
+  Initializer buildErroneousInitializer(Expression effect, Expression value,
+      {required int fileOffset});
+
+  /// Creates the AST node for this field as the default initializer.
+  ///
+  /// This is only used for instance fields.
+  void buildImplicitDefaultValue();
+
+  /// Creates the [Initializer] for the implicit initialization of this field
+  /// in a constructor.
+  ///
+  /// This is only used for instance fields.
+  Initializer buildImplicitInitializer();
+
+  /// Builds the [Initializer]s for each field used to encode this field
+  /// using the [fileOffset] for the created nodes and [value] as the initial
+  /// field value.
+  ///
+  /// This is only used for instance fields.
+  List<Initializer> buildInitializer(int fileOffset, Expression value,
+      {required bool isSynthetic});
+
+  /// Ensures that the type of this field declaration has been computed.
+  void ensureTypes(
+      ClassMembersBuilder membersBuilder,
+      Set<ClassMember>? getterOverrideDependencies,
+      Set<ClassMember>? setterOverrideDependencies);
+
+  /// Infers the type of this field declaration.
+  DartType inferType(ClassHierarchyBase hierarchy);
+
+  shared.Expression? get initializerExpression;
+}
+
+class FieldDeclarationImpl
+    with FieldDeclarationMixin
+    implements
+        FieldDeclaration,
+        FieldFragmentDeclaration,
+        Inferable,
+        InferredTypeListener {
+  final FieldFragment _fragment;
+
+  late final FieldEncoding _encoding;
+
+  shared.Expression? _initializerExpression;
+
+  /// Whether the body of this field has been built.
+  ///
+  /// Constant fields have their initializer built in the outline so we avoid
+  /// building them twice as part of the non-outline build.
+  bool hasBodyBeenBuilt = false;
+
+  FieldDeclarationImpl(this._fragment) {
+    _fragment.declaration = this;
+  }
+
+  @override
+  SourcePropertyBuilder get builder => _fragment.builder;
+
+  @override
+  FieldQuality get fieldQuality => _fragment.modifiers.isAbstract
+      ? FieldQuality.Abstract
+      : _fragment.modifiers.isExternal
+          ? FieldQuality.External
+          : FieldQuality.Concrete;
+
+  @override
+  DartType get fieldType => _encoding.type;
+
+  @override
+  Uri get fileUri => _fragment.fileUri;
+
+  @override
+  GetterQuality get getterQuality => _fragment.modifiers.isAbstract
+      ? GetterQuality.ImplicitAbstract
+      : _fragment.modifiers.isExternal
+          ? GetterQuality.ImplicitExternal
+          : GetterQuality.Implicit;
+
+  @override
+  bool get hasInitializer => _fragment.modifiers.hasInitializer;
+
+  @override
+  bool get hasSetter => _fragment.hasSetter;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  shared.Expression? get initializerExpression => _initializerExpression;
+
+  @override
+  bool get isConst => _fragment.modifiers.isConst;
+
+  @override
+  bool get isEnumElement => false;
+
+  @override
+  bool get isExtensionTypeDeclaredInstanceField =>
+      builder.isExtensionTypeInstanceMember &&
+      !_fragment.isPrimaryConstructorField;
+
+  @override
+  bool get isFinal => _fragment.modifiers.isFinal;
+
+  @override
+  bool get isLate => _fragment.modifiers.isLate;
+
+  @override
+  bool get isStatic =>
+      _fragment.modifiers.isStatic || builder.declarationBuilder == null;
+
+  @override
+  List<ClassMember> get localMembers => _encoding.localMembers;
+
+  @override
+  List<ClassMember> get localSetters => _encoding.localSetters;
+
+  @override
+  List<MetadataBuilder>? get metadata => _fragment.metadata;
+
+  @override
+  int get nameOffset => _fragment.nameOffset;
+
+  @override
+  Member get readTarget => _encoding.readTarget;
+
+  @override
+  SetterQuality get setterQuality => !hasSetter
+      ? SetterQuality.Absent
+      : _fragment.modifiers.isAbstract
+          ? SetterQuality.ImplicitAbstract
+          : _fragment.modifiers.isExternal
+              ? SetterQuality.ImplicitExternal
+              : SetterQuality.Implicit;
+
+  @override
+  TypeBuilder get type => _fragment.type;
+
+  @override
+  Member? get writeTarget => _encoding.writeTarget;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  DartType get fieldTypeInternal => _encoding.type;
+
+  @override
+  void set fieldTypeInternal(DartType value) {
+    _encoding.type = value;
+  }
+
+  /// Builds the body of this field using [initializer] as the initializer
+  /// expression.
+  void buildBody(CoreTypes coreTypes, Expression? initializer) {
+    assert(!hasBodyBeenBuilt, "Body has already been built for $this.");
+    hasBodyBeenBuilt = true;
+    if (!_fragment.modifiers.hasInitializer &&
+        initializer != null &&
+        initializer is! NullLiteral &&
+        // Coverage-ignore(suite): Not run.
+        !_fragment.modifiers.isConst &&
+        // Coverage-ignore(suite): Not run.
+        !_fragment.modifiers.isFinal) {
+      internalProblem(
+          messageInternalProblemAlreadyInitialized, nameOffset, fileUri);
+    }
+    _encoding.createBodies(coreTypes, initializer);
+  }
+
+  @override
+  Initializer buildErroneousInitializer(Expression effect, Expression value,
+      {required int fileOffset}) {
+    return _encoding.buildErroneousInitializer(effect, value,
+        fileOffset: fileOffset);
+  }
+
+  @override
+  void buildFieldInitializer(InferenceHelper helper, TypeInferrer typeInferrer,
+      CoreTypes coreTypes, Expression? initializer) {
+    if (initializer != null) {
+      if (!hasBodyBeenBuilt) {
+        initializer = typeInferrer
+            .inferFieldInitializer(helper, fieldType, initializer)
+            .expression;
+        buildBody(coreTypes, initializer);
+      }
+    } else if (!hasBodyBeenBuilt) {
+      buildBody(coreTypes, null);
+    }
+  }
+
+  @override
+  void buildImplicitDefaultValue() {
+    _encoding.buildImplicitDefaultValue();
+  }
+
+  @override
+  Initializer buildImplicitInitializer() {
+    return _encoding.buildImplicitInitializer();
+  }
+
+  @override
+  List<Initializer> buildInitializer(int fileOffset, Expression value,
+      {required bool isSynthetic}) {
+    return _encoding.createInitializer(fileOffset, value,
+        isSynthetic: isSynthetic);
+  }
+
+  @override
+  void buildOutlineExpressions(
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required List<Annotatable> annotatables,
+      required Uri annotatablesFileUri,
+      required bool isClassInstanceMember}) {
+    BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
+    for (Annotatable annotatable in annotatables) {
+      buildMetadataForOutlineExpressions(
+          libraryBuilder: libraryBuilder,
+          scope: _fragment.enclosingScope,
+          bodyBuilderContext: bodyBuilderContext,
+          annotatable: annotatable,
+          annotatableFileUri: annotatablesFileUri,
+          metadata: metadata);
+    }
+    // For modular compilation we need to include initializers of all const
+    // fields and all non-static final fields in classes with const constructors
+    // into the outline.
+    Token? token = _fragment.constInitializerToken;
+    if ((_fragment.modifiers.isConst ||
+            (isFinal &&
+                isClassInstanceMember &&
+                (declarationBuilder as SourceClassBuilder)
+                    .declaresConstConstructor)) &&
+        token != null) {
+      LookupScope scope = _fragment.enclosingScope;
+      BodyBuilder bodyBuilder = libraryBuilder.loader
+          .createBodyBuilderForOutlineExpression(
+              libraryBuilder, createBodyBuilderContext(), scope, fileUri);
+      bodyBuilder.constantContext = _fragment.modifiers.isConst
+          ? ConstantContext.inferred
+          : ConstantContext.required;
+      Expression initializer = bodyBuilder.typeInferrer
+          .inferFieldInitializer(
+              bodyBuilder, fieldType, bodyBuilder.parseFieldInitializer(token))
+          .expression;
+      buildBody(classHierarchy.coreTypes, initializer);
+      bodyBuilder.performBacklogComputations();
+      if (computeSharedExpressionForTesting) {
+        // Coverage-ignore-block(suite): Not run.
+        _initializerExpression = parseFieldInitializer(libraryBuilder.loader,
+            token, libraryBuilder.importUri, fileUri, scope);
+      }
+    }
+  }
+
+  @override
+  void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+      NameScheme nameScheme, BuildNodesCallback f, FieldReference references,
+      {required List<TypeParameter>? classTypeParameters}) {
+    _encoding.buildOutlineNode(libraryBuilder, nameScheme, references,
+        isAbstractOrExternal:
+            _fragment.modifiers.isAbstract || _fragment.modifiers.isExternal,
+        classTypeParameters: classTypeParameters);
+    if (type is! InferableTypeBuilder) {
+      fieldType = type.build(libraryBuilder, TypeUse.fieldType);
+    }
+    _encoding.registerMembers(f);
+  }
+
+  @override
+  void checkTypes(SourceLibraryBuilder libraryBuilder,
+      TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder) {
+    libraryBuilder.checkTypesInField(typeEnvironment,
+        isInstanceMember: builder.isDeclarationInstanceMember,
+        isLate: isLate,
+        isExternal: _fragment.modifiers.isExternal,
+        hasInitializer: hasInitializer,
+        fieldType: fieldType,
+        name: _fragment.name,
+        nameLength: _fragment.name.length,
+        nameOffset: nameOffset,
+        fileUri: fileUri);
+  }
+
+  @override
+  void checkVariance(
+      SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
+    sourceClassBuilder.checkVarianceInField(typeEnvironment,
+        fieldType: fieldType,
+        isInstanceMember: !isStatic,
+        hasSetter: hasSetter,
+        isCovariantByDeclaration: _fragment.modifiers.isCovariant,
+        fileUri: fileUri,
+        fileOffset: nameOffset);
+  }
+
+  @override
+  int computeDefaultTypes(ComputeDefaultTypeContext context) {
+    if (type is! OmittedTypeBuilder) {
+      context.reportInboundReferenceIssuesForType(type);
+      context.recursivelyReportGenericFunctionTypesAsBoundsForType(type);
+    }
+    return 0;
+  }
+
+  @override
+  BodyBuilderContext createBodyBuilderContext() {
+    return new FieldFragmentBodyBuilderContext(
+        this, _fragment, builder.libraryBuilder, builder.declarationBuilder,
+        isDeclarationInstanceMember: builder.isDeclarationInstanceMember);
+  }
+
+  void createEncoding(SourcePropertyBuilder builder) {
+    SourceLibraryBuilder libraryBuilder = builder.libraryBuilder;
+
+    bool isAbstract = _fragment.modifiers.isAbstract;
+    bool isExternal = _fragment.modifiers.isExternal;
+    bool isInstanceMember = builder.isDeclarationInstanceMember;
+    bool isExtensionMember = builder.isExtensionMember;
+    bool isExtensionTypeMember = builder.isExtensionTypeMember;
+
+    // If in mixed mode, late lowerings cannot use `null` as a sentinel on
+    // non-nullable fields since they can be assigned from legacy code.
+    late_lowering.IsSetStrategy isSetStrategy =
+        late_lowering.computeIsSetStrategy(libraryBuilder);
+    if (isAbstract || isExternal) {
+      _encoding = new AbstractOrExternalFieldEncoding(_fragment,
+          isExtensionInstanceMember: isExtensionMember && isInstanceMember,
+          isExtensionTypeInstanceMember:
+              isExtensionTypeMember && isInstanceMember,
+          isAbstract: isAbstract,
+          isExternal: isExternal);
+    } else if (isExtensionTypeMember && isInstanceMember) {
+      if (_fragment.isPrimaryConstructorField) {
+        _encoding = new RepresentationFieldEncoding(_fragment);
+      } else {
+        // Field on a extension type. Encode as abstract.
+        // TODO(johnniwinther): Should we have an erroneous flag on such
+        // members?
+        _encoding = new AbstractOrExternalFieldEncoding(_fragment,
+            isExtensionInstanceMember: isExtensionMember && isInstanceMember,
+            isExtensionTypeInstanceMember:
+                isExtensionTypeMember && isInstanceMember,
+            isAbstract: true,
+            isExternal: false,
+            isForcedExtension: true);
+      }
+    } else if (isLate &&
+        libraryBuilder.loader.target.backendTarget.isLateFieldLoweringEnabled(
+            hasInitializer: hasInitializer,
+            isFinal: isFinal,
+            isStatic: !isInstanceMember)) {
+      if (hasInitializer) {
+        if (isFinal) {
+          _encoding = new LateFinalFieldWithInitializerEncoding(_fragment,
+              isSetStrategy: isSetStrategy);
+        } else {
+          _encoding = new LateFieldWithInitializerEncoding(_fragment,
+              isSetStrategy: isSetStrategy);
+        }
+      } else {
+        if (isFinal) {
+          _encoding = new LateFinalFieldWithoutInitializerEncoding(_fragment,
+              isSetStrategy: isSetStrategy);
+        } else {
+          _encoding = new LateFieldWithoutInitializerEncoding(_fragment,
+              isSetStrategy: isSetStrategy);
+        }
+      }
+    } else if (libraryBuilder
+            .loader.target.backendTarget.useStaticFieldLowering &&
+        !isInstanceMember &&
+        !_fragment.modifiers.isConst &&
+        hasInitializer) {
+      if (isFinal) {
+        _encoding = new LateFinalFieldWithInitializerEncoding(_fragment,
+            isSetStrategy: isSetStrategy);
+      } else {
+        _encoding = new LateFieldWithInitializerEncoding(_fragment,
+            isSetStrategy: isSetStrategy);
+      }
+    } else {
+      _encoding = new RegularFieldEncoding(_fragment, isEnumElement: false);
+    }
+
+    type.registerInferredTypeListener(this);
+    Token? token = _fragment.initializerToken;
+    if (type is InferableTypeBuilder) {
+      if (!_fragment.modifiers.hasInitializer && isStatic) {
+        // A static field without type and initializer will always be inferred
+        // to have type `dynamic`.
+        type.registerInferredType(const DynamicType());
+      } else {
+        // A field with no type and initializer or an instance field without
+        // type and initializer need to have the type inferred.
+        _encoding.type = new InferredType(
+            libraryBuilder: libraryBuilder,
+            typeBuilder: type,
+            inferType: inferType,
+            computeType: _computeInferredType,
+            fileUri: fileUri,
+            name: _fragment.name,
+            nameOffset: nameOffset,
+            nameLength: _fragment.name.length,
+            token: token);
+        type.registerInferable(this);
+      }
+    }
+  }
+
+  @override
+  void ensureTypes(
+      ClassMembersBuilder membersBuilder,
+      Set<ClassMember>? getterOverrideDependencies,
+      Set<ClassMember>? setterOverrideDependencies) {
+    if (getterOverrideDependencies != null ||
+        setterOverrideDependencies != null) {
+      membersBuilder.inferFieldType(
+          builder.declarationBuilder as SourceClassBuilder,
+          type,
+          [...?getterOverrideDependencies, ...?setterOverrideDependencies],
+          name: _fragment.name,
+          fileUri: fileUri,
+          nameOffset: nameOffset,
+          nameLength: _fragment.name.length,
+          isAssignable: hasSetter);
+    } else {
+      // Coverage-ignore-block(suite): Not run.
+      type.build(builder.libraryBuilder, TypeUse.fieldType,
+          hierarchy: membersBuilder.hierarchyBuilder);
+    }
+  }
+
+  @override
+  Iterable<Reference> getExportedMemberReferences(FieldReference references) {
+    return [
+      references.getterReference!,
+      if (hasSetter) references.setterReference!
+    ];
+  }
+
+  @override
+  void registerSuperCall() {
+    _encoding.registerSuperCall();
+  }
+
+  DartType _computeInferredType(
+      ClassHierarchyBase classHierarchy, Token? token) {
+    DartType? inferredType;
+    SourceLibraryBuilder libraryBuilder = builder.libraryBuilder;
+    DeclarationBuilder? declarationBuilder = builder.declarationBuilder;
+    if (token != null) {
+      InterfaceType? enclosingClassThisType = declarationBuilder
+              is SourceClassBuilder
+          ? libraryBuilder.loader.typeInferenceEngine.coreTypes
+              .thisInterfaceType(
+                  declarationBuilder.cls, libraryBuilder.library.nonNullable)
+          : null;
+      LookupScope scope = _fragment.enclosingScope;
+      TypeInferrer typeInferrer =
+          libraryBuilder.loader.typeInferenceEngine.createTopLevelTypeInferrer(
+              fileUri,
+              enclosingClassThisType,
+              libraryBuilder,
+              scope,
+              builder
+                  .dataForTesting
+                  // Coverage-ignore(suite): Not run.
+                  ?.inferenceData);
+      BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
+      BodyBuilder bodyBuilder = libraryBuilder.loader.createBodyBuilderForField(
+          libraryBuilder, bodyBuilderContext, scope, typeInferrer, fileUri);
+      bodyBuilder.constantContext = _fragment.modifiers.isConst
+          ? ConstantContext.inferred
+          : ConstantContext.none;
+      bodyBuilder.inFieldInitializer = true;
+      bodyBuilder.inLateFieldInitializer = _fragment.modifiers.isLate;
+      Expression initializer = bodyBuilder.parseFieldInitializer(token);
+
+      inferredType =
+          typeInferrer.inferImplicitFieldType(bodyBuilder, initializer);
+    } else {
+      inferredType = const DynamicType();
+    }
+    return inferredType;
+  }
+
+  @override
+  void setCovariantByClassInternal() {
+    _encoding.setCovariantByClass();
+  }
+}
+
+mixin FieldDeclarationMixin
+    implements FieldDeclaration, Inferable, InferredTypeListener {
+  Uri get fileUri;
+
+  int get nameOffset;
+
+  SourcePropertyBuilder get builder;
+
+  bool get isConst;
+
+  /// The [TypeBuilder] for the declared type of this field declaration.
+  TypeBuilder get type;
+
+  void setCovariantByClassInternal();
+
+  abstract DartType fieldTypeInternal;
+
+  @override
+  void onInferredType(DartType type) {
+    fieldType = type;
+  }
+
+  @override
+  void inferTypes(ClassHierarchyBase hierarchy) {
+    inferType(hierarchy);
+  }
+
+  @override
+  DartType inferType(ClassHierarchyBase hierarchy) {
+    if (fieldType is! InferredType) {
+      // We have already inferred a type.
+      return fieldType;
+    }
+
+    return builder.libraryBuilder.loader
+        .withUriForCrashReporting(fileUri, nameOffset, () {
+      InferredType implicitFieldType = fieldType as InferredType;
+      DartType inferredType = implicitFieldType.computeType(hierarchy);
+      if (fieldType is InferredType) {
+        // `fieldType` may have changed if a circularity was detected when
+        // [inferredType] was computed.
+        type.registerInferredType(inferredType);
+
+        // TODO(johnniwinther): Isn't this handled in the [fieldType] setter?
+        IncludesTypeParametersNonCovariantly? needsCheckVisitor;
+        DeclarationBuilder? declarationBuilder = builder.declarationBuilder;
+        if (declarationBuilder is ClassBuilder) {
+          Class enclosingClass = declarationBuilder.cls;
+          if (enclosingClass.typeParameters.isNotEmpty) {
+            needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
+                enclosingClass.typeParameters,
+                // We are checking the field type as if it is the type of the
+                // parameter of the implicit setter and this is a contravariant
+                // position.
+                initialVariance: Variance.contravariant);
+          }
+        }
+        if (needsCheckVisitor != null) {
+          if (fieldType.accept(needsCheckVisitor)) {
+            setCovariantByClassInternal();
+          }
+        }
+      }
+      return fieldType;
+    });
+  }
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  DartType get fieldType => fieldTypeInternal;
+
+  @override
+  void set fieldType(DartType value) {
+    fieldTypeInternal = value;
+    DeclarationBuilder? declarationBuilder = builder.declarationBuilder;
+    // TODO(johnniwinther): Should this be `hasSetter`?
+    if (!isFinal && !isConst && declarationBuilder is ClassBuilder) {
+      Class enclosingClass = declarationBuilder.cls;
+      if (enclosingClass.typeParameters.isNotEmpty) {
+        IncludesTypeParametersNonCovariantly needsCheckVisitor =
+            new IncludesTypeParametersNonCovariantly(
+                enclosingClass.typeParameters,
+                // We are checking the field type as if it is the type of the
+                // parameter of the implicit setter and this is a contravariant
+                // position.
+                initialVariance: Variance.contravariant);
+        if (value.accept(needsCheckVisitor)) {
+          setCovariantByClassInternal();
+        }
+      }
+    }
+  }
+}
+
+abstract class FieldFragmentDeclaration {
+  bool get isStatic;
+
+  void buildFieldInitializer(InferenceHelper helper, TypeInferrer typeInferrer,
+      CoreTypes coreTypes, Expression? initializer);
+
+  BodyBuilderContext createBodyBuilderContext();
+
+  /// Registers that a `super` call has occurred in the initializer of this
+  /// field.
+  void registerSuperCall();
+}
diff --git a/pkg/front_end/lib/src/fragment/field/encoding.dart b/pkg/front_end/lib/src/fragment/field/encoding.dart
index c5de38e..b14502a 100644
--- a/pkg/front_end/lib/src/fragment/field/encoding.dart
+++ b/pkg/front_end/lib/src/fragment/field/encoding.dart
@@ -8,7 +8,7 @@
 ///
 /// This is used to provide lowerings for late fields using synthesized getters
 /// and setters.
-sealed class _FieldEncoding {
+sealed class FieldEncoding {
   /// Creates the members necessary for this field encoding.
   ///
   /// This method is called for both outline and full compilation so the created
@@ -100,7 +100,7 @@
   void registerSuperCall();
 }
 
-class RegularFieldEncoding implements _FieldEncoding {
+class RegularFieldEncoding implements FieldEncoding {
   final FieldFragment _fragment;
   final bool isEnumElement;
   Field? _field;
@@ -269,7 +269,7 @@
   }
 }
 
-abstract class AbstractLateFieldEncoding implements _FieldEncoding {
+abstract class AbstractLateFieldEncoding implements FieldEncoding {
   final FieldFragment _fragment;
   DartType? _type;
   Field? _field;
@@ -849,7 +849,7 @@
   }
 }
 
-class AbstractOrExternalFieldEncoding implements _FieldEncoding {
+class AbstractOrExternalFieldEncoding implements FieldEncoding {
   final FieldFragment _fragment;
   final bool isAbstract;
   final bool isExternal;
@@ -1191,7 +1191,7 @@
 }
 
 /// The encoding of an extension type declaration representation field.
-class RepresentationFieldEncoding implements _FieldEncoding {
+class RepresentationFieldEncoding implements FieldEncoding {
   final FieldFragment _fragment;
 
   late Procedure _getter;
diff --git a/pkg/front_end/lib/src/fragment/fragment.dart b/pkg/front_end/lib/src/fragment/fragment.dart
index 1a6b448..1322275 100644
--- a/pkg/front_end/lib/src/fragment/fragment.dart
+++ b/pkg/front_end/lib/src/fragment/fragment.dart
@@ -17,7 +17,6 @@
 import '../base/local_scope.dart';
 import '../base/messages.dart';
 import '../base/modifiers.dart';
-import '../base/problems.dart';
 import '../base/scope.dart';
 import '../builder/builder.dart';
 import '../builder/constructor_reference_builder.dart';
@@ -40,7 +39,6 @@
 import '../kernel/implicit_field_type.dart';
 import '../kernel/internal_ast.dart';
 import '../kernel/late_lowering.dart' as late_lowering;
-import '../kernel/macro/metadata.dart';
 import '../kernel/member_covariance.dart';
 import '../kernel/type_algorithms.dart';
 import '../source/builder_factory.dart';
@@ -58,13 +56,12 @@
 import '../source/source_type_alias_builder.dart';
 import '../source/source_type_parameter_builder.dart';
 import '../source/type_parameter_scope_builder.dart';
-import '../type_inference/inference_helper.dart';
 import '../type_inference/inference_results.dart';
 import '../type_inference/type_inference_engine.dart';
-import '../type_inference/type_inferrer.dart';
 import '../type_inference/type_schema.dart';
 import 'constructor/declaration.dart';
 import 'factory/declaration.dart';
+import 'field/declaration.dart';
 import 'getter/declaration.dart';
 import 'getter/encoding.dart';
 import 'method/declaration.dart';
diff --git a/pkg/front_end/lib/src/fragment/getter/declaration.dart b/pkg/front_end/lib/src/fragment/getter/declaration.dart
index 1b4c029..9ed821c 100644
--- a/pkg/front_end/lib/src/fragment/getter/declaration.dart
+++ b/pkg/front_end/lib/src/fragment/getter/declaration.dart
@@ -44,8 +44,8 @@
       required DeclarationBuilder? declarationBuilder,
       required SourcePropertyBuilder propertyBuilder,
       required Annotatable annotatable,
-      required bool isClassInstanceMember,
-      required bool createFileUriExpression});
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember});
 
   void buildOutlineNode(
       {required SourceLibraryBuilder libraryBuilder,
@@ -90,6 +90,7 @@
   AsyncMarker get asyncModifier => _fragment.asyncModifier;
 
   @override
+  // Coverage-ignore(suite): Not run.
   Uri get fileUri => _fragment.fileUri;
 
   @override
@@ -142,16 +143,16 @@
       required DeclarationBuilder? declarationBuilder,
       required SourcePropertyBuilder propertyBuilder,
       required Annotatable annotatable,
-      required bool isClassInstanceMember,
-      required bool createFileUriExpression}) {
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember}) {
     _encoding.buildOutlineExpressions(
-        classHierarchy,
-        libraryBuilder,
-        declarationBuilder,
-        createBodyBuilderContext(propertyBuilder),
-        annotatable,
-        isClassInstanceMember: isClassInstanceMember,
-        createFileUriExpression: createFileUriExpression);
+        classHierarchy: classHierarchy,
+        libraryBuilder: libraryBuilder,
+        declarationBuilder: declarationBuilder,
+        bodyBuilderContext: createBodyBuilderContext(propertyBuilder),
+        annotatable: annotatable,
+        annotatableFileUri: annotatableFileUri,
+        isClassInstanceMember: isClassInstanceMember);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fragment/getter/encoding.dart b/pkg/front_end/lib/src/fragment/getter/encoding.dart
index f5aa70b..427e47b 100644
--- a/pkg/front_end/lib/src/fragment/getter/encoding.dart
+++ b/pkg/front_end/lib/src/fragment/getter/encoding.dart
@@ -121,13 +121,13 @@
   void becomeNative(SourceLoader loader);
 
   void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      BodyBuilderContext bodyBuilderContext,
-      Annotatable annotatable,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression});
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required BodyBuilderContext bodyBuilderContext,
+      required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember});
 
   void buildOutlineNode(
       {required SourceLibraryBuilder libraryBuilder,
@@ -211,17 +211,20 @@
 
   @override
   void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      BodyBuilderContext bodyBuilderContext,
-      Annotatable annotatable,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression}) {
-    buildMetadataForOutlineExpressions(libraryBuilder, _fragment.enclosingScope,
-        bodyBuilderContext, annotatable, _fragment.metadata,
-        fileUri: _fragment.fileUri,
-        createFileUriExpression: createFileUriExpression);
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required BodyBuilderContext bodyBuilderContext,
+      required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember}) {
+    buildMetadataForOutlineExpressions(
+        libraryBuilder: libraryBuilder,
+        scope: _fragment.enclosingScope,
+        bodyBuilderContext: bodyBuilderContext,
+        annotatable: annotatable,
+        annotatableFileUri: annotatableFileUri,
+        metadata: _fragment.metadata);
     buildTypeParametersForOutlineExpressions(
         classHierarchy,
         libraryBuilder,
@@ -429,17 +432,20 @@
 
   @override
   void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      BodyBuilderContext bodyBuilderContext,
-      Annotatable annotatable,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression}) {
-    buildMetadataForOutlineExpressions(libraryBuilder, _fragment.enclosingScope,
-        bodyBuilderContext, annotatable, _fragment.metadata,
-        fileUri: _fragment.fileUri,
-        createFileUriExpression: createFileUriExpression);
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required BodyBuilderContext bodyBuilderContext,
+      required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember}) {
+    buildMetadataForOutlineExpressions(
+        libraryBuilder: libraryBuilder,
+        scope: _fragment.enclosingScope,
+        bodyBuilderContext: bodyBuilderContext,
+        annotatable: annotatable,
+        annotatableFileUri: annotatableFileUri,
+        metadata: _fragment.metadata);
 
     buildTypeParametersForOutlineExpressions(
         classHierarchy,
diff --git a/pkg/front_end/lib/src/fragment/method/declaration.dart b/pkg/front_end/lib/src/fragment/method/declaration.dart
index effc03f..cdc4d89 100644
--- a/pkg/front_end/lib/src/fragment/method/declaration.dart
+++ b/pkg/front_end/lib/src/fragment/method/declaration.dart
@@ -43,13 +43,13 @@
   Procedure? get readTarget;
 
   void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      SourceMethodBuilder methodBuilder,
-      Annotatable annotatable,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression});
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required SourceMethodBuilder methodBuilder,
+      required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember});
 
   void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
       NameScheme nameScheme, BuildNodesCallback f,
@@ -125,21 +125,21 @@
 
   @override
   void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      SourceMethodBuilder methodBuilder,
-      Annotatable annotatable,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression}) {
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required SourceMethodBuilder methodBuilder,
+      required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember}) {
     _encoding.buildOutlineExpressions(
-        classHierarchy,
-        libraryBuilder,
-        declarationBuilder,
-        createBodyBuilderContext(methodBuilder),
-        annotatable,
-        isClassInstanceMember: isClassInstanceMember,
-        createFileUriExpression: createFileUriExpression);
+        classHierarchy: classHierarchy,
+        libraryBuilder: libraryBuilder,
+        declarationBuilder: declarationBuilder,
+        bodyBuilderContext: createBodyBuilderContext(methodBuilder),
+        annotatable: annotatable,
+        annotatableFileUri: annotatableFileUri,
+        isClassInstanceMember: isClassInstanceMember);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fragment/method/encoding.dart b/pkg/front_end/lib/src/fragment/method/encoding.dart
index 7f2fdd9..ddeacaf 100644
--- a/pkg/front_end/lib/src/fragment/method/encoding.dart
+++ b/pkg/front_end/lib/src/fragment/method/encoding.dart
@@ -42,13 +42,13 @@
   void becomeNative(SourceLoader loader);
 
   void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      BodyBuilderContext bodyBuilderContext,
-      Annotatable annotatable,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression});
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required BodyBuilderContext bodyBuilderContext,
+      required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember});
 
   void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
       NameScheme nameScheme, BuildNodesCallback f,
@@ -145,17 +145,20 @@
 
   @override
   void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      BodyBuilderContext bodyBuilderContext,
-      Annotatable annotatable,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression}) {
-    buildMetadataForOutlineExpressions(libraryBuilder, _fragment.enclosingScope,
-        bodyBuilderContext, annotatable, _fragment.metadata,
-        fileUri: _fragment.fileUri,
-        createFileUriExpression: createFileUriExpression);
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required BodyBuilderContext bodyBuilderContext,
+      required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember}) {
+    buildMetadataForOutlineExpressions(
+        libraryBuilder: libraryBuilder,
+        scope: _fragment.enclosingScope,
+        bodyBuilderContext: bodyBuilderContext,
+        annotatable: annotatable,
+        annotatableFileUri: annotatableFileUri,
+        metadata: _fragment.metadata);
     buildTypeParametersForOutlineExpressions(classHierarchy, libraryBuilder,
         bodyBuilderContext, _fragment.declaredTypeParameters?.builders);
     buildFormalsForOutlineExpressions(
@@ -386,17 +389,20 @@
 
   @override
   void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      BodyBuilderContext bodyBuilderContext,
-      Annotatable annotatable,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression}) {
-    buildMetadataForOutlineExpressions(libraryBuilder, _fragment.enclosingScope,
-        bodyBuilderContext, annotatable, _fragment.metadata,
-        fileUri: _fragment.fileUri,
-        createFileUriExpression: createFileUriExpression);
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required BodyBuilderContext bodyBuilderContext,
+      required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember}) {
+    buildMetadataForOutlineExpressions(
+        libraryBuilder: libraryBuilder,
+        scope: _fragment.enclosingScope,
+        bodyBuilderContext: bodyBuilderContext,
+        annotatable: annotatable,
+        annotatableFileUri: annotatableFileUri,
+        metadata: _fragment.metadata);
 
     buildTypeParametersForOutlineExpressions(classHierarchy, libraryBuilder,
         bodyBuilderContext, _fragment.declaredTypeParameters?.builders);
diff --git a/pkg/front_end/lib/src/fragment/setter/declaration.dart b/pkg/front_end/lib/src/fragment/setter/declaration.dart
index dd2dbae..1dbd655 100644
--- a/pkg/front_end/lib/src/fragment/setter/declaration.dart
+++ b/pkg/front_end/lib/src/fragment/setter/declaration.dart
@@ -44,8 +44,8 @@
       required DeclarationBuilder? declarationBuilder,
       required SourcePropertyBuilder propertyBuilder,
       required Annotatable annotatable,
-      required bool isClassInstanceMember,
-      required bool createFileUriExpression});
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember});
 
   void buildOutlineNode(
       {required SourceLibraryBuilder libraryBuilder,
@@ -90,6 +90,7 @@
   AsyncMarker get asyncModifier => _fragment.asyncModifier;
 
   @override
+  // Coverage-ignore(suite): Not run.
   Uri get fileUri => _fragment.fileUri;
 
   @override
@@ -146,16 +147,16 @@
       required DeclarationBuilder? declarationBuilder,
       required SourcePropertyBuilder propertyBuilder,
       required Annotatable annotatable,
-      required bool isClassInstanceMember,
-      required bool createFileUriExpression}) {
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember}) {
     _encoding.buildOutlineExpressions(
-        classHierarchy,
-        libraryBuilder,
-        declarationBuilder,
-        createBodyBuilderContext(propertyBuilder),
-        annotatable,
-        isClassInstanceMember: isClassInstanceMember,
-        createFileUriExpression: createFileUriExpression);
+        classHierarchy: classHierarchy,
+        libraryBuilder: libraryBuilder,
+        declarationBuilder: declarationBuilder,
+        bodyBuilderContext: createBodyBuilderContext(propertyBuilder),
+        annotatable: annotatable,
+        annotatableFileUri: annotatableFileUri,
+        isClassInstanceMember: isClassInstanceMember);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fragment/setter/encoding.dart b/pkg/front_end/lib/src/fragment/setter/encoding.dart
index f7f5e2b..a5b3fca 100644
--- a/pkg/front_end/lib/src/fragment/setter/encoding.dart
+++ b/pkg/front_end/lib/src/fragment/setter/encoding.dart
@@ -139,13 +139,13 @@
   void becomeNative(SourceLoader loader);
 
   void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      BodyBuilderContext bodyBuilderContext,
-      Annotatable annotatable,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression});
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required BodyBuilderContext bodyBuilderContext,
+      required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember});
 
   void buildOutlineNode(
       {required SourceLibraryBuilder libraryBuilder,
@@ -212,17 +212,20 @@
 
   @override
   void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      BodyBuilderContext bodyBuilderContext,
-      Annotatable annotatable,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression}) {
-    buildMetadataForOutlineExpressions(libraryBuilder, _fragment.enclosingScope,
-        bodyBuilderContext, annotatable, _fragment.metadata,
-        fileUri: _fragment.fileUri,
-        createFileUriExpression: createFileUriExpression);
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required BodyBuilderContext bodyBuilderContext,
+      required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember}) {
+    buildMetadataForOutlineExpressions(
+        libraryBuilder: libraryBuilder,
+        scope: _fragment.enclosingScope,
+        bodyBuilderContext: bodyBuilderContext,
+        annotatable: annotatable,
+        annotatableFileUri: annotatableFileUri,
+        metadata: _fragment.metadata);
 
     buildTypeParametersForOutlineExpressions(
         classHierarchy,
@@ -437,17 +440,20 @@
 
   @override
   void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      BodyBuilderContext bodyBuilderContext,
-      Annotatable annotatable,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression}) {
-    buildMetadataForOutlineExpressions(libraryBuilder, _fragment.enclosingScope,
-        bodyBuilderContext, annotatable, _fragment.metadata,
-        fileUri: _fragment.fileUri,
-        createFileUriExpression: createFileUriExpression);
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required BodyBuilderContext bodyBuilderContext,
+      required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember}) {
+    buildMetadataForOutlineExpressions(
+        libraryBuilder: libraryBuilder,
+        scope: _fragment.enclosingScope,
+        bodyBuilderContext: bodyBuilderContext,
+        annotatable: annotatable,
+        annotatableFileUri: annotatableFileUri,
+        metadata: _fragment.metadata);
 
     buildTypeParametersForOutlineExpressions(
         classHierarchy,
diff --git a/pkg/front_end/lib/src/fragment/util.dart b/pkg/front_end/lib/src/fragment/util.dart
index f22c0a7..81374c9 100644
--- a/pkg/front_end/lib/src/fragment/util.dart
+++ b/pkg/front_end/lib/src/fragment/util.dart
@@ -46,16 +46,19 @@
 }
 
 void buildMetadataForOutlineExpressions(
-    SourceLibraryBuilder libraryBuilder,
-    LookupScope parentScope,
-    BodyBuilderContext bodyBuilderContext,
-    Annotatable annotatable,
-    List<MetadataBuilder>? metadata,
-    {required Uri fileUri,
-    required bool createFileUriExpression}) {
-  MetadataBuilder.buildAnnotations(annotatable, metadata, bodyBuilderContext,
-      libraryBuilder, fileUri, parentScope,
-      createFileUriExpression: createFileUriExpression);
+    {required SourceLibraryBuilder libraryBuilder,
+    required LookupScope scope,
+    required BodyBuilderContext bodyBuilderContext,
+    required Annotatable annotatable,
+    required Uri annotatableFileUri,
+    required List<MetadataBuilder>? metadata}) {
+  MetadataBuilder.buildAnnotations(
+      annotatable: annotatable,
+      annotatableFileUri: annotatableFileUri,
+      metadata: metadata,
+      bodyBuilderContext: bodyBuilderContext,
+      libraryBuilder: libraryBuilder,
+      scope: scope);
 }
 
 void buildTypeParametersForOutlineExpressions(
@@ -97,212 +100,6 @@
       scope: scope, buildDefaultValue: isClassInstanceMember);
 }
 
-/// Common interface for fragments that can declare a field.
-abstract class FieldDeclaration {
-  FieldQuality get fieldQuality;
-
-  GetterQuality get getterQuality;
-
-  SetterQuality get setterQuality;
-
-  /// The metadata declared on this fragment.
-  List<MetadataBuilder>? get metadata;
-
-  /// Builds the core AST structures for this field declaration as needed for
-  /// the outline.
-  void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
-      NameScheme nameScheme, BuildNodesCallback f, FieldReference references,
-      {required List<TypeParameter>? classTypeParameters});
-
-  void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      List<Annotatable> annotatables,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression});
-
-  int computeDefaultTypes(ComputeDefaultTypeContext context);
-
-  void checkTypes(SourceLibraryBuilder libraryBuilder,
-      TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder);
-
-  /// Checks the variance of type parameters [sourceClassBuilder] used in the
-  /// type of this field declaration.
-  void checkVariance(
-      SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment);
-
-  /// The references to the members from this field declaration that are
-  /// accessible in exports through the name of the builder.
-  Iterable<Reference> getExportedMemberReferences(FieldReference references);
-
-  /// Return `true` if the declaration introduces a setter.
-  bool get hasSetter;
-
-  /// Return `true` if the declaration has an initializer.
-  bool get hasInitializer;
-
-  /// Return `true` if the declaration is final.
-  bool get isFinal;
-
-  /// Return `true` if the declaration is late.
-  bool get isLate;
-
-  /// Return `true` if the declaration is in instance field declared in an
-  /// extension type.
-  bool get isExtensionTypeDeclaredInstanceField;
-
-  /// Returns `true` if this field is declared by an enum element.
-  bool get isEnumElement;
-
-  /// The [ClassMember]s for the getter introduced by this field declaration.
-  List<ClassMember> get localMembers;
-
-  /// The [ClassMember]s for the setter introduced by this field declaration,
-  /// if any.
-  List<ClassMember> get localSetters;
-
-  /// The [Member] uses as the target for reading from this field declaration.
-  Member get readTarget;
-
-  /// The [Member] uses as the target for writing to this field declaration, or
-  /// `null` if this field declaration has no setter.
-  Member? get writeTarget;
-
-  /// The [DartType] of this field declaration.
-  abstract DartType fieldType;
-
-  /// Creates the [Initializer] for the invalid initialization of this field.
-  ///
-  /// This is only used for instance fields.
-  Initializer buildErroneousInitializer(Expression effect, Expression value,
-      {required int fileOffset});
-
-  /// Creates the AST node for this field as the default initializer.
-  ///
-  /// This is only used for instance fields.
-  void buildImplicitDefaultValue();
-
-  /// Creates the [Initializer] for the implicit initialization of this field
-  /// in a constructor.
-  ///
-  /// This is only used for instance fields.
-  Initializer buildImplicitInitializer();
-
-  /// Builds the [Initializer]s for each field used to encode this field
-  /// using the [fileOffset] for the created nodes and [value] as the initial
-  /// field value.
-  ///
-  /// This is only used for instance fields.
-  List<Initializer> buildInitializer(int fileOffset, Expression value,
-      {required bool isSynthetic});
-
-  /// Ensures that the type of this field declaration has been computed.
-  void ensureTypes(
-      ClassMembersBuilder membersBuilder,
-      Set<ClassMember>? getterOverrideDependencies,
-      Set<ClassMember>? setterOverrideDependencies);
-
-  /// Infers the type of this field declaration.
-  DartType inferType(ClassHierarchyBase hierarchy);
-
-  shared.Expression? get initializerExpression;
-}
-
-mixin FieldDeclarationMixin
-    implements FieldDeclaration, Inferable, InferredTypeListener {
-  Uri get fileUri;
-
-  int get nameOffset;
-
-  SourcePropertyBuilder get builder;
-
-  bool get isConst;
-
-  /// The [TypeBuilder] for the declared type of this field declaration.
-  TypeBuilder get type;
-
-  void _setCovariantByClassInternal();
-
-  abstract DartType _fieldTypeInternal;
-
-  @override
-  void onInferredType(DartType type) {
-    fieldType = type;
-  }
-
-  @override
-  void inferTypes(ClassHierarchyBase hierarchy) {
-    inferType(hierarchy);
-  }
-
-  @override
-  DartType inferType(ClassHierarchyBase hierarchy) {
-    if (fieldType is! InferredType) {
-      // We have already inferred a type.
-      return fieldType;
-    }
-
-    return builder.libraryBuilder.loader
-        .withUriForCrashReporting(fileUri, nameOffset, () {
-      InferredType implicitFieldType = fieldType as InferredType;
-      DartType inferredType = implicitFieldType.computeType(hierarchy);
-      if (fieldType is InferredType) {
-        // `fieldType` may have changed if a circularity was detected when
-        // [inferredType] was computed.
-        type.registerInferredType(inferredType);
-
-        // TODO(johnniwinther): Isn't this handled in the [fieldType] setter?
-        IncludesTypeParametersNonCovariantly? needsCheckVisitor;
-        DeclarationBuilder? declarationBuilder = builder.declarationBuilder;
-        if (declarationBuilder is ClassBuilder) {
-          Class enclosingClass = declarationBuilder.cls;
-          if (enclosingClass.typeParameters.isNotEmpty) {
-            needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
-                enclosingClass.typeParameters,
-                // We are checking the field type as if it is the type of the
-                // parameter of the implicit setter and this is a contravariant
-                // position.
-                initialVariance: Variance.contravariant);
-          }
-        }
-        if (needsCheckVisitor != null) {
-          if (fieldType.accept(needsCheckVisitor)) {
-            _setCovariantByClassInternal();
-          }
-        }
-      }
-      return fieldType;
-    });
-  }
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  DartType get fieldType => _fieldTypeInternal;
-
-  @override
-  void set fieldType(DartType value) {
-    _fieldTypeInternal = value;
-    DeclarationBuilder? declarationBuilder = builder.declarationBuilder;
-    // TODO(johnniwinther): Should this be `hasSetter`?
-    if (!isFinal && !isConst && declarationBuilder is ClassBuilder) {
-      Class enclosingClass = declarationBuilder.cls;
-      if (enclosingClass.typeParameters.isNotEmpty) {
-        IncludesTypeParametersNonCovariantly needsCheckVisitor =
-            new IncludesTypeParametersNonCovariantly(
-                enclosingClass.typeParameters,
-                // We are checking the field type as if it is the type of the
-                // parameter of the implicit setter and this is a contravariant
-                // position.
-                initialVariance: Variance.contravariant);
-        if (value.accept(needsCheckVisitor)) {
-          _setCovariantByClassInternal();
-        }
-      }
-    }
-  }
-}
-
 sealed class PropertyEncodingStrategy {
   factory PropertyEncodingStrategy(DeclarationBuilder? declarationBuilder,
       {required bool isInstanceMember}) {
diff --git a/pkg/front_end/lib/src/kernel/record_use.dart b/pkg/front_end/lib/src/kernel/record_use.dart
index db4917a..d2866c3 100644
--- a/pkg/front_end/lib/src/kernel/record_use.dart
+++ b/pkg/front_end/lib/src/kernel/record_use.dart
@@ -12,6 +12,7 @@
 import '../base/messages.dart' show messageRecordUseCannotBePlacedHere;
 import 'constant_evaluator.dart' show ErrorReporter;
 
+// Coverage-ignore(suite): Not run.
 /// Get all of the `@RecordUse` annotations from `package:meta`
 /// that are attached to the specified [node].
 Iterable<InstanceConstant> findRecordUseAnnotation(Annotatable node) =>
@@ -19,15 +20,18 @@
         .whereType<ConstantExpression>()
         .map((expression) => expression.constant)
         .whereType<InstanceConstant>()
-        .where((instance) => isRecordUse(instance.classNode))
-        .toList(growable: false);
+        .where((instance) => isRecordUse(instance.classNode));
+
+// Coverage-ignore(suite): Not run.
+bool hasRecordUseAnnotation(Annotatable node) =>
+    findRecordUseAnnotation(node).isNotEmpty;
 
 // Coverage-ignore(suite): Not run.
 final Uri _metaLibraryUri = new Uri(scheme: 'package', path: 'meta/meta.dart');
 
+// Coverage-ignore(suite): Not run.
 bool isRecordUse(Class cls) =>
     cls.name == 'RecordUse' &&
-    // Coverage-ignore(suite): Not run.
     cls.enclosingLibrary.importUri == _metaLibraryUri;
 
 // Coverage-ignore(suite): Not run.
diff --git a/pkg/front_end/lib/src/kernel/utils.dart b/pkg/front_end/lib/src/kernel/utils.dart
index 0211286..928a213 100644
--- a/pkg/front_end/lib/src/kernel/utils.dart
+++ b/pkg/front_end/lib/src/kernel/utils.dart
@@ -259,7 +259,8 @@
 final Identifier dummyIdentifier = new SimpleIdentifier(dummyToken);
 final CombinatorBuilder dummyCombinator =
     new CombinatorBuilder(false, {}, -1, dummyUri);
-final MetadataBuilder dummyMetadataBuilder = new MetadataBuilder(dummyToken);
+final MetadataBuilder dummyMetadataBuilder =
+    new MetadataBuilder(dummyToken, dummyUri);
 final TypeBuilder dummyTypeBuilder =
     new FixedTypeBuilderImpl(dummyDartType, dummyUri, -1);
 final FormalParameterBuilder dummyFormalParameterBuilder =
diff --git a/pkg/front_end/lib/src/source/builder_factory.dart b/pkg/front_end/lib/src/source/builder_factory.dart
index 681bb16..d4e1d1f 100644
--- a/pkg/front_end/lib/src/source/builder_factory.dart
+++ b/pkg/front_end/lib/src/source/builder_factory.dart
@@ -536,7 +536,7 @@
     for (int index = 0; index < oldParameterBuilders.length; index++) {
       NominalParameterBuilder oldVariable = oldParameterBuilders[index];
       TypeParameterFragment? oldFragment = oldParameterFragments?[index];
-      Uri? fileUri = oldFragment?.fileUri ?? oldVariable.fileUri;
+      Uri fileUri = (oldFragment?.fileUri ?? oldVariable.fileUri)!;
       int fileOffset = oldFragment?.nameOffset ?? oldVariable.fileOffset;
       SourceNominalParameterBuilder newVariable =
           new SourceNominalParameterBuilder(
diff --git a/pkg/front_end/lib/src/source/outline_builder.dart b/pkg/front_end/lib/src/source/outline_builder.dart
index ed6c89a..5a96dd4 100644
--- a/pkg/front_end/lib/src/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/source/outline_builder.dart
@@ -598,7 +598,7 @@
     Object? sentinel = pop(); // prefix or constructor
     push(sentinel is ParserRecovery
         ? sentinel
-        : new MetadataBuilder(beginToken));
+        : new MetadataBuilder(beginToken, _compilationUnit.fileUri));
   }
 
   @override
diff --git a/pkg/front_end/lib/src/source/source_class_builder.dart b/pkg/front_end/lib/src/source/source_class_builder.dart
index 15f15a6..bdcd4d8 100644
--- a/pkg/front_end/lib/src/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/source/source_class_builder.dart
@@ -513,6 +513,7 @@
     BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
     _introductory.buildOutlineExpressions(
         annotatable: cls,
+        annotatableFileUri: cls.fileUri,
         bodyBuilderContext: bodyBuilderContext,
         libraryBuilder: libraryBuilder,
         classHierarchy: classHierarchy,
@@ -520,6 +521,7 @@
     for (ClassDeclaration augmentation in _augmentations) {
       augmentation.buildOutlineExpressions(
           annotatable: cls,
+          annotatableFileUri: cls.fileUri,
           bodyBuilderContext: bodyBuilderContext,
           classHierarchy: classHierarchy,
           libraryBuilder: libraryBuilder,
diff --git a/pkg/front_end/lib/src/source/source_compilation_unit.dart b/pkg/front_end/lib/src/source/source_compilation_unit.dart
index d377ce6..63c3ba5 100644
--- a/pkg/front_end/lib/src/source/source_compilation_unit.dart
+++ b/pkg/front_end/lib/src/source/source_compilation_unit.dart
@@ -878,11 +878,16 @@
 
   @override
   void buildOutlineExpressions(
-      Annotatable annotatable, BodyBuilderContext bodyBuilderContext,
-      {required bool createFileUriExpression}) {
-    MetadataBuilder.buildAnnotations(annotatable, metadata, bodyBuilderContext,
-        libraryBuilder, fileUri, compilationUnitScope,
-        createFileUriExpression: createFileUriExpression);
+      {required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required BodyBuilderContext bodyBuilderContext}) {
+    MetadataBuilder.buildAnnotations(
+        annotatable: annotatable,
+        annotatableFileUri: annotatableFileUri,
+        metadata: metadata,
+        bodyBuilderContext: bodyBuilderContext,
+        libraryBuilder: libraryBuilder,
+        scope: compilationUnitScope);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/source/source_constructor_builder.dart b/pkg/front_end/lib/src/source/source_constructor_builder.dart
index 1dd6ca6..5d25ca9 100644
--- a/pkg/front_end/lib/src/source/source_constructor_builder.dart
+++ b/pkg/front_end/lib/src/source/source_constructor_builder.dart
@@ -560,22 +560,20 @@
     if (!hasBuiltOutlineExpressions) {
       _introductory.buildOutlineExpressions(
           annotatables: annotatables,
+          annotatablesFileUri: invokeTarget.fileUri,
           libraryBuilder: libraryBuilder,
           declarationBuilder: declarationBuilder,
           constructorBuilder: this,
           classHierarchy: classHierarchy,
-          createFileUriExpression:
-              _invokeTarget.fileUri != _introductory.fileUri,
           delayedDefaultValueCloners: delayedDefaultValueCloners);
       for (ConstructorDeclaration augmentation in _augmentations) {
         augmentation.buildOutlineExpressions(
             annotatables: annotatables,
+            annotatablesFileUri: invokeTarget.fileUri,
             libraryBuilder: libraryBuilder,
             declarationBuilder: declarationBuilder,
             constructorBuilder: this,
             classHierarchy: classHierarchy,
-            createFileUriExpression:
-                _invokeTarget.fileUri != augmentation.fileUri,
             delayedDefaultValueCloners: delayedDefaultValueCloners);
       }
       hasBuiltOutlineExpressions = true;
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 4423bb7..5dcf9b5 100644
--- a/pkg/front_end/lib/src/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/source/source_enum_builder.dart
@@ -30,6 +30,7 @@
 import '../builder/nullability_builder.dart';
 import '../builder/type_builder.dart';
 import '../fragment/constructor/declaration.dart';
+import '../fragment/field/declaration.dart';
 import '../fragment/fragment.dart';
 import '../fragment/method/declaration.dart';
 import '../kernel/body_builder_context.dart';
@@ -477,13 +478,13 @@
 
   @override
   void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      SourceMethodBuilder methodBuilder,
-      Annotatable annotatable,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression}) {
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required SourceMethodBuilder methodBuilder,
+      required Annotatable annotatable,
+      required Uri annotatableFileUri,
+      required bool isClassInstanceMember}) {
     Name toStringName =
         new Name(_enumToStringName, classHierarchy.coreTypes.coreLibrary);
     Member? superToString = _enumBuilder.cls.superclass != null
@@ -641,12 +642,12 @@
 
   @override
   void buildOutlineExpressions(
-      ClassHierarchy classHierarchy,
-      SourceLibraryBuilder libraryBuilder,
-      DeclarationBuilder? declarationBuilder,
-      List<Annotatable> annotatables,
-      {required bool isClassInstanceMember,
-      required bool createFileUriExpression}) {
+      {required ClassHierarchy classHierarchy,
+      required SourceLibraryBuilder libraryBuilder,
+      required DeclarationBuilder? declarationBuilder,
+      required List<Annotatable> annotatables,
+      required Uri annotatablesFileUri,
+      required bool isClassInstanceMember}) {
     List<Expression> values = <Expression>[];
     for (EnumElementFragment enumElement in _sourceEnumBuilder._enumElements) {
       enumElement.declaration.inferType(classHierarchy);
diff --git a/pkg/front_end/lib/src/source/source_extension_builder.dart b/pkg/front_end/lib/src/source/source_extension_builder.dart
index 1b47c6d..80f540c 100644
--- a/pkg/front_end/lib/src/source/source_extension_builder.dart
+++ b/pkg/front_end/lib/src/source/source_extension_builder.dart
@@ -160,12 +160,12 @@
   void _buildOutlineExpressionsForFragment(ExtensionFragment fragment,
       ClassHierarchy classHierarchy, BodyBuilderContext bodyBuilderContext) {
     MetadataBuilder.buildAnnotations(
-        extension,
-        fragment.metadata,
-        bodyBuilderContext,
-        libraryBuilder,
-        fragment.fileUri,
-        fragment.enclosingScope);
+        annotatable: extension,
+        annotatableFileUri: extension.fileUri,
+        metadata: fragment.metadata,
+        bodyBuilderContext: bodyBuilderContext,
+        libraryBuilder: libraryBuilder,
+        scope: fragment.enclosingScope);
   }
 
   void buildOutlineExpressions(ClassHierarchy classHierarchy,
diff --git a/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart b/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
index 1324f41..c82d767 100644
--- a/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
@@ -703,18 +703,19 @@
 
   void buildOutlineExpressions(ClassHierarchy classHierarchy,
       List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
+    BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
     MetadataBuilder.buildAnnotations(
-        extensionTypeDeclaration,
-        _introductory.metadata,
-        createBodyBuilderContext(),
-        libraryBuilder,
-        _introductory.fileUri,
-        _introductory.enclosingScope);
+        annotatable: extensionTypeDeclaration,
+        annotatableFileUri: extensionTypeDeclaration.fileUri,
+        metadata: _introductory.metadata,
+        bodyBuilderContext: bodyBuilderContext,
+        libraryBuilder: libraryBuilder,
+        scope: _introductory.enclosingScope);
 
     if (_introductory.typeParameters != null) {
       for (int i = 0; i < _introductory.typeParameters!.length; i++) {
         _introductory.typeParameters![i].builder.buildOutlineExpressions(
-            libraryBuilder, createBodyBuilderContext(), classHierarchy);
+            libraryBuilder, bodyBuilderContext, classHierarchy);
       }
     }
 
diff --git a/pkg/front_end/lib/src/source/source_factory_builder.dart b/pkg/front_end/lib/src/source/source_factory_builder.dart
index b3634f7..ac99bec 100644
--- a/pkg/front_end/lib/src/source/source_factory_builder.dart
+++ b/pkg/front_end/lib/src/source/source_factory_builder.dart
@@ -297,16 +297,16 @@
         factoryBuilder: this,
         classHierarchy: classHierarchy,
         delayedDefaultValueCloners: delayedDefaultValueCloners,
-        createFileUriExpression:
-            _introductory.fileUri != _lastDeclaration.fileUri);
+        annotatables: annotatables,
+        annotatablesFileUri: _procedure.fileUri);
     for (FactoryDeclaration augmentation in _augmentations) {
       augmentation.buildOutlineExpressions(
           libraryBuilder: libraryBuilder,
           factoryBuilder: this,
           classHierarchy: classHierarchy,
           delayedDefaultValueCloners: delayedDefaultValueCloners,
-          createFileUriExpression:
-              augmentation.fileUri != _lastDeclaration.fileUri);
+          annotatables: annotatables,
+          annotatablesFileUri: _procedure.fileUri);
     }
   }
 
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 6857fca..4347ef3 100644
--- a/pkg/front_end/lib/src/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/source/source_library_builder.dart
@@ -843,8 +843,10 @@
 
   void buildOutlineExpressions(ClassHierarchy classHierarchy,
       List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
-    compilationUnit.buildOutlineExpressions(library, createBodyBuilderContext(),
-        createFileUriExpression: false);
+    compilationUnit.buildOutlineExpressions(
+        annotatable: library,
+        annotatableFileUri: library.fileUri,
+        bodyBuilderContext: createBodyBuilderContext());
 
     Iterator<Builder> iterator = localMembersIterator;
     while (iterator.moveNext()) {
diff --git a/pkg/front_end/lib/src/source/source_method_builder.dart b/pkg/front_end/lib/src/source/source_method_builder.dart
index 30afc57..109272c 100644
--- a/pkg/front_end/lib/src/source/source_method_builder.dart
+++ b/pkg/front_end/lib/src/source/source_method_builder.dart
@@ -146,17 +146,23 @@
   void buildOutlineExpressions(ClassHierarchy classHierarchy,
       List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
     if (!hasBuiltOutlineExpressions) {
-      _introductory.buildOutlineExpressions(classHierarchy, libraryBuilder,
-          declarationBuilder, this, _invokeTarget,
-          isClassInstanceMember: isClassInstanceMember,
-          createFileUriExpression:
-              _invokeTarget.fileUri != _introductory.fileUri);
+      _introductory.buildOutlineExpressions(
+          classHierarchy: classHierarchy,
+          libraryBuilder: libraryBuilder,
+          declarationBuilder: declarationBuilder,
+          methodBuilder: this,
+          annotatable: _invokeTarget,
+          annotatableFileUri: _invokeTarget.fileUri,
+          isClassInstanceMember: isClassInstanceMember);
       for (MethodDeclaration augmentation in _augmentations) {
-        augmentation.buildOutlineExpressions(classHierarchy, libraryBuilder,
-            declarationBuilder, this, _invokeTarget,
-            isClassInstanceMember: isClassInstanceMember,
-            createFileUriExpression:
-                _invokeTarget.fileUri != augmentation.fileUri);
+        augmentation.buildOutlineExpressions(
+            classHierarchy: classHierarchy,
+            libraryBuilder: libraryBuilder,
+            declarationBuilder: declarationBuilder,
+            methodBuilder: this,
+            annotatable: _invokeTarget,
+            annotatableFileUri: _invokeTarget.fileUri,
+            isClassInstanceMember: isClassInstanceMember);
       }
       hasBuiltOutlineExpressions = true;
     }
diff --git a/pkg/front_end/lib/src/source/source_property_builder.dart b/pkg/front_end/lib/src/source/source_property_builder.dart
index e44cc21..61306dd 100644
--- a/pkg/front_end/lib/src/source/source_property_builder.dart
+++ b/pkg/front_end/lib/src/source/source_property_builder.dart
@@ -15,7 +15,7 @@
 import '../builder/declaration_builders.dart';
 import '../builder/metadata_builder.dart';
 import '../builder/property_builder.dart';
-import '../fragment/fragment.dart';
+import '../fragment/field/declaration.dart';
 import '../fragment/getter/declaration.dart';
 import '../fragment/setter/declaration.dart';
 import '../kernel/hierarchy/class_member.dart';
@@ -220,25 +220,24 @@
       List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
     if (!hasBuiltOutlineExpressions) {
       _introductoryField?.buildOutlineExpressions(
-          classHierarchy,
-          libraryBuilder,
-          declarationBuilder,
-          [
+          classHierarchy: classHierarchy,
+          libraryBuilder: libraryBuilder,
+          declarationBuilder: declarationBuilder,
+          annotatables: [
             readTarget as Annotatable,
             if (writeTarget != null && readTarget != writeTarget)
               writeTarget as Annotatable
           ],
-          isClassInstanceMember: isClassInstanceMember,
-          createFileUriExpression: false);
+          annotatablesFileUri: readTarget!.fileUri,
+          isClassInstanceMember: isClassInstanceMember);
       _introductoryGetable?.buildOutlineExpressions(
           classHierarchy: classHierarchy,
           libraryBuilder: libraryBuilder,
           declarationBuilder: declarationBuilder,
           propertyBuilder: this,
           annotatable: readTarget as Annotatable,
-          isClassInstanceMember: isClassInstanceMember,
-          createFileUriExpression:
-              _introductoryGetable?.fileUri != _lastGetable?.fileUri);
+          annotatableFileUri: readTarget!.fileUri,
+          isClassInstanceMember: isClassInstanceMember);
       List<GetterDeclaration>? getterAugmentations = _getterAugmentations;
       if (getterAugmentations != null) {
         for (GetterDeclaration augmentation in getterAugmentations) {
@@ -248,9 +247,8 @@
               declarationBuilder: declarationBuilder,
               propertyBuilder: this,
               annotatable: readTarget as Annotatable,
-              isClassInstanceMember: isClassInstanceMember,
-              createFileUriExpression:
-                  augmentation.fileUri != _lastGetable?.fileUri);
+              annotatableFileUri: readTarget!.fileUri,
+              isClassInstanceMember: isClassInstanceMember);
         }
       }
       _introductorySetable?.buildOutlineExpressions(
@@ -259,9 +257,8 @@
           declarationBuilder: declarationBuilder,
           propertyBuilder: this,
           annotatable: writeTarget as Annotatable,
-          isClassInstanceMember: isClassInstanceMember,
-          createFileUriExpression:
-              _introductorySetable?.fileUri != _lastSetable?.fileUri);
+          annotatableFileUri: writeTarget!.fileUri,
+          isClassInstanceMember: isClassInstanceMember);
       List<SetterDeclaration>? setterAugmentations = _setterAugmentations;
       if (setterAugmentations != null) {
         for (SetterDeclaration augmentation in setterAugmentations) {
@@ -271,9 +268,8 @@
               declarationBuilder: declarationBuilder,
               propertyBuilder: this,
               annotatable: writeTarget as Annotatable,
-              isClassInstanceMember: isClassInstanceMember,
-              createFileUriExpression:
-                  augmentation.fileUri != _lastSetable?.fileUri);
+              annotatableFileUri: writeTarget!.fileUri,
+              isClassInstanceMember: isClassInstanceMember);
         }
       }
       hasBuiltOutlineExpressions = true;
diff --git a/pkg/front_end/lib/src/source/source_type_alias_builder.dart b/pkg/front_end/lib/src/source/source_type_alias_builder.dart
index 62d9ede..04df66f 100644
--- a/pkg/front_end/lib/src/source/source_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/source/source_type_alias_builder.dart
@@ -368,17 +368,18 @@
 
   void buildOutlineExpressions(ClassHierarchy classHierarchy,
       List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
+    BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
     MetadataBuilder.buildAnnotations(
-        typedef,
-        _introductory.metadata,
-        createBodyBuilderContext(),
-        libraryBuilder,
-        fileUri,
-        _introductory.enclosingScope);
+        annotatable: typedef,
+        annotatableFileUri: typedef.fileUri,
+        metadata: _introductory.metadata,
+        bodyBuilderContext: bodyBuilderContext,
+        libraryBuilder: libraryBuilder,
+        scope: _introductory.enclosingScope);
     if (typeParameters != null) {
       for (int i = 0; i < typeParameters!.length; i++) {
         typeParameters![i].buildOutlineExpressions(
-            libraryBuilder, createBodyBuilderContext(), classHierarchy);
+            libraryBuilder, bodyBuilderContext, classHierarchy);
       }
     }
     _tearOffDependencies?.forEach((Procedure tearOff, Member target) {
diff --git a/pkg/front_end/lib/src/source/source_type_parameter_builder.dart b/pkg/front_end/lib/src/source/source_type_parameter_builder.dart
index 5ff1dec..0f3a6e4 100644
--- a/pkg/front_end/lib/src/source/source_type_parameter_builder.dart
+++ b/pkg/front_end/lib/src/source/source_type_parameter_builder.dart
@@ -49,7 +49,7 @@
   bool get isWildcard => _declaration.isWildcard;
 
   @override
-  Uri? get fileUri => _declaration.fileUri;
+  Uri get fileUri => _declaration.fileUri;
 
   void buildOutlineExpressions(SourceLibraryBuilder libraryBuilder,
       BodyBuilderContext bodyBuilderContext, ClassHierarchy classHierarchy) {
@@ -94,14 +94,14 @@
 
   int get fileOffset;
 
-  Uri? get fileUri;
+  Uri get fileUri;
 
   void buildOutlineExpressions(
       {required SourceLibraryBuilder libraryBuilder,
       required BodyBuilderContext bodyBuilderContext,
       required ClassHierarchy classHierarchy,
       required TypeParameter parameter,
-      required Uri? annotatableFileUri});
+      required Uri annotatableFileUri});
 }
 
 class RegularNominalParameterDeclaration
@@ -114,7 +114,7 @@
   int get fileOffset => _fragment.nameOffset;
 
   @override
-  Uri? get fileUri => _fragment.fileUri;
+  Uri get fileUri => _fragment.fileUri;
 
   @override
   bool get isWildcard => _fragment.isWildcard;
@@ -131,15 +131,14 @@
       required BodyBuilderContext bodyBuilderContext,
       required ClassHierarchy classHierarchy,
       required TypeParameter parameter,
-      required Uri? annotatableFileUri}) {
+      required Uri annotatableFileUri}) {
     MetadataBuilder.buildAnnotations(
-        parameter,
-        _fragment.metadata,
-        bodyBuilderContext,
-        libraryBuilder,
-        _fragment.fileUri,
-        _fragment.typeParameterScope,
-        createFileUriExpression: _fragment.fileUri != annotatableFileUri);
+        annotatable: parameter,
+        annotatableFileUri: annotatableFileUri,
+        metadata: _fragment.metadata,
+        bodyBuilderContext: bodyBuilderContext,
+        libraryBuilder: libraryBuilder,
+        scope: _fragment.typeParameterScope);
   }
 }
 
@@ -157,7 +156,7 @@
   final bool isWildcard;
 
   @override
-  final Uri? fileUri;
+  final Uri fileUri;
 
   DirectNominalParameterDeclaration(
       {required this.name,
@@ -184,7 +183,7 @@
   final int fileOffset;
 
   @override
-  final Uri? fileUri;
+  final Uri fileUri;
 
   @override
   final TypeParameterKind kind;
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 50a0d14..b1b0e07 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
@@ -26,6 +26,7 @@
 import '../builder/type_builder.dart';
 import '../fragment/constructor/declaration.dart';
 import '../fragment/factory/declaration.dart';
+import '../fragment/field/declaration.dart';
 import '../fragment/fragment.dart';
 import '../fragment/getter/declaration.dart';
 import '../fragment/method/declaration.dart';
@@ -1700,7 +1701,7 @@
               context: [
                 templateTypeParameterDuplicatedNameCause
                     .withArguments(tv.name)
-                    .withLocation(existing.fileUri!, existing.fileOffset,
+                    .withLocation(existing.fileUri, existing.fileOffset,
                         existing.name.length)
               ]);
         }
diff --git a/pkg/front_end/test/coverage_suite_expected.dart b/pkg/front_end/test/coverage_suite_expected.dart
index e3a2fc1..012277a 100644
--- a/pkg/front_end/test/coverage_suite_expected.dart
+++ b/pkg/front_end/test/coverage_suite_expected.dart
@@ -335,7 +335,7 @@
   ),
   // 100.0%.
   "package:front_end/src/builder/metadata_builder.dart": (
-    hitCount: 37,
+    hitCount: 41,
     missCount: 0,
   ),
   // 100.0%.
@@ -490,7 +490,7 @@
   ),
   // 100.0%.
   "package:front_end/src/fragment/class/declaration.dart": (
-    hitCount: 178,
+    hitCount: 170,
     missCount: 0,
   ),
   // 100.0%.
@@ -505,7 +505,7 @@
   ),
   // 100.0%.
   "package:front_end/src/fragment/constructor/declaration.dart": (
-    hitCount: 677,
+    hitCount: 673,
     missCount: 0,
   ),
   // 100.0%.
@@ -520,7 +520,7 @@
   ),
   // 100.0%.
   "package:front_end/src/fragment/enum_element.dart": (
-    hitCount: 283,
+    hitCount: 282,
     missCount: 0,
   ),
   // 100.0%.
@@ -545,7 +545,7 @@
   ),
   // 100.0%.
   "package:front_end/src/fragment/factory/declaration.dart": (
-    hitCount: 125,
+    hitCount: 120,
     missCount: 0,
   ),
   // 100.0%.
@@ -555,7 +555,7 @@
   ),
   // 100.0%.
   "package:front_end/src/fragment/field.dart": (
-    hitCount: 394,
+    hitCount: 28,
     missCount: 0,
   ),
   // 100.0%.
@@ -569,6 +569,11 @@
     missCount: 0,
   ),
   // 100.0%.
+  "package:front_end/src/fragment/field/declaration.dart": (
+    hitCount: 412,
+    missCount: 0,
+  ),
+  // 100.0%.
   "package:front_end/src/fragment/field/encoding.dart": (
     hitCount: 996,
     missCount: 0,
@@ -585,12 +590,12 @@
   ),
   // 100.0%.
   "package:front_end/src/fragment/getter/declaration.dart": (
-    hitCount: 120,
+    hitCount: 117,
     missCount: 0,
   ),
   // 100.0%.
   "package:front_end/src/fragment/getter/encoding.dart": (
-    hitCount: 368,
+    hitCount: 364,
     missCount: 0,
   ),
   // 100.0%.
@@ -610,7 +615,7 @@
   ),
   // 100.0%.
   "package:front_end/src/fragment/method/encoding.dart": (
-    hitCount: 642,
+    hitCount: 638,
     missCount: 0,
   ),
   // 100.0%.
@@ -640,12 +645,12 @@
   ),
   // 100.0%.
   "package:front_end/src/fragment/setter/declaration.dart": (
-    hitCount: 116,
+    hitCount: 113,
     missCount: 0,
   ),
   // 100.0%.
   "package:front_end/src/fragment/setter/encoding.dart": (
-    hitCount: 393,
+    hitCount: 389,
     missCount: 0,
   ),
   // 100.0%.
@@ -660,7 +665,7 @@
   ),
   // 100.0%.
   "package:front_end/src/fragment/util.dart": (
-    hitCount: 127,
+    hitCount: 80,
     missCount: 0,
   ),
   // 100.0%.
@@ -875,7 +880,7 @@
   ),
   // 100.0%.
   "package:front_end/src/kernel/utils.dart": (
-    hitCount: 85,
+    hitCount: 86,
     missCount: 0,
   ),
   // 100.0%.
@@ -915,7 +920,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/outline_builder.dart": (
-    hitCount: 2107,
+    hitCount: 2109,
     missCount: 0,
   ),
   // 100.0%.
@@ -935,17 +940,17 @@
   ),
   // 100.0%.
   "package:front_end/src/source/source_class_builder.dart": (
-    hitCount: 1428,
+    hitCount: 1432,
     missCount: 0,
   ),
   // 100.0%.
   "package:front_end/src/source/source_compilation_unit.dart": (
-    hitCount: 664,
+    hitCount: 663,
     missCount: 0,
   ),
   // 100.0%.
   "package:front_end/src/source/source_constructor_builder.dart": (
-    hitCount: 415,
+    hitCount: 410,
     missCount: 0,
   ),
   // 100.0%.
@@ -955,18 +960,18 @@
   ),
   // 100.0%.
   "package:front_end/src/source/source_extension_builder.dart": (
-    hitCount: 129,
+    hitCount: 130,
     missCount: 0,
   ),
   // 100.0%.
   "package:front_end/src/source/source_extension_type_declaration_builder.dart":
       (
-    hitCount: 536,
+    hitCount: 535,
     missCount: 0,
   ),
   // 100.0%.
   "package:front_end/src/source/source_factory_builder.dart": (
-    hitCount: 132,
+    hitCount: 129,
     missCount: 0,
   ),
   // 100.0%.
@@ -976,7 +981,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/source_library_builder.dart": (
-    hitCount: 1069,
+    hitCount: 1071,
     missCount: 0,
   ),
   // 100.0%.
@@ -991,12 +996,12 @@
   ),
   // 100.0%.
   "package:front_end/src/source/source_method_builder.dart": (
-    hitCount: 195,
+    hitCount: 190,
     missCount: 0,
   ),
   // 100.0%.
   "package:front_end/src/source/source_property_builder.dart": (
-    hitCount: 664,
+    hitCount: 656,
     missCount: 0,
   ),
   // 100.0%.
@@ -1006,7 +1011,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/source_type_parameter_builder.dart": (
-    hitCount: 111,
+    hitCount: 106,
     missCount: 0,
   ),
   // 100.0%.
diff --git a/pkg/front_end/testcases/extensions/patch/main.dart.strong.expect b/pkg/front_end/testcases/extensions/patch/main.dart.strong.expect
index fdf90e1..75585b5 100644
--- a/pkg/front_end/testcases/extensions/patch/main.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/patch/main.dart.strong.expect
@@ -16,14 +16,14 @@
 
 import "dart:_internal";
 
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension IntExtension on core::int {
   method method1 = test::IntExtension|method1;
   method tearoff method1 = test::IntExtension|get#method1;
   method method2 = test::IntExtension|method2;
   method tearoff method2 = test::IntExtension|get#method2;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension GenericExtension<T extends core::Object? = dynamic> on T% {
   method method3 = test::GenericExtension|method3;
   method tearoff method3 = test::GenericExtension|get#method3;
diff --git a/pkg/front_end/testcases/extensions/patch/main.dart.strong.modular.expect b/pkg/front_end/testcases/extensions/patch/main.dart.strong.modular.expect
index fdf90e1..75585b5 100644
--- a/pkg/front_end/testcases/extensions/patch/main.dart.strong.modular.expect
+++ b/pkg/front_end/testcases/extensions/patch/main.dart.strong.modular.expect
@@ -16,14 +16,14 @@
 
 import "dart:_internal";
 
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension IntExtension on core::int {
   method method1 = test::IntExtension|method1;
   method tearoff method1 = test::IntExtension|get#method1;
   method method2 = test::IntExtension|method2;
   method tearoff method2 = test::IntExtension|get#method2;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension GenericExtension<T extends core::Object? = dynamic> on T% {
   method method3 = test::GenericExtension|method3;
   method tearoff method3 = test::GenericExtension|get#method3;
diff --git a/pkg/front_end/testcases/extensions/patch/main.dart.strong.outline.expect b/pkg/front_end/testcases/extensions/patch/main.dart.strong.outline.expect
index d6c09a8..eddc591 100644
--- a/pkg/front_end/testcases/extensions/patch/main.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/extensions/patch/main.dart.strong.outline.expect
@@ -13,14 +13,14 @@
 
 import "dart:_internal";
 
-@_in::patch
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
 extension IntExtension on core::int {
   method method1 = self2::IntExtension|method1;
   method tearoff method1 = self2::IntExtension|get#method1;
   method method2 = self2::IntExtension|method2;
   method tearoff method2 = self2::IntExtension|get#method2;
 }
-@_in::patch
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
 extension GenericExtension<T extends core::Object? = dynamic> on T% {
   method method3 = self2::GenericExtension|method3;
   method tearoff method3 = self2::GenericExtension|get#method3;
@@ -52,8 +52,8 @@
 
 
 Extra constant evaluation status:
-Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:5:63 -> InstanceConstant(const _Patch{})
-Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:7:5 -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:8:1 -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:16:1 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:10:4 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:18:4 -> InstanceConstant(const _Patch{})
 Extra constant evaluation: evaluated: 16, effectively constant: 4
diff --git a/pkg/front_end/testcases/extensions/patch/main.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/patch/main.dart.strong.transformed.expect
index fdf90e1..75585b5 100644
--- a/pkg/front_end/testcases/extensions/patch/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/patch/main.dart.strong.transformed.expect
@@ -16,14 +16,14 @@
 
 import "dart:_internal";
 
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension IntExtension on core::int {
   method method1 = test::IntExtension|method1;
   method tearoff method1 = test::IntExtension|get#method1;
   method method2 = test::IntExtension|method2;
   method tearoff method2 = test::IntExtension|get#method2;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension GenericExtension<T extends core::Object? = dynamic> on T% {
   method method3 = test::GenericExtension|method3;
   method tearoff method3 = test::GenericExtension|get#method3;
diff --git a/pkg/front_end/testcases/extensions/patching/main.dart.strong.expect b/pkg/front_end/testcases/extensions/patching/main.dart.strong.expect
index 2583619..8265d24 100644
--- a/pkg/front_end/testcases/extensions/patching/main.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/patching/main.dart.strong.expect
@@ -27,7 +27,7 @@
 
 import "dart:_internal";
 
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension Extension on core::String {
   method instanceMethod = test::Extension|instanceMethod;
   method tearoff instanceMethod = test::Extension|get#instanceMethod;
@@ -40,7 +40,7 @@
   set instanceProperty = test::Extension|set#instanceProperty;
   static set staticProperty = set test::Extension|staticProperty;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension GenericExtension<T extends core::Object? = dynamic> on T% {
   method instanceMethod = test::GenericExtension|instanceMethod;
   method tearoff instanceMethod = test::GenericExtension|get#instanceMethod;
diff --git a/pkg/front_end/testcases/extensions/patching/main.dart.strong.modular.expect b/pkg/front_end/testcases/extensions/patching/main.dart.strong.modular.expect
index 2583619..8265d24 100644
--- a/pkg/front_end/testcases/extensions/patching/main.dart.strong.modular.expect
+++ b/pkg/front_end/testcases/extensions/patching/main.dart.strong.modular.expect
@@ -27,7 +27,7 @@
 
 import "dart:_internal";
 
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension Extension on core::String {
   method instanceMethod = test::Extension|instanceMethod;
   method tearoff instanceMethod = test::Extension|get#instanceMethod;
@@ -40,7 +40,7 @@
   set instanceProperty = test::Extension|set#instanceProperty;
   static set staticProperty = set test::Extension|staticProperty;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension GenericExtension<T extends core::Object? = dynamic> on T% {
   method instanceMethod = test::GenericExtension|instanceMethod;
   method tearoff instanceMethod = test::GenericExtension|get#instanceMethod;
diff --git a/pkg/front_end/testcases/extensions/patching/main.dart.strong.outline.expect b/pkg/front_end/testcases/extensions/patching/main.dart.strong.outline.expect
index c2f7ce4..8c8eb11 100644
--- a/pkg/front_end/testcases/extensions/patching/main.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/extensions/patching/main.dart.strong.outline.expect
@@ -13,7 +13,7 @@
 
 import "dart:_internal";
 
-@_in::patch
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
 extension Extension on core::String {
   method instanceMethod = self2::Extension|instanceMethod;
   method tearoff instanceMethod = self2::Extension|get#instanceMethod;
@@ -26,7 +26,7 @@
   set instanceProperty = self2::Extension|set#instanceProperty;
   static set staticProperty = set self2::Extension|staticProperty;
 }
-@_in::patch
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
 extension GenericExtension<T extends core::Object? = dynamic> on T% {
   method instanceMethod = self2::GenericExtension|instanceMethod;
   method tearoff instanceMethod = self2::GenericExtension|get#instanceMethod;
@@ -98,8 +98,8 @@
 
 
 Extra constant evaluation status:
-Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:6:31 -> InstanceConstant(const _Patch{})
-Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:26:39 -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:8:1 -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:35:1 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:10:4 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:13:4 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:16:4 -> InstanceConstant(const _Patch{})
diff --git a/pkg/front_end/testcases/extensions/patching/main.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/patching/main.dart.strong.transformed.expect
index 2583619..8265d24 100644
--- a/pkg/front_end/testcases/extensions/patching/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/patching/main.dart.strong.transformed.expect
@@ -27,7 +27,7 @@
 
 import "dart:_internal";
 
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension Extension on core::String {
   method instanceMethod = test::Extension|instanceMethod;
   method tearoff instanceMethod = test::Extension|get#instanceMethod;
@@ -40,7 +40,7 @@
   set instanceProperty = test::Extension|set#instanceProperty;
   static set staticProperty = set test::Extension|staticProperty;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension GenericExtension<T extends core::Object? = dynamic> on T% {
   method instanceMethod = test::GenericExtension|instanceMethod;
   method tearoff instanceMethod = test::GenericExtension|get#instanceMethod;
diff --git a/pkg/front_end/testcases/general/inject_public/main.dart.strong.expect b/pkg/front_end/testcases/general/inject_public/main.dart.strong.expect
index 4394326..91910a0 100644
--- a/pkg/front_end/testcases/general/inject_public/main.dart.strong.expect
+++ b/pkg/front_end/testcases/general/inject_public/main.dart.strong.expect
@@ -70,13 +70,13 @@
     ;
   method publicMethod() → dynamic {}
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension Extension on core::int {
   method injectedMethod = test::Extension|injectedMethod;
   method tearoff injectedMethod = test::Extension|get#injectedMethod;
   static method staticInjectedMethod = test::Extension|staticInjectedMethod;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension _PrivateExtension on core::int {
   method injectedMethod = test::_PrivateExtension|injectedMethod;
   method tearoff injectedMethod = test::_PrivateExtension|get#injectedMethod;
diff --git a/pkg/front_end/testcases/general/inject_public/main.dart.strong.modular.expect b/pkg/front_end/testcases/general/inject_public/main.dart.strong.modular.expect
index 4394326..91910a0 100644
--- a/pkg/front_end/testcases/general/inject_public/main.dart.strong.modular.expect
+++ b/pkg/front_end/testcases/general/inject_public/main.dart.strong.modular.expect
@@ -70,13 +70,13 @@
     ;
   method publicMethod() → dynamic {}
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension Extension on core::int {
   method injectedMethod = test::Extension|injectedMethod;
   method tearoff injectedMethod = test::Extension|get#injectedMethod;
   static method staticInjectedMethod = test::Extension|staticInjectedMethod;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension _PrivateExtension on core::int {
   method injectedMethod = test::_PrivateExtension|injectedMethod;
   method tearoff injectedMethod = test::_PrivateExtension|get#injectedMethod;
diff --git a/pkg/front_end/testcases/general/inject_public/main.dart.strong.outline.expect b/pkg/front_end/testcases/general/inject_public/main.dart.strong.outline.expect
index a34b2d0..ab70b26 100644
--- a/pkg/front_end/testcases/general/inject_public/main.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/general/inject_public/main.dart.strong.outline.expect
@@ -66,13 +66,13 @@
   method publicMethod() → dynamic
     ;
 }
-@_in::patch
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
 extension Extension on core::int {
   method injectedMethod = self2::Extension|injectedMethod;
   method tearoff injectedMethod = self2::Extension|get#injectedMethod;
   static method staticInjectedMethod = self2::Extension|staticInjectedMethod;
 }
-@_in::patch
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
 extension _PrivateExtension on core::int {
   method injectedMethod = self2::_PrivateExtension|injectedMethod;
   method tearoff injectedMethod = self2::_PrivateExtension|get#injectedMethod;
@@ -105,6 +105,6 @@
 Extra constant evaluation status:
 Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:12:1 -> InstanceConstant(const _Patch{})
 Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:32:1 -> InstanceConstant(const _Patch{})
-Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
-Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:18:1 -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:38:1 -> InstanceConstant(const _Patch{})
 Extra constant evaluation: evaluated: 13, effectively constant: 4
diff --git a/pkg/front_end/testcases/general/inject_public/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/inject_public/main.dart.strong.transformed.expect
index 4394326..91910a0 100644
--- a/pkg/front_end/testcases/general/inject_public/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/inject_public/main.dart.strong.transformed.expect
@@ -70,13 +70,13 @@
     ;
   method publicMethod() → dynamic {}
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension Extension on core::int {
   method injectedMethod = test::Extension|injectedMethod;
   method tearoff injectedMethod = test::Extension|get#injectedMethod;
   static method staticInjectedMethod = test::Extension|staticInjectedMethod;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension _PrivateExtension on core::int {
   method injectedMethod = test::_PrivateExtension|injectedMethod;
   method tearoff injectedMethod = test::_PrivateExtension|get#injectedMethod;
diff --git a/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.expect b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.expect
index 85f0092..37dac80 100644
--- a/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.expect
+++ b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.expect
@@ -75,13 +75,13 @@
     : super core::Object::•()
     ;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension InvalidExtensionTypeParameterCount1 on core::int {
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension InvalidExtensionTypeParameterCount2<T extends core::Object? = dynamic> on core::int {
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension InvalidExtensionTypeParameterCount3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> on core::int {
 }
 
diff --git a/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.modular.expect b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.modular.expect
index 85f0092..37dac80 100644
--- a/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.modular.expect
+++ b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.modular.expect
@@ -75,13 +75,13 @@
     : super core::Object::•()
     ;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension InvalidExtensionTypeParameterCount1 on core::int {
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension InvalidExtensionTypeParameterCount2<T extends core::Object? = dynamic> on core::int {
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension InvalidExtensionTypeParameterCount3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> on core::int {
 }
 
diff --git a/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.outline.expect b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.outline.expect
index 59d64c6..c01a670 100644
--- a/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.outline.expect
@@ -73,13 +73,13 @@
   synthetic constructor •() → self2::InvalidClassTypeParameterCount3<self2::InvalidClassTypeParameterCount3::T%, self2::InvalidClassTypeParameterCount3::S%>
     ;
 }
-@_in::patch
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
 extension InvalidExtensionTypeParameterCount1 on core::int {
 }
-@_in::patch
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
 extension InvalidExtensionTypeParameterCount2<T extends core::Object? = dynamic> on core::int {
 }
-@_in::patch
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
 extension InvalidExtensionTypeParameterCount3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> on core::int {
 }
 
@@ -88,7 +88,7 @@
 Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:8:1 -> InstanceConstant(const _Patch{})
 Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:11:1 -> InstanceConstant(const _Patch{})
 Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:14:1 -> InstanceConstant(const _Patch{})
-Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:14:1 -> InstanceConstant(const _Patch{})
-Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
-Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:17:1 -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:20:1 -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:23:1 -> InstanceConstant(const _Patch{})
 Extra constant evaluation: evaluated: 6, effectively constant: 6
diff --git a/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.transformed.expect
index 85f0092..37dac80 100644
--- a/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.transformed.expect
@@ -75,13 +75,13 @@
     : super core::Object::•()
     ;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension InvalidExtensionTypeParameterCount1 on core::int {
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension InvalidExtensionTypeParameterCount2<T extends core::Object? = dynamic> on core::int {
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension InvalidExtensionTypeParameterCount3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> on core::int {
 }
 
diff --git a/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.expect b/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.expect
index d7f8e96..4f738f7 100644
--- a/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.expect
+++ b/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.expect
@@ -27,8 +27,8 @@
   external method /* from org-dartlang-testcase:///patch_lib.dart */ method<@#C22 S extends core::Object? = dynamic>() → void;
 }
 @#C24
-@#C6
-@#C26
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C6
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C26
 extension Extension<@#C28 @/* from org-dartlang-testcase:///patch_lib.dart */ #C30 T extends core::Object? = dynamic> on core::int {
   method method = self2::Extension|method;
   method tearoff method = self2::Extension|get#method;
diff --git a/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.modular.expect b/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.modular.expect
index d7f8e96..4f738f7 100644
--- a/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.modular.expect
+++ b/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.modular.expect
@@ -27,8 +27,8 @@
   external method /* from org-dartlang-testcase:///patch_lib.dart */ method<@#C22 S extends core::Object? = dynamic>() → void;
 }
 @#C24
-@#C6
-@#C26
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C6
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C26
 extension Extension<@#C28 @/* from org-dartlang-testcase:///patch_lib.dart */ #C30 T extends core::Object? = dynamic> on core::int {
   method method = self2::Extension|method;
   method tearoff method = self2::Extension|get#method;
diff --git a/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.outline.expect b/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.outline.expect
index 31a0196..8b0793c 100644
--- a/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.outline.expect
@@ -28,8 +28,8 @@
   external method /* from org-dartlang-testcase:///patch_lib.dart */ method<@core::pragma::_("patch-method-type-variable") S extends core::Object? = dynamic>() → void;
 }
 @core::pragma::_("origin-extension")
-@_in::patch
-@core::pragma::_("patch-extension")
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
+@/* from org-dartlang-testcase:///patch_lib.dart */ const core::pragma::_("patch-extension")
 extension Extension<@core::pragma::_("origin-extension-type-variable") @/* from org-dartlang-testcase:///patch_lib.dart */ const core::pragma::_("patch-extension-type-variable") T extends core::Object? = dynamic> on core::int {
   method method = self2::Extension|method;
   method tearoff method = self2::Extension|get#method;
@@ -57,8 +57,8 @@
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///patch_lib.dart:16:4 -> InstanceConstant(const pragma{pragma.name: "patch-procedure", pragma.options: null})
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///patch_lib.dart:17:25 -> InstanceConstant(const pragma{pragma.name: "patch-method-type-variable", pragma.options: null})
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///origin_lib.dart:17:2 -> InstanceConstant(const pragma{pragma.name: "origin-extension", pragma.options: null})
-Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:18:19 -> InstanceConstant(const _Patch{})
-Evaluated: ConstructorInvocation @ org-dartlang-testcase:///origin_lib.dart:18:26 -> InstanceConstant(const pragma{pragma.name: "patch-extension", pragma.options: null})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:20:1 -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:21:1 -> InstanceConstant(const pragma{pragma.name: "patch-extension", pragma.options: null})
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///origin_lib.dart:18:22 -> InstanceConstant(const pragma{pragma.name: "origin-extension-type-variable", pragma.options: null})
 Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:22:21 -> InstanceConstant(const pragma{pragma.name: "patch-extension-type-variable", pragma.options: null})
 Evaluated: FileUriExpression @ org-dartlang-testcase:///origin_lib.dart:19:3 -> InstanceConstant(const pragma{pragma.name: "origin-extension-method", pragma.options: null})
diff --git a/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.transformed.expect
index d7f8e96..4f738f7 100644
--- a/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/patch_annotations/main.dart.strong.transformed.expect
@@ -27,8 +27,8 @@
   external method /* from org-dartlang-testcase:///patch_lib.dart */ method<@#C22 S extends core::Object? = dynamic>() → void;
 }
 @#C24
-@#C6
-@#C26
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C6
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C26
 extension Extension<@#C28 @/* from org-dartlang-testcase:///patch_lib.dart */ #C30 T extends core::Object? = dynamic> on core::int {
   method method = self2::Extension|method;
   method tearoff method = self2::Extension|get#method;
diff --git a/pkg/front_end/testcases/general/patch_getter/main.dart.strong.expect b/pkg/front_end/testcases/general/patch_getter/main.dart.strong.expect
index 47d3abc..16caa5b 100644
--- a/pkg/front_end/testcases/general/patch_getter/main.dart.strong.expect
+++ b/pkg/front_end/testcases/general/patch_getter/main.dart.strong.expect
@@ -41,7 +41,7 @@
   static get /* from org-dartlang-testcase:///patch_lib.dart */ staticGetter() → core::int
     return 42;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension Extension on core::int {
   get instanceGetter = test::Extension|get#instanceGetter;
   static get staticGetter = get test::Extension|staticGetter;
diff --git a/pkg/front_end/testcases/general/patch_getter/main.dart.strong.modular.expect b/pkg/front_end/testcases/general/patch_getter/main.dart.strong.modular.expect
index 47d3abc..16caa5b 100644
--- a/pkg/front_end/testcases/general/patch_getter/main.dart.strong.modular.expect
+++ b/pkg/front_end/testcases/general/patch_getter/main.dart.strong.modular.expect
@@ -41,7 +41,7 @@
   static get /* from org-dartlang-testcase:///patch_lib.dart */ staticGetter() → core::int
     return 42;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension Extension on core::int {
   get instanceGetter = test::Extension|get#instanceGetter;
   static get staticGetter = get test::Extension|staticGetter;
diff --git a/pkg/front_end/testcases/general/patch_getter/main.dart.strong.outline.expect b/pkg/front_end/testcases/general/patch_getter/main.dart.strong.outline.expect
index 9c86dfe..26bafaa 100644
--- a/pkg/front_end/testcases/general/patch_getter/main.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/general/patch_getter/main.dart.strong.outline.expect
@@ -32,7 +32,7 @@
   static get /* from org-dartlang-testcase:///patch_lib.dart */ staticGetter() → core::int
     ;
 }
-@_in::patch
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
 extension Extension on core::int {
   get instanceGetter = self2::Extension|get#instanceGetter;
   static get staticGetter = get self2::Extension|staticGetter;
@@ -56,7 +56,7 @@
 Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:11:1 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:13:4 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:16:4 -> InstanceConstant(const _Patch{})
-Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:18:9 -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:20:1 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:8:2 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:22:4 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:25:4 -> InstanceConstant(const _Patch{})
diff --git a/pkg/front_end/testcases/general/patch_getter/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/patch_getter/main.dart.strong.transformed.expect
index 47d3abc..16caa5b 100644
--- a/pkg/front_end/testcases/general/patch_getter/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/patch_getter/main.dart.strong.transformed.expect
@@ -41,7 +41,7 @@
   static get /* from org-dartlang-testcase:///patch_lib.dart */ staticGetter() → core::int
     return 42;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension Extension on core::int {
   get instanceGetter = test::Extension|get#instanceGetter;
   static get staticGetter = get test::Extension|staticGetter;
diff --git a/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.expect b/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.expect
index 5d808e7..bb4c56c 100644
--- a/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.expect
+++ b/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.expect
@@ -27,7 +27,7 @@
   method /* from org-dartlang-testcase:///patch_lib.dart */ method() → core::int
     return #C2;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension Extension on core::int {
   method method = test::Extension|method;
   method tearoff method = test::Extension|get#method;
diff --git a/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.modular.expect b/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.modular.expect
index 5d808e7..bb4c56c 100644
--- a/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.modular.expect
+++ b/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.modular.expect
@@ -27,7 +27,7 @@
   method /* from org-dartlang-testcase:///patch_lib.dart */ method() → core::int
     return #C2;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension Extension on core::int {
   method method = test::Extension|method;
   method tearoff method = test::Extension|get#method;
diff --git a/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.outline.expect b/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.outline.expect
index a6c4484..acd48ff 100644
--- a/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.outline.expect
@@ -23,7 +23,7 @@
   method /* from org-dartlang-testcase:///patch_lib.dart */ method() → core::int
     ;
 }
-@_in::patch
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
 extension Extension on core::int {
   method method = self2::Extension|method;
   method tearoff method = self2::Extension|get#method;
@@ -46,6 +46,6 @@
 Extra constant evaluation status:
 Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:9:1 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:13:4 -> InstanceConstant(const _Patch{})
-Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:17:1 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:21:4 -> InstanceConstant(const _Patch{})
 Extra constant evaluation: evaluated: 7, effectively constant: 4
diff --git a/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.transformed.expect
index 5d808e7..bb4c56c 100644
--- a/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/patch_prefix_access/main.dart.strong.transformed.expect
@@ -27,7 +27,7 @@
   method /* from org-dartlang-testcase:///patch_lib.dart */ method() → core::int
     return #C2;
 }
-@#C1
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
 extension Extension on core::int {
   method method = test::Extension|method;
   method tearoff method = test::Extension|get#method;
diff --git a/pkg/front_end/testcases/general/patching/main.dart.strong.expect b/pkg/front_end/testcases/general/patching/main.dart.strong.expect
index 458525f..7735314 100644
--- a/pkg/front_end/testcases/general/patching/main.dart.strong.expect
+++ b/pkg/front_end/testcases/general/patching/main.dart.strong.expect
@@ -114,7 +114,7 @@
   static set staticSetter(core::int value) → void {}
   static method staticMethod(core::int value) → void {}
 }
-@#C8
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C8
 extension Extension on test::Class {
   get extensionInstanceGetter = test::Extension|get#extensionInstanceGetter;
   method extensionInstanceMethod = test::Extension|extensionInstanceMethod;
diff --git a/pkg/front_end/testcases/general/patching/main.dart.strong.modular.expect b/pkg/front_end/testcases/general/patching/main.dart.strong.modular.expect
index 458525f..7735314 100644
--- a/pkg/front_end/testcases/general/patching/main.dart.strong.modular.expect
+++ b/pkg/front_end/testcases/general/patching/main.dart.strong.modular.expect
@@ -114,7 +114,7 @@
   static set staticSetter(core::int value) → void {}
   static method staticMethod(core::int value) → void {}
 }
-@#C8
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C8
 extension Extension on test::Class {
   get extensionInstanceGetter = test::Extension|get#extensionInstanceGetter;
   method extensionInstanceMethod = test::Extension|extensionInstanceMethod;
diff --git a/pkg/front_end/testcases/general/patching/main.dart.strong.outline.expect b/pkg/front_end/testcases/general/patching/main.dart.strong.outline.expect
index 012cc63..495466d 100644
--- a/pkg/front_end/testcases/general/patching/main.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/general/patching/main.dart.strong.outline.expect
@@ -93,7 +93,7 @@
   static method staticMethod(core::int value) → void
     ;
 }
-@_in::patch
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
 extension Extension on self2::Class {
   get extensionInstanceGetter = self2::Extension|get#extensionInstanceGetter;
   method extensionInstanceMethod = self2::Extension|extensionInstanceMethod;
@@ -180,7 +180,7 @@
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:103:4 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:108:4 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:113:4 -> InstanceConstant(const _Patch{})
-Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:134:1 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:8:2 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:13:2 -> InstanceConstant(const _Patch{})
 Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:18:2 -> InstanceConstant(const _Patch{})
diff --git a/pkg/front_end/testcases/general/patching/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/patching/main.dart.strong.transformed.expect
index 458525f..7735314 100644
--- a/pkg/front_end/testcases/general/patching/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/patching/main.dart.strong.transformed.expect
@@ -114,7 +114,7 @@
   static set staticSetter(core::int value) → void {}
   static method staticMethod(core::int value) → void {}
 }
-@#C8
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C8
 extension Extension on test::Class {
   get extensionInstanceGetter = test::Extension|get#extensionInstanceGetter;
   method extensionInstanceMethod = test::Extension|extensionInstanceMethod;
diff --git a/pkg/record_use/CHANGELOG.md b/pkg/record_use/CHANGELOG.md
index cfd2549..8d3da5f 100644
--- a/pkg/record_use/CHANGELOG.md
+++ b/pkg/record_use/CHANGELOG.md
@@ -1,6 +1,8 @@
-## 0.3.1-wip
+## 0.4.0
 
 - Update SDK constraint to `^3.5.0`.
+- Rewrite API to expose less symbols.
+- Remove locations for easier caching.
 
 ## 0.3.0
 
diff --git a/pkg/record_use/README.md b/pkg/record_use/README.md
index 7371b29..e3c6f85 100644
--- a/pkg/record_use/README.md
+++ b/pkg/record_use/README.md
@@ -104,5 +104,14 @@
 }
 ```
 
+## Limitations
+As this is designed to work on both web and native platforms, we have to adapt 
+to the platform pecularities. One of them is that javascript does not support
+named arguments, so the dart2js compiler rewrites functions to only accept named
+parameters.
+While you can use named parameters to record functions, we advise caution as the
+retrieval behavior might change once we work around this dart2js limitation and
+implement separate positional and named parameters.
+
 ## Contributing
-Contributions are welcome! Please open an issue or submit a pull request.
\ No newline at end of file
+Contributions are welcome! Please open an issue or submit a pull request.
diff --git a/pkg/record_use/example/record_use_example.dart b/pkg/record_use/example/record_use_example.dart
index f3359cc..688d9e0 100644
--- a/pkg/record_use/example/record_use_example.dart
+++ b/pkg/record_use/example/record_use_example.dart
@@ -4,9 +4,14 @@
 
 import 'package:record_use/record_use.dart';
 
-void doStuff(RecordedUsages usage, Identifier callId, Identifier referenceId) {
+void doStuffInLinkHook(
+  RecordedUsages usage,
+  Identifier identifier1,
+  Identifier identifier2,
+  Identifier identifier3,
+) {
   print(usage.metadata);
-  print(usage.argumentsTo(callId));
-  print(usage.instancesOf(referenceId));
-  print(usage.hasNonConstArguments(callId));
+  print(usage.constArgumentsFor(identifier1, 'void foo(int i)'));
+  print(usage.constantsOf(identifier2));
+  print(usage.hasNonConstArguments(identifier3));
 }
diff --git a/pkg/record_use/lib/record_use.dart b/pkg/record_use/lib/record_use.dart
index 30c7561..3f51793 100644
--- a/pkg/record_use/lib/record_use.dart
+++ b/pkg/record_use/lib/record_use.dart
@@ -2,22 +2,6 @@
 // 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.
 
-export 'src/public/arguments.dart'
-    show Arguments, ConstArguments, NonConstArguments;
-export 'src/public/constant.dart'
-    show
-        BoolConstant,
-        Constant,
-        InstanceConstant,
-        IntConstant,
-        ListConstant,
-        MapConstant,
-        NullConstant,
-        PrimitiveConstant,
-        StringConstant;
-export 'src/public/identifier.dart' show Identifier;
-export 'src/public/location.dart' show Location;
-export 'src/public/metadata.dart' show Metadata;
-//Not exporting `Reference` as it is not used in the API
-export 'src/public/reference.dart' show CallReference, InstanceReference;
-export 'src/record_use.dart' show RecordedUsages;
+export 'src/identifier.dart' show Identifier;
+export 'src/metadata.dart' show Metadata, MetadataExt;
+export 'src/record_use.dart' show ConstantInstance, RecordedUsages;
diff --git a/pkg/record_use/lib/record_use_internal.dart b/pkg/record_use/lib/record_use_internal.dart
index eb97752..6f341ee 100644
--- a/pkg/record_use/lib/record_use_internal.dart
+++ b/pkg/record_use/lib/record_use_internal.dart
@@ -2,7 +2,23 @@
 // 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.
 
-export 'record_use.dart';
-export 'src/internal/definition.dart' show Definition;
-export 'src/internal/usage.dart' show Usage;
-export 'src/internal/usage_record.dart' show UsageRecord;
+export 'src/constant.dart'
+    show
+        BoolConstant,
+        Constant,
+        InstanceConstant,
+        IntConstant,
+        ListConstant,
+        MapConstant,
+        NullConstant,
+        PrimitiveConstant,
+        StringConstant;
+export 'src/definition.dart' show Definition;
+export 'src/identifier.dart' show Identifier;
+export 'src/location.dart' show Location;
+export 'src/metadata.dart' show Metadata, MetadataExt;
+export 'src/record_use.dart' show RecordedUsages;
+export 'src/recordings.dart' show Recordings;
+export 'src/reference.dart'
+    show CallReference, CallTearOff, CallWithArguments, InstanceReference;
+export 'src/signature.dart' show Signature;
diff --git a/pkg/record_use/lib/src/constant.dart b/pkg/record_use/lib/src/constant.dart
new file mode 100644
index 0000000..81e0dfd
--- /dev/null
+++ b/pkg/record_use/lib/src/constant.dart
@@ -0,0 +1,262 @@
+// 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 'helper.dart';
+
+const _typeKey = 'type';
+const _valueKey = 'value';
+
+/// A constant value that can be recorded and serialized.
+///
+/// This supports basic constants such as [bool]s or [int]s, as well as
+/// [ListConstant], [MapConstant] or [InstanceConstant] for more complex
+/// structures.
+///
+/// This follows the AST constant concept from the Dart SDK.
+sealed class Constant {
+  /// Creates a [Constant] object.
+  const Constant();
+
+  /// Converts this [Constant] object to a JSON representation.
+  ///
+  /// [constants] needs to be passed, as the [Constant]s are normalized and
+  /// stored separately in the JSON.
+  Map<String, Object?> toJson(Map<Constant, int> constants);
+
+  /// Converts this [Constant] to the value it represents.
+  Object? toValue() => switch (this) {
+    NullConstant() => null,
+    PrimitiveConstant p => p.value,
+    ListConstant<Constant> l => l.value.map((c) => c.toValue()).toList(),
+    MapConstant<Constant> m => m.value.map(
+      (key, value) => MapEntry(key, value.toValue()),
+    ),
+    InstanceConstant i => i.fields.map(
+      (key, value) => MapEntry(key, value.toValue()),
+    ),
+  };
+
+  /// Creates a [Constant] object from its JSON representation.
+  ///
+  /// [constants] needs to be passed, as the [Constant]s are normalized and
+  /// stored separately in the JSON.
+  static Constant fromJson(
+    Map<String, Object?> value,
+    List<Constant> constants,
+  ) => switch (value[_typeKey] as String) {
+    NullConstant._type => const NullConstant(),
+    BoolConstant._type => BoolConstant(value[_valueKey] as bool),
+    IntConstant._type => IntConstant(value[_valueKey] as int),
+    StringConstant._type => StringConstant(value[_valueKey] as String),
+    ListConstant._type => ListConstant(
+      (value[_valueKey] as List<dynamic>)
+          .map((value) => value as int)
+          .map((value) => constants[value])
+          .toList(),
+    ),
+    MapConstant._type => MapConstant(
+      (value[_valueKey] as Map<String, Object?>).map(
+        (key, value) => MapEntry(key, constants[value as int]),
+      ),
+    ),
+    InstanceConstant._type => InstanceConstant(
+      fields: (value[_valueKey] as Map<String, Object?>).map(
+        (key, value) => MapEntry(key, constants[value as int]),
+      ),
+    ),
+    String() =>
+      throw UnimplementedError('This type is not a supported constant'),
+  };
+}
+
+/// Represents the `null` constant value.
+final class NullConstant extends Constant {
+  /// The type identifier for JSON serialization.
+  static const _type = 'Null';
+
+  /// Creates a [NullConstant] object.
+  const NullConstant() : super();
+
+  @override
+  Map<String, Object?> toJson(Map<Constant, int> constants) =>
+      _toJson(_type, null);
+
+  @override
+  bool operator ==(Object other) => other is NullConstant;
+
+  @override
+  int get hashCode => 0;
+}
+
+/// Represents a constant value of a primitive type.
+sealed class PrimitiveConstant<T extends Object> extends Constant {
+  /// The underlying value of this constant.
+  final T value;
+
+  /// Creates a [PrimitiveConstant] object with the given [value].
+  const PrimitiveConstant(this.value);
+
+  @override
+  int get hashCode => value.hashCode;
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+
+    return other is PrimitiveConstant<T> && other.value == value;
+  }
+
+  @override
+  Map<String, Object?> toJson(Map<Constant, int> constants) => valueToJson();
+
+  /// Converts this primitive constant to a JSON representation.
+  Map<String, Object?> valueToJson();
+}
+
+/// Represents a constant boolean value.
+final class BoolConstant extends PrimitiveConstant<bool> {
+  /// The type identifier for JSON serialization.
+  static const _type = 'bool';
+
+  /// Creates a [BoolConstant] object with the given boolean [value].
+  const BoolConstant(super.value);
+
+  @override
+  Map<String, Object?> valueToJson() => _toJson(_type, value);
+}
+
+/// Represents a constant integer value.
+final class IntConstant extends PrimitiveConstant<int> {
+  /// The type identifier for JSON serialization.
+  static const _type = 'int';
+
+  /// Creates an [IntConstant] object with the given integer [value].
+  const IntConstant(super.value);
+
+  @override
+  Map<String, Object?> valueToJson() => _toJson(_type, value);
+}
+
+/// Represents a constant string value.
+final class StringConstant extends PrimitiveConstant<String> {
+  /// The type identifier for JSON serialization.
+  static const _type = 'String';
+
+  /// Creates a [StringConstant] object with the given string [value].
+  const StringConstant(super.value);
+
+  @override
+  Map<String, Object?> valueToJson() => _toJson(_type, value);
+}
+
+/// Represents a constant list of [Constant] values.
+final class ListConstant<T extends Constant> extends Constant {
+  /// The type identifier for JSON serialization.
+  static const _type = 'list';
+
+  /// The underlying list of constant values.
+  final List<T> value;
+
+  /// Creates a [ListConstant] object with the given list of [value]s.
+  const ListConstant(this.value);
+
+  @override
+  int get hashCode => deepHash(value);
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+
+    return other is ListConstant && deepEquals(other.value, value);
+  }
+
+  @override
+  Map<String, Object?> toJson(Map<Constant, int> constants) =>
+      _toJson(_type, value.map((constant) => constants[constant]).toList());
+}
+
+/// Represents a constant map from string keys to [Constant] values.
+final class MapConstant<T extends Constant> extends Constant {
+  /// The type identifier for JSON serialization.
+  static const _type = 'map';
+
+  /// The underlying map of constant values.
+  final Map<String, T> value;
+
+  /// Creates a [MapConstant] object with the given map of [value]s.
+  const MapConstant(this.value);
+
+  @override
+  int get hashCode => deepHash(value);
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+
+    return other is MapConstant && deepEquals(other.value, value);
+  }
+
+  @override
+  Map<String, Object?> toJson(Map<Constant, int> constants) => _toJson(
+    _type,
+    value.map((key, constant) => MapEntry(key, constants[constant]!)),
+  );
+}
+
+/// A constant instance of a class with its fields
+///
+/// Only as far as they can also be represented by constants. This is more or
+/// less the same as a [MapConstant].
+final class InstanceConstant extends Constant {
+  /// The type identifier for JSON serialization.
+  static const _type = 'Instance';
+
+  /// The fields of this instance, mapped from field name to [Constant] value.
+  final Map<String, Constant> fields;
+
+  /// Creates an [InstanceConstant] object with the given [fields].
+  const InstanceConstant({required this.fields});
+
+  /// Creates an [InstanceConstant] object from JSON.
+  ///
+  /// [json] is a map representing the JSON structure.
+  /// [constants] is a list of [Constant] objects that are referenced by index
+  /// in the JSON.
+  factory InstanceConstant.fromJson(
+    Map<String, Object?> json,
+    List<Constant> constants,
+  ) {
+    return InstanceConstant(
+      fields: json.map(
+        (key, constantIndex) => MapEntry(key, constants[constantIndex as int]),
+      ),
+    );
+  }
+
+  @override
+  Map<String, Object?> toJson(Map<Constant, int> constants) => _toJson(
+    _type,
+    fields.isNotEmpty
+        ? fields.map(
+          (name, constantIndex) => MapEntry(name, constants[constantIndex]!),
+        )
+        : null,
+  );
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+
+    return other is InstanceConstant && deepEquals(other.fields, fields);
+  }
+
+  @override
+  int get hashCode => deepHash(fields);
+}
+
+/// Helper to create the JSON structure of constants by storing the value with
+/// the type.
+Map<String, Object?> _toJson(String type, Object? value) {
+  return {_typeKey: type, if (value != null) _valueKey: value};
+}
diff --git a/pkg/record_use/lib/src/definition.dart b/pkg/record_use/lib/src/definition.dart
new file mode 100644
index 0000000..ffc04ff
--- /dev/null
+++ b/pkg/record_use/lib/src/definition.dart
@@ -0,0 +1,42 @@
+// 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 'identifier.dart' show Identifier;
+
+/// A defintion is an [identifier] with its [loadingUnit].
+class Definition {
+  final Identifier identifier;
+  final String? loadingUnit;
+
+  const Definition({required this.identifier, this.loadingUnit});
+
+  static const _identifierKey = 'identifier';
+  static const _loadingUnitKey = 'loading_unit';
+
+  factory Definition.fromJson(Map<String, Object?> json) {
+    return Definition(
+      identifier: Identifier.fromJson(
+        json[_identifierKey] as Map<String, Object?>,
+      ),
+      loadingUnit: json[_loadingUnitKey] as String?,
+    );
+  }
+
+  Map<String, Object?> toJson() => {
+    _identifierKey: identifier.toJson(),
+    if (loadingUnit != null) _loadingUnitKey: loadingUnit,
+  };
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+
+    return other is Definition &&
+        other.identifier == identifier &&
+        other.loadingUnit == loadingUnit;
+  }
+
+  @override
+  int get hashCode => Object.hash(identifier, loadingUnit);
+}
diff --git a/pkg/record_use/lib/src/identifier.dart b/pkg/record_use/lib/src/identifier.dart
new file mode 100644
index 0000000..b50a730
--- /dev/null
+++ b/pkg/record_use/lib/src/identifier.dart
@@ -0,0 +1,68 @@
+// 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.
+
+/// Represents a unique identifier for a code element, such as a class, method,
+/// or field, within a Dart program.
+///
+/// An [Identifier] is used to pinpoint a specific element based on its
+/// location and name. It consists of:
+///
+/// - `importUri`: The URI of the library where the element is defined.
+/// - `parent`: The name of the parent element (e.g., the class name for a
+///   method or field). This is optional, as not all elements have parents (e.g.
+///   top-level functions).
+/// - `name`: The name of the element itself.
+class Identifier {
+  /// The URI of the library where the element is defined.
+  ///
+  /// This is given in the form of its package import uri, so that it is OS- and
+  /// user independent.
+  final String importUri;
+
+  /// The name of the parent element (e.g., the class name for a method or
+  /// field). This is optional, as not all elements have parents (e.g. top-level
+  /// functions).
+  final String? scope;
+
+  /// The name of the element itself.
+  final String name;
+
+  /// Creates an [Identifier] object.
+  ///
+  /// [importUri] is the URI of the library where the element is defined.
+  /// [scope] is the optional name of the parent element.
+  /// [name] is the name of the element.
+  const Identifier({required this.importUri, this.scope, required this.name});
+
+  static const String _uriKey = 'uri';
+  static const String _scopeKey = 'scope';
+  static const String _nameKey = 'name';
+
+  /// Creates an [Identifier] object from its JSON representation.
+  factory Identifier.fromJson(Map<String, Object?> json) => Identifier(
+    importUri: json[_uriKey] as String,
+    scope: json[_scopeKey] as String?,
+    name: json[_nameKey] as String,
+  );
+
+  /// Converts this [Identifier] object to a JSON representation.
+  Map<String, Object?> toJson() => {
+    _uriKey: importUri,
+    if (scope != null) _scopeKey: scope,
+    _nameKey: name,
+  };
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+
+    return other is Identifier &&
+        other.importUri == importUri &&
+        other.scope == scope &&
+        other.name == name;
+  }
+
+  @override
+  int get hashCode => Object.hash(importUri, scope, name);
+}
diff --git a/pkg/record_use/lib/src/internal/definition.dart b/pkg/record_use/lib/src/internal/definition.dart
deleted file mode 100644
index 5b53b32..0000000
--- a/pkg/record_use/lib/src/internal/definition.dart
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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 '../public/identifier.dart';
-import '../public/location.dart';
-
-class Definition {
-  final Identifier identifier;
-
-  /// Represents the '@' field in the JSON
-  final Location location;
-  final String? loadingUnit;
-
-  const Definition({
-    required this.identifier,
-    required this.location,
-    this.loadingUnit,
-  });
-
-  factory Definition.fromJson(
-    Map<String, dynamic> json,
-    List<Identifier> identifiers,
-    List<String> uris,
-  ) {
-    final identifier = identifiers[json['id'] as int];
-    return Definition(
-      identifier: identifier,
-      location: Location.fromJson(json['@'] as Map<String, dynamic>, uris),
-      loadingUnit: json['loadingUnit'] as String?,
-    );
-  }
-
-  Map<String, dynamic> toJson(
-    Map<Identifier, int> identifiers,
-    Map<String, int> uris,
-  ) =>
-      {
-        'id': identifiers[identifier]!,
-        '@': location.toJson(uris),
-        'loadingUnit': loadingUnit,
-      };
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    return other is Definition &&
-        other.identifier == identifier &&
-        other.location == location &&
-        other.loadingUnit == loadingUnit;
-  }
-
-  @override
-  int get hashCode => Object.hash(identifier, location, loadingUnit);
-}
diff --git a/pkg/record_use/lib/src/internal/usage.dart b/pkg/record_use/lib/src/internal/usage.dart
deleted file mode 100644
index ff8b093..0000000
--- a/pkg/record_use/lib/src/internal/usage.dart
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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 '../helper.dart';
-import '../public/constant.dart';
-import '../public/identifier.dart';
-import '../public/reference.dart';
-import 'definition.dart';
-
-class Usage<T extends Reference> {
-  final Definition definition;
-  final List<T> references;
-
-  const Usage({
-    required this.definition,
-    required this.references,
-  });
-
-  factory Usage.fromJson(
-    Map<String, dynamic> json,
-    List<Identifier> identifiers,
-    List<String> uris,
-    List<Constant> constants,
-    T Function(Map<String, dynamic>, List<String>, List<Constant>) constr,
-  ) =>
-      Usage(
-        definition: Definition.fromJson(
-          json['definition'] as Map<String, dynamic>,
-          identifiers,
-          uris,
-        ),
-        references: (json['references'] as List)
-            .map((x) => constr(x as Map<String, dynamic>, uris, constants))
-            .toList(),
-      );
-
-  Map<String, dynamic> toJson(
-    Map<Identifier, int> identifiers,
-    Map<String, int> uris,
-    Map<Constant, int> constants,
-  ) =>
-      {
-        'definition': definition.toJson(identifiers, uris),
-        'references': references.map((x) => x.toJson(uris, constants)).toList(),
-      };
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    return other is Usage<T> &&
-        other.definition == definition &&
-        deepEquals(other.references, references);
-  }
-
-  @override
-  int get hashCode => Object.hash(definition, deepHash(references));
-}
diff --git a/pkg/record_use/lib/src/internal/usage_record.dart b/pkg/record_use/lib/src/internal/usage_record.dart
deleted file mode 100644
index ba63a3a..0000000
--- a/pkg/record_use/lib/src/internal/usage_record.dart
+++ /dev/null
@@ -1,147 +0,0 @@
-// 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:collection/collection.dart';
-
-import '../helper.dart';
-import '../public/arguments.dart';
-import '../public/constant.dart';
-import '../public/identifier.dart';
-import '../public/metadata.dart';
-import '../public/reference.dart';
-import 'usage.dart';
-
-class UsageRecord {
-  final Metadata metadata;
-  final List<Usage<CallReference>> calls;
-  final List<Usage<InstanceReference>> instances;
-
-  const UsageRecord({
-    required this.metadata,
-    required this.calls,
-    required this.instances,
-  });
-
-  factory UsageRecord.fromJson(Map<String, dynamic> json) {
-    final uris = (json['uris'] as List).cast<String>();
-
-    final identifiers = (json['ids'] as List)
-        .whereType<Map<String, dynamic>>()
-        .map(
-          (e) => Identifier.fromJson(e, uris),
-        )
-        .toList();
-
-    final constants = <Constant>[];
-    for (var constantJsonObj in json['constants'] as List) {
-      var constantJson = constantJsonObj as Map<String, dynamic>;
-      constants.add(Constant.fromJson(constantJson, constants));
-    }
-
-    return UsageRecord(
-      metadata: Metadata.fromJson(json['metadata'] as Map<String, dynamic>),
-      calls: (json['calls'] as List?)
-              ?.map((x) => Usage.fromJson(
-                    x as Map<String, dynamic>,
-                    identifiers,
-                    uris,
-                    constants,
-                    CallReference.fromJson,
-                  ))
-              .toList() ??
-          [],
-      instances: (json['instances'] as List?)
-              ?.map((x) => Usage.fromJson(
-                    x as Map<String, dynamic>,
-                    identifiers,
-                    uris,
-                    constants,
-                    InstanceReference.fromJson,
-                  ))
-              .toList() ??
-          [],
-    );
-  }
-
-  Map<String, dynamic> toJson() {
-    final identifiers = <Identifier>{
-      ...calls.map((call) => call.definition.identifier),
-      ...instances.map((instance) => instance.definition.identifier),
-    }.asMapToIndices;
-
-    final uris = <String>{
-      ...identifiers.keys.map((e) => e.importUri),
-      ...calls.expand((call) => [
-            call.definition.location.uri,
-            ...call.references.map((reference) => reference.location.uri),
-          ]),
-      ...instances.expand((instance) => [
-            instance.definition.location.uri,
-            ...instance.references.map((reference) => reference.location.uri),
-          ]),
-    }.asMapToIndices;
-
-    final constants = {
-      ...calls.expand((e) => e.references
-          .map((e) => e.arguments?.constArguments)
-          .whereType<ConstArguments>()
-          .expand((e) => {...e.named.values, ...e.positional.values})),
-      ...instances.expand((element) => element.references).expand((e) => {
-            ...e.instanceConstant.fields.values,
-            e.instanceConstant,
-          })
-    }.flatten().asMapToIndices;
-    return {
-      'metadata': metadata.toJson(),
-      'uris': uris.keys.toList(),
-      'ids': identifiers.keys
-          .map((identifier) => identifier.toJson(uris))
-          .toList(),
-      'constants':
-          constants.keys.map((constant) => constant.toJson(constants)).toList(),
-      if (calls.isNotEmpty)
-        'calls': calls
-            .map((reference) => reference.toJson(identifiers, uris, constants))
-            .toList(),
-      if (instances.isNotEmpty)
-        'instances': instances
-            .map((reference) => reference.toJson(identifiers, uris, constants))
-            .toList(),
-    };
-  }
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    return other is UsageRecord &&
-        other.metadata == metadata &&
-        deepEquals(other.calls, calls) &&
-        deepEquals(other.instances, instances);
-  }
-
-  @override
-  int get hashCode =>
-      Object.hash(metadata, deepHash(calls), deepHash(instances));
-}
-
-extension on Iterable<Constant> {
-  Set<Constant> flatten() {
-    final constants = <Constant>{};
-    for (var constant in this) {
-      constants.addAll(switch (constant) {
-        ListConstant<Constant> list => [...list.value.flatten(), list],
-        MapConstant<Constant> map => [...map.value.values.flatten(), map],
-        Constant() => {constant},
-      });
-    }
-    return constants;
-  }
-}
-
-extension _PrivateIterableExtension<T> on Iterable<T> {
-  Map<T, int> get asMapToIndices => Map.fromEntries(
-        mapIndexed((index, uri) => MapEntry(uri, index)),
-      );
-}
diff --git a/pkg/record_use/lib/src/location.dart b/pkg/record_use/lib/src/location.dart
new file mode 100644
index 0000000..73ce20605
--- /dev/null
+++ b/pkg/record_use/lib/src/location.dart
@@ -0,0 +1,44 @@
+// 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.
+
+class Location {
+  final String uri;
+  final int? line;
+  final int? column;
+
+  const Location({required this.uri, this.line, this.column});
+
+  static const _uriKey = 'uri';
+  static const _lineKey = 'line';
+  static const _columnKey = 'column';
+
+  factory Location.fromJson(Map<String, Object?> map) {
+    return Location(
+      uri: map[_uriKey] as String,
+      line: map[_lineKey] as int?,
+      column: map[_columnKey] as int?,
+    );
+  }
+
+  Map<String, Object?> toJson() {
+    return {
+      _uriKey: uri,
+      if (line != null) _lineKey: line,
+      if (line != null) _columnKey: column,
+    };
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+
+    return other is Location &&
+        other.uri == uri &&
+        other.line == line &&
+        other.column == column;
+  }
+
+  @override
+  int get hashCode => Object.hash(uri, line, column);
+}
diff --git a/pkg/record_use/lib/src/metadata.dart b/pkg/record_use/lib/src/metadata.dart
new file mode 100644
index 0000000..819b614
--- /dev/null
+++ b/pkg/record_use/lib/src/metadata.dart
@@ -0,0 +1,41 @@
+// 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:pub_semver/pub_semver.dart';
+
+import 'helper.dart';
+
+/// Metadata attached to a recorded usages file.
+///
+/// Whatever [Metadata] should be added to the usage recording. Care should be
+/// applied to not include non-deterministic or dynamic data such as timestamps,
+/// as this would mess with the usage recording caching.
+class Metadata {
+  /// The underlying data.
+  ///
+  /// Together with the metadata extension [MetadataExt], this makes the
+  /// metadata extensible by the user implementing the recording. For example,
+  /// dart2js might want to store different metadata than the Dart VM.
+  final Map<String, Object?> json;
+
+  const Metadata._({required this.json});
+
+  factory Metadata.fromJson(Map<String, Object?> json) =>
+      Metadata._(json: json);
+
+  @override
+  bool operator ==(covariant Metadata other) {
+    if (identical(this, other)) return true;
+
+    return deepEquals(other.json, json);
+  }
+
+  @override
+  int get hashCode => deepHash(json);
+}
+
+extension MetadataExt on Metadata {
+  Version get version => Version.parse(json['version'] as String);
+  String get comment => json['comment'] as String;
+}
diff --git a/pkg/record_use/lib/src/public/arguments.dart b/pkg/record_use/lib/src/public/arguments.dart
deleted file mode 100644
index 8b20ea3..0000000
--- a/pkg/record_use/lib/src/public/arguments.dart
+++ /dev/null
@@ -1,138 +0,0 @@
-// 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 '../helper.dart';
-import 'constant.dart';
-
-class Arguments {
-  final ConstArguments constArguments;
-  final NonConstArguments nonConstArguments;
-
-  const Arguments({
-    ConstArguments? constArguments,
-    NonConstArguments? nonConstArguments,
-  })  : constArguments = constArguments ?? const ConstArguments(),
-        nonConstArguments = nonConstArguments ?? const NonConstArguments();
-
-  factory Arguments.fromJson(
-    Map<String, dynamic> json,
-    List<Constant> constants,
-  ) {
-    final constJson = json['const'] as Map<String, dynamic>?;
-    final nonConstJson = json['nonConst'] as Map<String, dynamic>?;
-    return Arguments(
-      constArguments: constJson != null
-          ? ConstArguments.fromJson(constJson, constants)
-          : null,
-      nonConstArguments: nonConstJson != null
-          ? NonConstArguments.fromJson(nonConstJson)
-          : null,
-    );
-  }
-
-  Map<String, dynamic> toJson(Map<Constant, int> constants) {
-    final hasConst =
-        constArguments.named.isNotEmpty || constArguments.positional.isNotEmpty;
-    final hasNonConst = nonConstArguments.named.isNotEmpty ||
-        nonConstArguments.positional.isNotEmpty;
-    return {
-      if (hasConst) 'const': constArguments.toJson(constants),
-      if (hasNonConst) 'nonConst': nonConstArguments.toJson(),
-    };
-  }
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    return other is Arguments &&
-        other.constArguments == constArguments &&
-        other.nonConstArguments == nonConstArguments;
-  }
-
-  @override
-  int get hashCode => Object.hash(constArguments, nonConstArguments);
-}
-
-class ConstArguments {
-  final Map<int, Constant> positional;
-  final Map<String, Constant> named;
-
-  const ConstArguments(
-      {Map<int, Constant>? positional, Map<String, Constant>? named})
-      : named = named ?? const {},
-        positional = positional ?? const {};
-
-  factory ConstArguments.fromJson(
-    Map<String, dynamic> json,
-    List<Constant> constants,
-  ) =>
-      ConstArguments(
-        positional: json['positional'] != null
-            ? (json['positional'] as Map<String, dynamic>).map((position,
-                    constantIndex) =>
-                MapEntry(int.parse(position), constants[constantIndex as int]))
-            : {},
-        named: json['named'] != null
-            ? (json['named'] as Map<String, dynamic>).map(
-                (name, constantIndex) =>
-                    MapEntry(name, constants[constantIndex as int]))
-            : {},
-      );
-
-  Map<String, dynamic> toJson(Map<Constant, int> constants) => {
-        if (positional.isNotEmpty)
-          'positional': positional.map((position, constantIndex) =>
-              MapEntry(position.toString(), constants[constantIndex]!)),
-        if (named.isNotEmpty)
-          'named': named.map((name, constantIndex) =>
-              MapEntry(name, constants[constantIndex]!)),
-      };
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    return other is ConstArguments &&
-        deepEquals(other.positional, positional) &&
-        deepEquals(other.named, named);
-  }
-
-  @override
-  int get hashCode => Object.hash(deepHash(positional), deepHash(named));
-}
-
-class NonConstArguments {
-  final List<int> positional;
-  final List<String> named;
-
-  const NonConstArguments({List<int>? positional, List<String>? named})
-      : named = named ?? const [],
-        positional = positional ?? const [];
-
-  factory NonConstArguments.fromJson(Map<String, dynamic> json) =>
-      NonConstArguments(
-        positional: json['positional'] != null
-            ? (json['positional'] as List).cast()
-            : <int>[],
-        named: json['named'] != null ? (json['named'] as List).cast() : [],
-      );
-
-  Map<String, dynamic> toJson() => {
-        if (positional.isNotEmpty) 'positional': positional,
-        if (named.isNotEmpty) 'named': named,
-      };
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    return other is NonConstArguments &&
-        deepEquals(other.positional, positional) &&
-        deepEquals(other.named, named);
-  }
-
-  @override
-  int get hashCode => Object.hash(deepHash(positional), deepHash(named));
-}
diff --git a/pkg/record_use/lib/src/public/constant.dart b/pkg/record_use/lib/src/public/constant.dart
deleted file mode 100644
index 2336475..0000000
--- a/pkg/record_use/lib/src/public/constant.dart
+++ /dev/null
@@ -1,184 +0,0 @@
-// 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 '../helper.dart';
-
-sealed class Constant {
-  const Constant();
-
-  Map<String, dynamic> toJson(Map<Constant, int> constants);
-
-  static Constant fromJson(
-          Map<String, dynamic> value, List<Constant> constants) =>
-      switch (value['type'] as String) {
-        NullConstant._type => const NullConstant(),
-        BoolConstant._type => BoolConstant(value['value'] as bool),
-        IntConstant._type => IntConstant(value['value'] as int),
-        StringConstant._type => StringConstant(value['value'] as String),
-        ListConstant._type => ListConstant((value['value'] as List<dynamic>)
-            .map((value) => value as int)
-            .map((value) => constants[value])
-            .toList()),
-        MapConstant._type => MapConstant(
-            (value['value'] as Map<String, dynamic>)
-                .map((key, value) => MapEntry(key, constants[value as int]))),
-        InstanceConstant._type => InstanceConstant(
-            fields: (value['value'] as Map<String, dynamic>)
-                .map((key, value) => MapEntry(key, constants[value as int]))),
-        String() =>
-          throw UnimplementedError('This type is not a supported constant'),
-      };
-}
-
-final class NullConstant extends Constant {
-  static const _type = 'Null';
-
-  const NullConstant() : super();
-
-  @override
-  Map<String, dynamic> toJson(Map<Constant, int> constants) =>
-      _toJson(_type, null);
-}
-
-sealed class PrimitiveConstant<T extends Object> extends Constant {
-  final T value;
-
-  const PrimitiveConstant(this.value);
-
-  @override
-  int get hashCode => value.hashCode;
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    return other is PrimitiveConstant<T> && other.value == value;
-  }
-
-  @override
-  Map<String, dynamic> toJson(Map<Constant, int> constants) => valueToJson();
-
-  Map<String, dynamic> valueToJson();
-}
-
-final class BoolConstant extends PrimitiveConstant<bool> {
-  static const _type = 'bool';
-
-  const BoolConstant(super.value);
-
-  @override
-  Map<String, dynamic> valueToJson() => _toJson(_type, value);
-}
-
-final class IntConstant extends PrimitiveConstant<int> {
-  static const _type = 'int';
-
-  const IntConstant(super.value);
-
-  @override
-  Map<String, dynamic> valueToJson() => _toJson(_type, value);
-}
-
-final class StringConstant extends PrimitiveConstant<String> {
-  static const _type = 'String';
-
-  const StringConstant(super.value);
-
-  @override
-  Map<String, dynamic> valueToJson() => _toJson(_type, value);
-}
-
-final class ListConstant<T extends Constant> extends Constant {
-  static const _type = 'list';
-
-  final List<T> value;
-
-  const ListConstant(this.value);
-
-  @override
-  int get hashCode => deepHash(value);
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    return other is ListConstant && deepEquals(other.value, value);
-  }
-
-  @override
-  Map<String, dynamic> toJson(Map<Constant, int> constants) => _toJson(
-        _type,
-        value.map((constant) => constants[constant]).toList(),
-      );
-}
-
-final class MapConstant<T extends Constant> extends Constant {
-  static const _type = 'map';
-
-  final Map<String, T> value;
-
-  const MapConstant(this.value);
-
-  @override
-  int get hashCode => deepHash(value);
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    return other is MapConstant && deepEquals(other.value, value);
-  }
-
-  @override
-  Map<String, dynamic> toJson(Map<Constant, int> constants) => _toJson(
-        _type,
-        value.map((key, constant) => MapEntry(key, constants[constant]!)),
-      );
-}
-
-final class InstanceConstant extends Constant {
-  static const _type = 'Instance';
-
-  final Map<String, Constant> fields;
-
-  const InstanceConstant({
-    required this.fields,
-  });
-
-  factory InstanceConstant.fromJson(
-    Map<String, dynamic> json,
-    List<Constant> constants,
-  ) {
-    return InstanceConstant(
-      fields: json.map((key, constantIndex) =>
-          MapEntry(key, constants[constantIndex as int])),
-    );
-  }
-
-  @override
-  Map<String, dynamic> toJson(Map<Constant, int> constants) => _toJson(
-        _type,
-        fields.isNotEmpty
-            ? fields.map((name, constantIndex) =>
-                MapEntry(name, constants[constantIndex]!))
-            : null,
-      );
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    return other is InstanceConstant && deepEquals(other.fields, fields);
-  }
-
-  @override
-  int get hashCode => deepHash(fields);
-}
-
-Map<String, dynamic> _toJson(String type, Object? value) {
-  return {
-    'type': type,
-    if (value != null) 'value': value,
-  };
-}
diff --git a/pkg/record_use/lib/src/public/identifier.dart b/pkg/record_use/lib/src/public/identifier.dart
deleted file mode 100644
index 18bf720..0000000
--- a/pkg/record_use/lib/src/public/identifier.dart
+++ /dev/null
@@ -1,41 +0,0 @@
-// 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.
-
-class Identifier {
-  final String importUri;
-  final String? parent; // Optional since not all elements have parents
-  final String name;
-
-  const Identifier({
-    required this.importUri,
-    this.parent,
-    required this.name,
-  });
-
-  factory Identifier.fromJson(Map<String, dynamic> json, List<String> uris) =>
-      Identifier(
-        importUri: uris[json['uri'] as int],
-        parent: json['parent'] as String?,
-        name: json['name'] as String,
-      );
-
-  Map<String, dynamic> toJson(Map<String, int> uris) => {
-        'uri': uris[importUri]!,
-        if (parent != null) 'parent': parent,
-        'name': name,
-      };
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    return other is Identifier &&
-        other.importUri == importUri &&
-        other.parent == parent &&
-        other.name == name;
-  }
-
-  @override
-  int get hashCode => Object.hash(importUri, parent, name);
-}
diff --git a/pkg/record_use/lib/src/public/location.dart b/pkg/record_use/lib/src/public/location.dart
deleted file mode 100644
index f0ef6c1..0000000
--- a/pkg/record_use/lib/src/public/location.dart
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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.
-
-class Location {
-  final String uri;
-  final int line;
-  final int column;
-
-  const Location({
-    required this.uri,
-    required this.line,
-    required this.column,
-  });
-
-  factory Location.fromJson(Map<String, dynamic> map, List<String> uris) {
-    return Location(
-      uri: uris[map['uri'] as int],
-      line: map['line'] as int,
-      column: map['column'] as int,
-    );
-  }
-
-  Map<String, dynamic> toJson(Map<String, int> uris) {
-    return {
-      'uri': uris[uri]!,
-      'line': line,
-      'column': column,
-    };
-  }
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    return other is Location &&
-        other.uri == uri &&
-        other.line == line &&
-        other.column == column;
-  }
-
-  @override
-  int get hashCode => Object.hash(uri, line, column);
-}
diff --git a/pkg/record_use/lib/src/public/metadata.dart b/pkg/record_use/lib/src/public/metadata.dart
deleted file mode 100644
index 62b4e70..0000000
--- a/pkg/record_use/lib/src/public/metadata.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// 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:pub_semver/pub_semver.dart';
-
-class Metadata {
-  final String? comment;
-  final Version version;
-
-  const Metadata({
-    this.comment,
-    required this.version,
-  });
-
-  factory Metadata.fromJson(Map<String, dynamic> json) => Metadata(
-        comment: json['comment'] as String?,
-        version: Version.parse(json['version'] as String),
-      );
-
-  Map<String, dynamic> toJson() => {
-        if (comment != null) 'comment': comment,
-        'version': version.toString(),
-      };
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    return other is Metadata &&
-        other.comment == comment &&
-        other.version == version;
-  }
-
-  @override
-  int get hashCode => Object.hash(comment, version);
-}
diff --git a/pkg/record_use/lib/src/public/reference.dart b/pkg/record_use/lib/src/public/reference.dart
deleted file mode 100644
index 0894380..0000000
--- a/pkg/record_use/lib/src/public/reference.dart
+++ /dev/null
@@ -1,130 +0,0 @@
-// 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 'arguments.dart';
-import 'constant.dart';
-import 'location.dart';
-
-sealed class Reference {
-  final String? loadingUnit;
-
-  /// Represents the "@" field in the JSON
-  final Location location;
-
-  const Reference({this.loadingUnit, required this.location});
-
-  Map<String, dynamic> toJson(
-    Map<String, int> uris,
-    Map<Constant, int> constants,
-  ) =>
-      {
-        'loadingUnit': loadingUnit,
-        '@': location.toJson(uris),
-      };
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    return other is Reference &&
-        other.loadingUnit == loadingUnit &&
-        other.location == location;
-  }
-
-  @override
-  int get hashCode => Object.hash(loadingUnit, location);
-}
-
-final class CallReference extends Reference {
-  final Arguments? arguments;
-
-  const CallReference({
-    required this.arguments,
-    super.loadingUnit,
-    required super.location,
-  });
-
-  factory CallReference.fromJson(
-    Map<String, dynamic> json,
-    List<String> uris,
-    List<Constant> constants,
-  ) {
-    return CallReference(
-      arguments: json['arguments'] != null
-          ? Arguments.fromJson(
-              json['arguments'] as Map<String, dynamic>, constants)
-          : null,
-      loadingUnit: json['loadingUnit'] as String?,
-      location: Location.fromJson(json['@'] as Map<String, dynamic>, uris),
-    );
-  }
-
-  @override
-  Map<String, dynamic> toJson(
-    Map<String, int> uris,
-    Map<Constant, int> constants,
-  ) {
-    final argumentJson = arguments?.toJson(constants) ?? {};
-    return {
-      if (argumentJson.isNotEmpty) 'arguments': argumentJson,
-      ...super.toJson(uris, constants),
-    };
-  }
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-    if (!(super == other)) return false;
-
-    return other is CallReference && other.arguments == arguments;
-  }
-
-  @override
-  int get hashCode => Object.hash(arguments, super.hashCode);
-}
-
-final class InstanceReference extends Reference {
-  final InstanceConstant instanceConstant;
-
-  const InstanceReference({
-    super.loadingUnit,
-    required super.location,
-    required this.instanceConstant,
-  });
-
-  factory InstanceReference.fromJson(
-    Map<String, dynamic> json,
-    List<String> uris,
-    List<Constant> constants,
-  ) {
-    return InstanceReference(
-      instanceConstant:
-          constants[json['instanceConstant'] as int] as InstanceConstant,
-      loadingUnit: json['loadingUnit'] as String?,
-      location: Location.fromJson(json['@'] as Map<String, dynamic>, uris),
-    );
-  }
-
-  @override
-  Map<String, dynamic> toJson(
-    Map<String, int> uris,
-    Map<Constant, int> constants,
-  ) =>
-      {
-        'instanceConstant': constants[instanceConstant]!,
-        ...super.toJson(uris, constants),
-      };
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-    if (!(super == other)) return false;
-
-    return other is InstanceReference &&
-        other.instanceConstant == instanceConstant;
-  }
-
-  @override
-  int get hashCode => Object.hash(instanceConstant, super.hashCode);
-}
diff --git a/pkg/record_use/lib/src/record_use.dart b/pkg/record_use/lib/src/record_use.dart
index bb6f192..f4cbcf66 100644
--- a/pkg/record_use/lib/src/record_use.dart
+++ b/pkg/record_use/lib/src/record_use.dart
@@ -2,27 +2,24 @@
 // 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:collection/collection.dart';
+import '../record_use_internal.dart';
 
-import 'internal/usage.dart';
-import 'internal/usage_record.dart';
-import 'public/arguments.dart';
-import 'public/identifier.dart';
-import 'public/metadata.dart';
-import 'public/reference.dart';
-
-extension type RecordedUsages._(UsageRecord _usages) {
-  RecordedUsages.fromJson(Map<String, dynamic> json)
-      : this._(UsageRecord.fromJson(json));
+/// Holds all information recorded during compilation.
+///
+/// This can be queried using the methods provided, which each take an
+/// [Identifier] which must be annotated with `@RecordUse` from `package:meta`.
+extension type RecordedUsages._(Recordings _recordings) {
+  RecordedUsages.fromJson(Map<String, Object?> json)
+    : this._(Recordings.fromJson(json));
 
   /// Show the metadata for this recording of usages.
-  Metadata get metadata => _usages.metadata;
+  Metadata get metadata => _recordings.metadata;
 
-  /// Finds all const arguments for calls to the [method].
+  /// Finds all const arguments for calls to the [identifier].
   ///
   /// The definition must be annotated with `@RecordUse()`. If there are no
   /// calls to the definition, either because it was treeshaken, because it was
-  /// not annotated, or because it does not exist, returns `null`.
+  /// not annotated, or because it does not exist, returns empty.
   ///
   /// Returns an empty iterable if the arguments were not collected.
   ///
@@ -48,20 +45,32 @@
   ///           parent: 'SomeClass',
   ///           name: 'someStaticMethod'),
   ///       ).first ==
-  ///       Arguments(
-  ///         constArguments: ConstArguments(positional: {1: IntConstant(42)}),
-  ///       );
+  ///       [
+  ///         {1: 42}
+  ///       ]
   /// ```
-  Iterable<Arguments>? argumentsTo(Identifier method) => _callTo(method)
-      ?.references
-      .map((reference) => reference.arguments)
-      .whereType();
+  Iterable<({Map<String, Object?> named, List<Object?> positional})>
+  constArgumentsFor(Identifier identifier, String signature) {
+    return _recordings.calls[identifier]?.whereType<CallWithArguments>().map((
+          call,
+        ) {
+          final (:named, :positional) = Signature.parseMethodSignature(
+            signature,
+          ).parseArguments(call);
+          named.removeWhere((key, value) => value == null);
+          return (
+            named: named.map((key, value) => MapEntry(key, value?.toValue())),
+            positional: positional.nonNulls.map((e) => e.toValue()).toList(),
+          );
+        }) ??
+        [];
+  }
 
-  /// Finds all fields of a const instance of the class at [classIdentifier].
+  /// Finds all constant fields of a const instance of the class [identifier].
   ///
   /// The definition must be annotated with `@RecordUse()`. If there are
   /// no instances of the definition, either because it was treeshaken, because
-  /// it was not annotated, or because it does not exist, returns `null`.
+  /// it was not annotated, or because it does not exist, returns empty.
   ///
   /// The types of fields supported are defined at
   ///
@@ -78,7 +87,7 @@
   ///   }
   /// }
   ///
-  /// @ResourceIdentifier()
+  /// @RecordUse()
   /// class AnnotationClass {
   ///   final String s;
   ///   const AnnotationClass(this.s);
@@ -87,40 +96,46 @@
   ///
   /// Would mean that
   /// ```
-  /// instancesOf(Identifier(
+  /// constantsOf(Identifier(
   ///           uri: 'path/to/file.dart',
   ///           name: 'AnnotationClass'),
-  ///       ).first.instanceConstant ==
-  ///       [
-  ///         InstanceConstant(fields: {'s': 'freddie'})
-  ///       ];
+  ///       ).first['s'] == 'freddie';
   /// ```
   ///
   /// What kinds of fields can be recorded depends on the implementation of
   /// https://dart-review.googlesource.com/c/sdk/+/369620/13/pkg/vm/lib/transformations/record_use/record_instance.dart
-  Iterable<InstanceReference>? instancesOf(Identifier classIdentifier) =>
-      _usages.instances
-          .firstWhereOrNull(
-              (instance) => instance.definition.identifier == classIdentifier)
-          ?.references;
+  Iterable<ConstantInstance> constantsOf(Identifier identifier) {
+    return _recordings.instances[identifier]?.map(
+          (reference) => ConstantInstance(reference.instanceConstant.fields),
+        ) ??
+        [];
+  }
 
-  /// Checks if any call to [method] has non-const arguments.
+  /// Checks if any call to [identifier] has non-const arguments, or if any
+  /// tear-off was recorded.
   ///
   /// The definition must be annotated with `@RecordUse()`. If there are no
   /// calls to the definition, either because it was treeshaken, because it was
   /// not annotated, or because it does not exist, returns `false`.
-  bool hasNonConstArguments(Identifier method) =>
-      _callTo(method)?.references.any(
-        (reference) {
-          final nonConstArguments = reference.arguments?.nonConstArguments;
-          final hasNamed = nonConstArguments?.named.isNotEmpty ?? false;
-          final hasPositional =
-              nonConstArguments?.positional.isNotEmpty ?? false;
-          return hasNamed || hasPositional;
-        },
-      ) ??
-      false;
+  bool hasNonConstArguments(Identifier identifier) {
+    return (_recordings.calls[identifier] ?? []).any(
+      (element) => switch (element) {
+        CallTearOff() => true,
+        CallWithArguments call => call.positionalArguments.any(
+          (argument) => argument == null,
+        ),
+      },
+    );
+  }
+}
 
-  Usage<CallReference>? _callTo(Identifier definition) => _usages.calls
-      .firstWhereOrNull((call) => call.definition.identifier == definition);
+extension type ConstantInstance(Map<String, Constant> _fields) {
+  bool hasField(String key) => _fields.containsKey(key);
+
+  Object? operator [](String key) {
+    if (!hasField(key)) {
+      throw ArgumentError('No field with name $key found.');
+    }
+    return _fields[key]!.toValue();
+  }
 }
diff --git a/pkg/record_use/lib/src/recordings.dart b/pkg/record_use/lib/src/recordings.dart
new file mode 100644
index 0000000..01349e4
--- /dev/null
+++ b/pkg/record_use/lib/src/recordings.dart
@@ -0,0 +1,237 @@
+// ignore_for_file: public_member_api_docs, sort_constructors_first
+// 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 'constant.dart';
+import 'definition.dart';
+import 'helper.dart';
+import 'identifier.dart';
+import 'location.dart' show Location;
+import 'metadata.dart';
+import 'reference.dart';
+
+/// [Recordings] combines recordings of calls and instances with metadata.
+///
+/// This class acts as the top-level container for recorded usage information.
+/// The metadata provides context for the recording, such as version and
+/// commentary. The [callsForDefinition] and [instancesForDefinition] store the
+/// core data, associating each [Definition] with its corresponding [Reference]
+/// details.
+///
+/// The class uses a normalized JSON format, allowing the reuse of locations and
+/// constants across multiple recordings to optimize storage.
+class Recordings {
+  /// [Metadata] such as the recording protocol version.
+  final Metadata metadata;
+
+  /// The collected [CallReference]s for each [Definition].
+  final Map<Definition, List<CallReference>> callsForDefinition;
+
+  late final Map<Identifier, List<CallReference>> calls = callsForDefinition
+      .map((definition, calls) => MapEntry(definition.identifier, calls));
+
+  /// The collected [InstanceReference]s for each [Definition].
+  final Map<Definition, List<InstanceReference>> instancesForDefinition;
+
+  late final Map<Identifier, List<InstanceReference>> instances =
+      instancesForDefinition.map(
+        (definition, instances) => MapEntry(definition.identifier, instances),
+      );
+
+  static const _metadataKey = 'metadata';
+  static const _constantsKey = 'constants';
+  static const _locationsKey = 'locations';
+  static const _recordingsKey = 'recordings';
+  static const _callsKey = 'calls';
+  static const _instancesKey = 'instances';
+  static const _definitionKey = 'definition';
+
+  Recordings({
+    required this.metadata,
+    required this.callsForDefinition,
+    required this.instancesForDefinition,
+  });
+
+  /// Decodes a JSON representation into a [Recordings] object.
+  ///
+  /// The format is specifically designed to reduce redundancy and improve
+  /// efficiency. Identifiers and constants are stored in separate tables,
+  /// allowing them to be referenced by index in the `recordings` map.
+  factory Recordings.fromJson(Map<String, Object?> json) {
+    final constants = <Constant>[];
+    for (final constantJsonObj in json[_constantsKey] as List? ?? []) {
+      final constantJson = constantJsonObj as Map<String, Object?>;
+      constants.add(Constant.fromJson(constantJson, constants));
+    }
+    final locations = <Location>[];
+    for (final locationJsonObj in json[_locationsKey] as List? ?? []) {
+      final locationJson = locationJsonObj as Map<String, Object?>;
+      locations.add(Location.fromJson(locationJson));
+    }
+
+    final recordings =
+        (json[_recordingsKey] as List?)?.whereType<Map<String, Object?>>() ??
+        [];
+    final recordedCalls = recordings.where(
+      (recording) => recording[_callsKey] != null,
+    );
+    final recordedInstances = recordings.where(
+      (recording) => recording[_instancesKey] != null,
+    );
+    return Recordings(
+      metadata: Metadata.fromJson(json[_metadataKey] as Map<String, Object?>),
+      callsForDefinition: {
+        for (final recording in recordedCalls)
+          Definition.fromJson(
+                recording[_definitionKey] as Map<String, Object?>,
+              ):
+              (recording[_callsKey] as List)
+                  .map(
+                    (json) => CallReference.fromJson(
+                      json as Map<String, Object?>,
+                      constants,
+                      locations,
+                    ),
+                  )
+                  .toList(),
+      },
+      instancesForDefinition: {
+        for (final recording in recordedInstances)
+          Definition.fromJson(
+                recording[_definitionKey] as Map<String, Object?>,
+              ):
+              (recording[_instancesKey] as List)
+                  .map(
+                    (json) => InstanceReference.fromJson(
+                      json as Map<String, Object?>,
+                      constants,
+                      locations,
+                    ),
+                  )
+                  .toList(),
+      },
+    );
+  }
+
+  /// Encodes this object into a JSON representation.
+  ///
+  /// This method normalizes identifiers and constants for storage efficiency.
+  Map<String, Object?> toJson() {
+    final constants =
+        {
+          ...callsForDefinition.values
+              .expand((element) => element)
+              .whereType<CallWithArguments>()
+              .expand(
+                (call) => [
+                  ...call.positionalArguments,
+                  ...call.namedArguments.values,
+                ],
+              )
+              .nonNulls,
+          ...instancesForDefinition.values
+              .expand((element) => element)
+              .expand(
+                (instance) => {
+                  ...instance.instanceConstant.fields.values,
+                  instance.instanceConstant,
+                },
+              ),
+        }.flatten().asMapToIndices;
+    final locations =
+        {
+          ...callsForDefinition.values
+              .expand((calls) => calls)
+              .map((call) => call.location),
+          ...instancesForDefinition.values
+              .expand((instances) => instances)
+              .map((instance) => instance.location),
+        }.asMapToIndices;
+    return {
+      _metadataKey: metadata.json,
+      if (constants.isNotEmpty)
+        _constantsKey:
+            constants.keys
+                .map((constant) => constant.toJson(constants))
+                .toList(),
+      if (locations.isNotEmpty)
+        _locationsKey:
+            locations.keys.map((location) => location.toJson()).toList(),
+      if (callsForDefinition.isNotEmpty || instancesForDefinition.isNotEmpty)
+        _recordingsKey: [
+          if (callsForDefinition.isNotEmpty)
+            ...callsForDefinition.entries.map(
+              (entry) => {
+                _definitionKey: entry.key.toJson(),
+                _callsKey:
+                    entry.value
+                        .map((call) => call.toJson(constants, locations))
+                        .toList(),
+              },
+            ),
+          if (instancesForDefinition.isNotEmpty)
+            ...instancesForDefinition.entries.map(
+              (entry) => {
+                _definitionKey: entry.key.toJson(),
+                _instancesKey:
+                    entry.value
+                        .map(
+                          (instance) => instance.toJson(constants, locations),
+                        )
+                        .toList(),
+              },
+            ),
+        ],
+    };
+  }
+
+  @override
+  bool operator ==(covariant Recordings other) {
+    if (identical(this, other)) return true;
+
+    return other.metadata == metadata &&
+        deepEquals(other.callsForDefinition, callsForDefinition) &&
+        deepEquals(other.instancesForDefinition, instancesForDefinition);
+  }
+
+  @override
+  int get hashCode => Object.hash(
+    metadata.hashCode,
+    deepHash(callsForDefinition),
+    deepHash(instancesForDefinition),
+  );
+}
+
+extension on Iterable<Constant> {
+  Set<Constant> flatten() {
+    final constants = <Constant>{};
+    for (final constant in this) {
+      depthFirstSearch(constant, constants);
+    }
+    return constants;
+  }
+
+  void depthFirstSearch(Constant constant, Set<Constant> collected) {
+    final children = switch (constant) {
+      ListConstant<Constant>() => constant.value,
+      MapConstant<Constant>() => constant.value.values,
+      InstanceConstant() => constant.fields.values,
+      _ => <Constant>[],
+    };
+    for (final child in children) {
+      if (!collected.contains(child)) {
+        depthFirstSearch(child, collected);
+      }
+    }
+    collected.add(constant);
+  }
+}
+
+extension _PrivateIterableExtension<T> on Iterable<T> {
+  /// Transform list to map, faster than using list.indexOf
+  Map<T, int> get asMapToIndices {
+    var i = 0;
+    return {for (final element in this) element: i++};
+  }
+}
diff --git a/pkg/record_use/lib/src/reference.dart b/pkg/record_use/lib/src/reference.dart
new file mode 100644
index 0000000..8cb3b96
--- /dev/null
+++ b/pkg/record_use/lib/src/reference.dart
@@ -0,0 +1,189 @@
+// 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 'constant.dart';
+import 'helper.dart';
+import 'identifier.dart';
+import 'location.dart' show Location;
+
+const _loadingUnitKey = 'loading_unit';
+
+/// A reference to *something*.
+///
+/// The something might be a call or an instance, matching a [CallReference] or
+/// an [InstanceReference].
+/// All references have in common that they occur in a [loadingUnit], which we
+/// record to be able to piece together which loading units are "related", for
+/// example all needing the same asset.
+sealed class Reference {
+  final String? loadingUnit;
+  final Location location;
+
+  const Reference({required this.loadingUnit, required this.location});
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+
+    return other is Reference &&
+        other.loadingUnit == loadingUnit &&
+        other.location == location;
+  }
+
+  @override
+  int get hashCode => Object.hash(loadingUnit, location);
+
+  Map<String, Object?> toJson(
+    Map<Constant, int> constants,
+    Map<Location, int> locations,
+  ) => {_loadingUnitKey: loadingUnit, _locationKey: locations[location]};
+}
+
+const _locationKey = '@';
+const _positionalKey = 'positional';
+const _namedKey = 'named';
+const _typeKey = 'type';
+
+/// A reference to a call to some [Identifier].
+///
+/// This might be an actual call, in which case we record the arguments, or a
+/// tear-off, in which case we can't record the arguments.
+sealed class CallReference extends Reference {
+  const CallReference({required super.loadingUnit, required super.location});
+
+  static CallReference fromJson(
+    Map<String, Object?> json,
+    List<Constant> constants,
+    List<Location> locations,
+  ) {
+    final loadingUnit = json[_loadingUnitKey] as String?;
+    final location = locations[json[_locationKey] as int];
+    return json[_typeKey] == 'tearoff'
+        ? CallTearOff(loadingUnit: loadingUnit, location: location)
+        : CallWithArguments(
+          positionalArguments:
+              (json[_positionalKey] as List<dynamic>? ?? [])
+                  .whereType<int?>()
+                  .map((index) {
+                    return index != null ? constants[index] : null;
+                  })
+                  .toList(),
+          namedArguments: (json[_namedKey] as Map<String, Object?>? ?? {}).map(
+            (key, value) =>
+                MapEntry(key, value != null ? constants[value as int] : null),
+          ),
+          loadingUnit: loadingUnit,
+          location: location,
+        );
+  }
+}
+
+/// A reference to a call to some [Identifier] with [positionalArguments] and
+/// [namedArguments].
+final class CallWithArguments extends CallReference {
+  final List<Constant?> positionalArguments;
+  final Map<String, Constant?> namedArguments;
+
+  const CallWithArguments({
+    required this.positionalArguments,
+    required this.namedArguments,
+    required super.loadingUnit,
+    required super.location,
+  });
+
+  @override
+  Map<String, Object?> toJson(
+    Map<Constant, int> constants,
+    Map<Location, int> locations,
+  ) {
+    final positionalJson =
+        positionalArguments.map((constant) => constants[constant]).toList();
+    final namedJson = namedArguments.map(
+      (name, constant) => MapEntry(name, constants[constant]),
+    );
+    return {
+      _typeKey: 'with_arguments',
+      if (positionalJson.isNotEmpty) _positionalKey: positionalJson,
+      if (namedJson.isNotEmpty) _namedKey: namedJson,
+      ...super.toJson(constants, locations),
+    };
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    if (!(super == other)) return false;
+
+    return other is CallWithArguments &&
+        deepEquals(other.positionalArguments, positionalArguments) &&
+        deepEquals(other.namedArguments, namedArguments);
+  }
+
+  @override
+  int get hashCode => Object.hash(
+    deepHash(positionalArguments),
+    deepHash(namedArguments),
+    super.hashCode,
+  );
+}
+
+/// A reference to a tear-off use of the [Identifier]. This means that we can't
+/// record the arguments possibly passed to the method somewhere else.
+final class CallTearOff extends CallReference {
+  const CallTearOff({required super.loadingUnit, required super.location});
+
+  @override
+  Map<String, Object?> toJson(
+    Map<Constant, int> constants,
+    Map<Location, int> locations,
+  ) {
+    return {_typeKey: 'tearoff', ...super.toJson(constants, locations)};
+  }
+}
+
+final class InstanceReference extends Reference {
+  final InstanceConstant instanceConstant;
+
+  const InstanceReference({
+    required this.instanceConstant,
+    required super.loadingUnit,
+    required super.location,
+  });
+
+  static const _constantKey = 'constant_index';
+
+  factory InstanceReference.fromJson(
+    Map<String, Object?> json,
+    List<Constant> constants,
+    List<Location> locations,
+  ) {
+    return InstanceReference(
+      instanceConstant:
+          constants[json[_constantKey] as int] as InstanceConstant,
+      loadingUnit: json[_loadingUnitKey] as String?,
+      location: locations[json[_locationKey] as int],
+    );
+  }
+
+  @override
+  Map<String, Object?> toJson(
+    Map<Constant, int> constants,
+    Map<Location, int> locations,
+  ) => {
+    _constantKey: constants[instanceConstant]!,
+    ...super.toJson(constants, locations),
+  };
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    if (!(super == other)) return false;
+
+    return other is InstanceReference &&
+        other.instanceConstant == instanceConstant;
+  }
+
+  @override
+  int get hashCode => Object.hash(instanceConstant, super.hashCode);
+}
diff --git a/pkg/record_use/lib/src/signature.dart b/pkg/record_use/lib/src/signature.dart
new file mode 100644
index 0000000..c89c740
--- /dev/null
+++ b/pkg/record_use/lib/src/signature.dart
@@ -0,0 +1,218 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:collection/collection.dart';
+
+import '../record_use_internal.dart' show CallWithArguments;
+import 'constant.dart';
+import 'helper.dart'; // Assuming helper.dart contains the deepEquals function
+
+/// Represents the signature of a Dart method, categorizing its parameters.
+class Signature {
+  /// List of required positional parameter names.
+  final List<String> positionalParameters;
+
+  /// List of optional positional parameter names, enclosed in `[]`.
+  final List<String> positionalOptionalParameters;
+
+  /// List of required named parameter names, preceded by `required`.
+  final List<String> namedParameters;
+
+  /// List of optional named parameter names, enclosed in `{}`.
+  final List<String> namedOptionalParameters;
+
+  /// Creates a new [Signature] instance.
+  const Signature({
+    required this.positionalParameters,
+    required this.positionalOptionalParameters,
+    required this.namedParameters,
+    required this.namedOptionalParameters,
+  });
+
+  ({List<Constant?> positional, Map<String, Constant?> named}) parseArguments(
+    CallWithArguments call,
+  ) {
+    final positionalArguments = <Constant?>[];
+    final namedArguments = <String, Constant?>{};
+    final names = [
+      ...positionalParameters,
+      ...positionalOptionalParameters,
+      ...namedParameters,
+      ...namedOptionalParameters,
+    ];
+    if (call.positionalArguments.length != names.length) {
+      throw FormatException(
+        '''
+Invalid number of arguments - $names vs ${call.positionalArguments} and ${call.namedArguments}''',
+      );
+    }
+    final sortedNames = names.sorted();
+    final mapping = <String, Constant?>{};
+    for (var i = 0; i < sortedNames.length; i++) {
+      final name = sortedNames[i];
+      mapping[name] = call.namedArguments[name] ?? call.positionalArguments[i];
+    }
+    for (var name in names) {
+      var constant = mapping[name];
+      if (positionalParameters.contains(name) ||
+          positionalOptionalParameters.contains(name)) {
+        positionalArguments.add(constant);
+      } else if (namedParameters.contains(name) ||
+          namedOptionalParameters.contains(name)) {
+        namedArguments[name] = constant;
+      }
+    }
+    return (named: namedArguments, positional: positionalArguments);
+  }
+
+  /// Parses a Dart method signature string and returns a [Signature] instance.
+  ///
+  /// The signature string should follow the standard Dart method signature
+  /// syntax, including return type, method name, and parameter list enclosed in
+  /// parentheses. This parser attempts to correctly identify positional,
+  /// optional positional, required named, and optional named parameters,
+  /// extracting only their names.
+  /// It handles basic type annotations and default values but might not cover
+  /// all edge cases of complex Dart type syntax.
+  ///
+  /// Example:
+  /// ```dart
+  /// final signatureString = '''String greet(String name,
+  /// [String? greeting = "Hello"])''';
+  /// final signature = Signature.parseMethodSignature(signatureString);
+  /// print(signature.positionalParameters); // Output: [name]
+  /// print(signature.positionalOptionalParameters); // Output: [greeting]
+  /// print(signature.namedParameters); // Output: []
+  /// print(signature.namedOptionalParameters); // Output: []
+  /// ```
+  ///
+  /// Throws a [FormatException] if the provided [signature] string does not
+  /// match the expected basic method signature format.
+  factory Signature.parseMethodSignature(String signature) {
+    var firstParensIndex = signature.indexOf('(');
+    int? lastParensIndex = signature.lastIndexOf(')');
+    if (firstParensIndex == -1 || lastParensIndex == -1) {
+      throw const FormatException('Invalid signature format');
+    }
+    final parameterString = signature
+        .substring(firstParensIndex + 1, lastParensIndex)
+        .split('\n')
+        .map((line) => line.trim())
+        .whereNot((line) => line.startsWith('//'))
+        .join('\n');
+
+    final positionalParams = <String>[];
+    final positionalOptionalParams = <String>[];
+    final namedParams = <String>[];
+    final namedOptionalParams = <String>[];
+
+    if (parameterString.isNotEmpty) {
+      var inOptionalPositional = false;
+      var inNamed = false;
+
+      var i = 0;
+      while (i < parameterString.length) {
+        var start = i;
+        var bracketCounter = 0;
+        for (; i < parameterString.length; i++) {
+          if (parameterString[i] == '<') {
+            bracketCounter++;
+          } else if (parameterString[i] == '>') {
+            bracketCounter--;
+          } else if (parameterString[i] == ',' && bracketCounter == 0) {
+            break;
+          }
+        }
+        var param = parameterString.substring(start, i);
+        i++;
+
+        param = param.trim();
+        if (param.isEmpty) {
+          continue;
+        }
+
+        if (param.startsWith('[')) {
+          inOptionalPositional = true;
+          param = param.substring(1).trim();
+        } else if (param.startsWith('{')) {
+          inNamed = true;
+          param = param.substring(1).trim();
+        }
+        if (param.endsWith(']')) {
+          param = param.substring(0, param.length - 1).trim();
+        } else if (param.endsWith('}')) {
+          param = param.substring(0, param.length - 1).trim();
+        }
+
+        if (inOptionalPositional) {
+          positionalOptionalParams.add(_extractParameterName(param));
+        } else if (inNamed) {
+          var req = 'required ';
+          if (param.startsWith(req)) {
+            namedParams.add(_extractParameterName(param.substring(req.length)));
+          } else {
+            namedOptionalParams.add(_extractParameterName(param));
+          }
+        } else {
+          positionalParams.add(_extractParameterName(param));
+        }
+      }
+    }
+
+    // Extract only the name for positional parameters
+    final positionalNames =
+        positionalParams.map(_extractParameterName).toList();
+    final positionalOptionalNames =
+        positionalOptionalParams.map(_extractParameterName).toList();
+
+    return Signature(
+      positionalParameters: positionalNames,
+      positionalOptionalParameters: positionalOptionalNames,
+      namedParameters: namedParams,
+      namedOptionalParameters: namedOptionalParams,
+    );
+  }
+
+  /// Extracts the parameter name from a parameter declaration string.
+  ///
+  /// This method splits the declaration by the `=` sign to remove default
+  /// values and then by spaces, taking the last part as the parameter name.
+  /// This is a simple heuristic and might not work perfectly for all complex
+  /// type annotations.
+  static String _extractParameterName(String parameterDeclaration) {
+    return parameterDeclaration.split('=').first.trim().split(' ').last;
+  }
+
+  @override
+  bool operator ==(Object other) =>
+      identical(this, other) ||
+      other is Signature &&
+          runtimeType == other.runtimeType &&
+          deepEquals(positionalParameters, other.positionalParameters) &&
+          deepEquals(
+            positionalOptionalParameters,
+            other.positionalOptionalParameters,
+          ) &&
+          deepEquals(namedParameters, other.namedParameters) &&
+          deepEquals(namedOptionalParameters, other.namedOptionalParameters);
+
+  @override
+  int get hashCode => Object.hash(
+    positionalParameters.hashCode,
+    positionalOptionalParameters.hashCode,
+    namedParameters.hashCode,
+    namedOptionalParameters.hashCode,
+  );
+
+  @override
+  String toString() {
+    return '''
+Signature(
+  positionalParameters: $positionalParameters,
+  positionalOptionalParameters: $positionalOptionalParameters,
+  namedParameters: $namedParameters,
+  namedOptionalParameters: $namedOptionalParameters
+)''';
+  }
+}
diff --git a/pkg/record_use/pubspec.yaml b/pkg/record_use/pubspec.yaml
index da8e87a..20fe1b9 100644
--- a/pkg/record_use/pubspec.yaml
+++ b/pkg/record_use/pubspec.yaml
@@ -1,11 +1,11 @@
 name: record_use
 description: >
   The serialization logic and API for the usage recording SDK feature.
-version: 0.3.1-wip
+version: 0.4.0
 repository: https://github.com/dart-lang/sdk/tree/main/pkg/record_use
 
 environment:
-  sdk: ^3.5.0
+  sdk: ^3.7.0
 
 resolution: workspace
 
diff --git a/pkg/record_use/test/signature_test.dart b/pkg/record_use/test/signature_test.dart
new file mode 100644
index 0000000..563368d
--- /dev/null
+++ b/pkg/record_use/test/signature_test.dart
@@ -0,0 +1,147 @@
+// Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:record_use/src/signature.dart';
+import 'package:test/test.dart';
+
+void main() {
+  group('Signature.parseMethodSignature', () {
+    test('positional and optional positional parameters', () {
+      final signature =
+          'String greet(String name, [String? greeting = "Hello"])';
+      final expected = const Signature(
+        positionalParameters: ['name'],
+        positionalOptionalParameters: ['greeting'],
+        namedParameters: [],
+        namedOptionalParameters: [],
+      );
+      expect(Signature.parseMethodSignature(signature), expected);
+    });
+
+    test('only named parameters (required and optional)', () {
+      final signature =
+          'void process({required int id, String? label, double value = 0.0})';
+      final expected = const Signature(
+        positionalParameters: [],
+        positionalOptionalParameters: [],
+        namedParameters: ['id'],
+        namedOptionalParameters: ['label', 'value'],
+      );
+      expect(Signature.parseMethodSignature(signature), expected);
+    });
+
+    test(
+      'positional and optional positional parameters (without default values)',
+      () {
+        final signature = '''
+Future<void> fetchData(String url, int retries, [bool? cache, Duration? timeout])''';
+        final expected = const Signature(
+          positionalParameters: ['url', 'retries'],
+          positionalOptionalParameters: ['cache', 'timeout'],
+          namedParameters: [],
+          namedOptionalParameters: [],
+        );
+        expect(Signature.parseMethodSignature(signature), expected);
+      },
+    );
+
+    test('positional and named parameters (with default values)', () {
+      final signature =
+          'void log(String message, {int? level = 0, DateTime? timestamp})';
+      final expected = const Signature(
+        positionalParameters: ['message'],
+        positionalOptionalParameters: [],
+        namedParameters: [],
+        namedOptionalParameters: ['level', 'timestamp'],
+      );
+      expect(Signature.parseMethodSignature(signature), expected);
+    });
+
+    test('only positional parameters', () {
+      final signature = 'int add(int a, int b)';
+      final expected = const Signature(
+        positionalParameters: ['a', 'b'],
+        positionalOptionalParameters: [],
+        namedParameters: [],
+        namedOptionalParameters: [],
+      );
+      expect(Signature.parseMethodSignature(signature), expected);
+    });
+
+    test('only optional positional parameters', () {
+      final signature = 'String format([String? prefix, String? suffix])';
+      final expected = const Signature(
+        positionalParameters: [],
+        positionalOptionalParameters: ['prefix', 'suffix'],
+        namedParameters: [],
+        namedOptionalParameters: [],
+      );
+      expect(Signature.parseMethodSignature(signature), expected);
+    });
+
+    test('only required named parameters', () {
+      final signature =
+          'void config({required String apiKey, required String apiUrl})';
+      final expected = const Signature(
+        positionalParameters: [],
+        positionalOptionalParameters: [],
+        namedParameters: ['apiKey', 'apiUrl'],
+        namedOptionalParameters: [],
+      );
+      expect(Signature.parseMethodSignature(signature), expected);
+    });
+
+    test('handles signatures with no parameters', () {
+      final signature = 'void doSomething()';
+      final expected = const Signature(
+        positionalParameters: [],
+        positionalOptionalParameters: [],
+        namedParameters: [],
+        namedOptionalParameters: [],
+      );
+      expect(Signature.parseMethodSignature(signature), expected);
+    });
+
+    test('handles signatures with complex type annotations', () {
+      final signature = '''
+List<Map<String, int>> processData(Map<String, List<int>> input, [Set<String>? filter])''';
+      final expected = const Signature(
+        positionalParameters: ['input'],
+        positionalOptionalParameters: ['filter'],
+        namedParameters: [],
+        namedOptionalParameters: [],
+      );
+      expect(Signature.parseMethodSignature(signature), expected);
+    });
+
+    test('handles signatures with complex type annotations', () {
+      final signature = '''
+void test(Object? description, dynamic Function() body,
+    {String? testOn,
+    Timeout? timeout,
+    Object? skip,
+    Object? tags,
+    Map<String, Object?>? onPlatform,
+    int? retry,
+    // TODO(https://github.com/dart-lang/test/issues/2205): Remove deprecated.
+    // Map<String, Object?>? error,
+    @Deprecated('Debug only') @doNotSubmit bool solo = false})''';
+      final expected = const Signature(
+        positionalParameters: ['description', 'body'],
+        positionalOptionalParameters: [],
+        namedParameters: [],
+        namedOptionalParameters: [
+          'testOn',
+          'timeout',
+          'skip',
+          'tags',
+          'onPlatform',
+          'retry',
+          'solo',
+        ],
+      );
+      expect(Signature.parseMethodSignature(signature), expected);
+    });
+  });
+}
diff --git a/pkg/record_use/test/storage_test.dart b/pkg/record_use/test/storage_test.dart
index 7a8da25..d62610d 100644
--- a/pkg/record_use/test/storage_test.dart
+++ b/pkg/record_use/test/storage_test.dart
@@ -10,22 +10,33 @@
 import 'test_data.dart';
 
 void main() {
-  final json = jsonDecode(recordedUsesJson) as Map<String, dynamic>;
-  test(
-    'JSON',
-    () => expect(recordedUses.toJson(), json),
-  );
+  group('object 1', () {
+    final json = jsonDecode(recordedUsesJson) as Map<String, Object?>;
+    test('JSON', () => expect(recordedUses.toJson(), json));
 
-  test(
-    'Object',
-    () => expect(UsageRecord.fromJson(json), recordedUses),
-  );
+    test('Object', () => expect(Recordings.fromJson(json), recordedUses));
 
-  test('Json->Object->Json', () {
-    expect(UsageRecord.fromJson(json).toJson(), json);
+    test('Json->Object->Json', () {
+      expect(Recordings.fromJson(json).toJson(), json);
+    });
+
+    test('Object->Json->Object', () {
+      expect(Recordings.fromJson(recordedUses.toJson()), recordedUses);
+    });
   });
 
-  test('Object->Json->Object', () {
-    expect(UsageRecord.fromJson(recordedUses.toJson()), recordedUses);
+  group('object 2', () {
+    final json2 = jsonDecode(recordedUsesJson2) as Map<String, Object?>;
+    test('JSON', () => expect(recordedUses2.toJson(), json2));
+
+    test('Object', () => expect(Recordings.fromJson(json2), recordedUses2));
+
+    test('Json->Object->Json', () {
+      expect(Recordings.fromJson(json2).toJson(), json2);
+    });
+
+    test('Object->Json->Object', () {
+      expect(Recordings.fromJson(recordedUses2.toJson()), recordedUses2);
+    });
   });
 }
diff --git a/pkg/record_use/test/test_data.dart b/pkg/record_use/test/test_data.dart
index d758481..c1aae17 100644
--- a/pkg/record_use/test/test_data.dart
+++ b/pkg/record_use/test/test_data.dart
@@ -6,218 +6,243 @@
 import 'package:record_use/record_use_internal.dart';
 
 final callId = Identifier(
-  importUri: Uri.parse('file://lib/_internal/js_runtime/lib/js_helper.dart')
-      .toString(),
-  parent: 'MyClass',
+  importUri:
+      Uri.parse(
+        'file://lib/_internal/js_runtime/lib/js_helper.dart',
+      ).toString(),
+  scope: 'MyClass',
   name: 'get:loadDeferredLibrary',
 );
 final instanceId = Identifier(
-  importUri: Uri.parse('file://lib/_internal/js_runtime/lib/js_helper.dart')
-      .toString(),
+  importUri:
+      Uri.parse(
+        'file://lib/_internal/js_runtime/lib/js_helper.dart',
+      ).toString(),
   name: 'MyAnnotation',
 );
 
-final recordedUses = UsageRecord(
-  metadata: Metadata(
-    version: Version(1, 6, 2, pre: 'wip', build: '5.-.2.z'),
-    comment:
-        'Recorded references at compile time and their argument values, as far'
-        ' as known, to definitions annotated with @RecordUse',
-  ),
-  instances: [
-    Usage(
-      definition: Definition(
-        identifier: instanceId,
-        location: Location(
-          uri: Uri.parse('file://lib/_internal/js_runtime/lib/js_helper.dart')
-              .toString(),
-          line: 15,
-          column: 30,
-        ),
+final recordedUses = Recordings(
+  metadata: Metadata.fromJson({
+    'version': Version(1, 6, 2, pre: 'wip', build: '5.-.2.z').toString(),
+    'comment':
+        'Recorded references at compile time and their argument values, as'
+        ' far as known, to definitions annotated with @RecordUse',
+  }),
+  callsForDefinition: {
+    Definition(identifier: callId, loadingUnit: 'part_15.js'): [
+      const CallWithArguments(
+        positionalArguments: [
+          BoolConstant(false),
+          StringConstant('mercury'),
+          IntConstant(1),
+          StringConstant('jenkins'),
+          StringConstant('lib_SHA1'),
+        ],
+        namedArguments: {},
+        loadingUnit: 'o.js',
+        location: Location(uri: 'lib/test.dart'),
       ),
-      references: [
-        InstanceReference(
-          instanceConstant: const InstanceConstant(
-            fields: {
-              'a': IntConstant(42),
-              'b': NullConstant(),
-            },
-          ),
-          location: Location(
-            uri: Uri.parse('file://lib/_internal/js_runtime/lib/js_helper.dart')
-                .toString(),
-            line: 40,
-            column: 30,
-          ),
-          loadingUnit: '3',
-        ),
-      ],
-    ),
-  ],
-  calls: [
-    Usage(
-      definition: Definition(
-        identifier: callId,
-        location: Location(
-          uri: Uri.parse('file://lib/_internal/js_runtime/lib/js_helper.dart')
-              .toString(),
-          line: 12,
-          column: 67,
-        ),
-        loadingUnit: 'part_15.js',
+      const CallWithArguments(
+        positionalArguments: [
+          StringConstant('lib_SHA1'),
+          IntConstant(0),
+          MapConstant<IntConstant>({'key': IntConstant(99)}),
+          StringConstant('jenkins'),
+          ListConstant([
+            StringConstant('camus'),
+            ListConstant([
+              StringConstant('einstein'),
+              StringConstant('insert'),
+              BoolConstant(false),
+            ]),
+            StringConstant('einstein'),
+          ]),
+        ],
+        namedArguments: {},
+        loadingUnit: 'o.js',
+        location: Location(uri: 'lib/test2.dart'),
       ),
-      references: [
-        CallReference(
-          arguments: const Arguments(
-            constArguments: ConstArguments(
-              positional: {
-                0: StringConstant('lib_SHA1'),
-                1: BoolConstant(false),
-                2: IntConstant(1)
-              },
-              named: {
-                'leroy': StringConstant('jenkins'),
-                'freddy': StringConstant('mercury')
-              },
-            ),
-          ),
-          location: Location(
-            uri: Uri.parse(
-                    'file://benchmarks/OmnibusDeferred/dart/OmnibusDeferred.dart')
-                .toString(),
-            line: 14,
-            column: 49,
-          ),
-          loadingUnit: 'o.js',
+    ],
+  },
+  instancesForDefinition: {
+    Definition(identifier: instanceId): [
+      const InstanceReference(
+        instanceConstant: InstanceConstant(
+          fields: {'a': IntConstant(42), 'b': NullConstant()},
         ),
-        CallReference(
-          arguments: const Arguments(
-            constArguments: ConstArguments(
-              positional: {
-                0: StringConstant('lib_SHA1'),
-                2: IntConstant(0),
-                4: MapConstant<IntConstant>({'key': IntConstant(99)}),
-              },
-              named: {
-                'leroy': StringConstant('jenkins'),
-                'albert': ListConstant([
-                  StringConstant('camus'),
-                  ListConstant([
-                    StringConstant('einstein'),
-                    StringConstant('insert'),
-                    BoolConstant(false),
-                  ]),
-                  StringConstant('einstein'),
-                ]),
-              },
-            ),
-            nonConstArguments: NonConstArguments(
-              positional: [1],
-              named: ['freddy'],
-            ),
-          ),
-          location: Location(
-            uri: Uri.parse(
-                    'file://benchmarks/OmnibusDeferred/dart/OmnibusDeferred.dart')
-                .toString(),
-            line: 14,
-            column: 48,
-          ),
-          loadingUnit: 'o.js',
-        ),
-      ],
-    ),
-  ],
+        loadingUnit: '3',
+        location: Location(uri: 'lib/test3.dart'),
+      ),
+    ],
+  },
+);
+
+final recordedUses2 = Recordings(
+  metadata: Metadata.fromJson({
+    'version': Version(1, 6, 2, pre: 'wip', build: '5.-.2.z').toString(),
+    'comment':
+        'Recorded references at compile time and their argument values, as'
+        ' far as known, to definitions annotated with @RecordUse',
+  }),
+  callsForDefinition: {
+    Definition(identifier: callId, loadingUnit: 'part_15.js'): [
+      const CallWithArguments(
+        positionalArguments: [BoolConstant(false), IntConstant(1)],
+        namedArguments: {
+          'freddy': StringConstant('mercury'),
+          'answer': IntConstant(42),
+        },
+        loadingUnit: 'o.js',
+        location: Location(uri: 'lib/test3.dart'),
+      ),
+    ],
+  },
+  instancesForDefinition: {},
 );
 
 final recordedUsesJson = '''{
   "metadata": {
-    "comment":
-        "Recorded references at compile time and their argument values, as far as known, to definitions annotated with @RecordUse",
-    "version": "1.6.2-wip+5.-.2.z"
+    "version": "1.6.2-wip+5.-.2.z",
+    "comment": "Recorded references at compile time and their argument values, as far as known, to definitions annotated with @RecordUse"
   },
-  "uris": [
-    "file://lib/_internal/js_runtime/lib/js_helper.dart",
-    "file://benchmarks/OmnibusDeferred/dart/OmnibusDeferred.dart"
-  ],
-  "ids": [
-    {"uri": 0, "parent": "MyClass", "name": "get:loadDeferredLibrary"},
-    {"uri": 0, "name": "MyAnnotation"}
-  ],
   "constants": [
-    {"type": "String", "value": "jenkins"},
-    {"type": "String", "value": "mercury"},
-    {"type": "String", "value": "lib_SHA1"},
-    {"type": "bool", "value": false},
-    {"type": "int", "value": 1},
-    {"type": "String", "value": "camus"},
-    {"type": "String", "value": "einstein"},
-    {"type": "String", "value": "insert"},
     {
-      "type": "list",
-      "value": [6, 7, 3]
+      "type": "bool",
+      "value": false
     },
     {
-      "type": "list",
-      "value": [5, 8, 6]
+      "type": "String",
+      "value": "mercury"
     },
-    {"type": "int", "value": 0},
-    {"type": "int", "value": 99},
+    {
+      "type": "int",
+      "value": 1
+    },
+    {
+      "type": "String",
+      "value": "jenkins"
+    },
+    {
+      "type": "String",
+      "value": "lib_SHA1"
+    },
+    {
+      "type": "int",
+      "value": 0
+    },
+    {
+      "type": "int",
+      "value": 99
+    },
     {
       "type": "map",
-      "value": {"key": 11}
+      "value": {
+        "key": 6
+      }
     },
-    {"type": "int", "value": 42},
-    {"type": "Null"},
-    {"type": "Instance", "value": {"a": 13, "b": 14}}
-  ],
-  "calls": [
     {
-      "definition": {
-        "id": 0,
-        "@": {"uri": 0, "line": 12, "column": 67},
-        "loadingUnit": "part_15.js"
-      },
-      "references": [
-        {
-          "arguments": {
-            "const": {
-              "positional": {"0": 2, "1": 3, "2": 4},
-              "named": {"leroy": 0, "freddy": 1}
-            }
-          },
-          "loadingUnit": "o.js",
-          "@": {"uri": 1, "line": 14, "column": 49}
-        },
-        {
-          "arguments": {
-            "const": {
-              "positional": {"0": 2, "2": 10, "4": 12},
-              "named": {"leroy": 0, "albert": 9}
-            },
-            "nonConst": {
-              "positional": [1],
-              "named": ["freddy"]
-            }
-          },
-          "loadingUnit": "o.js",
-          "@": {"uri": 1, "line": 14, "column": 48}
-        }
+      "type": "String",
+      "value": "camus"
+    },
+    {
+      "type": "String",
+      "value": "einstein"
+    },
+    {
+      "type": "String",
+      "value": "insert"
+    },
+    {
+      "type": "list",
+      "value": [
+        9,
+        10,
+        0
       ]
+    },
+    {
+      "type": "list",
+      "value": [
+        8,
+        11,
+        9
+      ]
+    },
+    {
+      "type": "int",
+      "value": 42
+    },
+    {
+      "type": "Null"
+    },
+    {
+      "type": "Instance",
+      "value": {
+        "a": 13,
+        "b": 14
+      }
     }
   ],
-  "instances": [
+  "locations": [
+    {
+      "uri": "lib/test.dart"
+    },
+    {
+      "uri": "lib/test2.dart"
+    },
+    {
+      "uri": "lib/test3.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 1,
-        "@": {"uri": 0, "line": 15, "column": 30},
-        "loadingUnit": null
+        "identifier": {
+          "uri": "file://lib/_internal/js_runtime/lib/js_helper.dart",
+          "scope": "MyClass",
+          "name": "get:loadDeferredLibrary"
+        },
+        "loading_unit": "part_15.js"
       },
-      "references": [
+      "calls": [
         {
-          "instanceConstant": 15,
-          "loadingUnit": "3",
-          "@": {"uri": 0, "line": 40, "column": 30}
+          "type": "with_arguments",
+          "positional": [
+            0,
+            1,
+            2,
+            3,
+            4
+          ],
+          "loading_unit": "o.js",
+          "@": 0
+        },
+        {
+          "type": "with_arguments",
+          "positional": [
+            4,
+            5,
+            7,
+            3,
+            12
+          ],
+          "loading_unit": "o.js",
+          "@": 1
+        }
+      ]
+    },
+    {
+      "definition": {
+        "identifier": {
+          "uri": "file://lib/_internal/js_runtime/lib/js_helper.dart",
+          "name": "MyAnnotation"
+        }
+      },
+      "instances": [
+        {
+          "constant_index": 15,
+          "loading_unit": "3",
+          "@": 2
         }
       ]
     }
@@ -226,51 +251,55 @@
 
 final recordedUsesJson2 = '''{
   "metadata": {
-    "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "1.6.2-wip+5.-.2.z",
+    "comment": "Recorded references at compile time and their argument values, as far as known, to definitions annotated with @RecordUse"
   },
-  "uris": [
-    "package:drop_dylib_recording/src/drop_dylib_recording.dart",
-    "drop_dylib_recording_calls.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "name": "getMathMethod"
-    }
-  ],
   "constants": [
     {
+      "type": "bool",
+      "value": false
+    },
+    {
+      "type": "int",
+      "value": 1
+    },
+    {
       "type": "String",
-      "value": "add"
+      "value": "mercury"
+    },
+    {
+      "type": "int",
+      "value": 42
     }
   ],
-  "calls": [
+  "locations": [
+    {
+      "uri": "lib/test3.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0, 
-          "line": 10,
-          "column": 6
+        "identifier": {
+          "uri": "file://lib/_internal/js_runtime/lib/js_helper.dart",
+          "scope": "MyClass",
+          "name": "get:loadDeferredLibrary"
         },
-        "loadingUnit": "1"
+        "loading_unit": "part_15.js"
       },
-      "references": [
+      "calls": [
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "0": 0
-              }
-            }
+          "type": "with_arguments",
+          "positional": [
+            0,
+            1
+          ],
+          "named": {
+            "freddy": 2,
+            "answer": 3
           },
-          "loadingUnit": "1",
-          "@": {
-            "uri": 1,
-            "line": 8,
-            "column": 3
-          }
+          "loading_unit": "o.js",
+          "@": 0
         }
       ]
     }
diff --git a/pkg/record_use/test/usage_test.dart b/pkg/record_use/test/usage_test.dart
index bd2e066..f749932 100644
--- a/pkg/record_use/test/usage_test.dart
+++ b/pkg/record_use/test/usage_test.dart
@@ -13,97 +13,115 @@
   test('All API calls', () {
     expect(
       RecordedUsages.fromJson(
-              jsonDecode(recordedUsesJson) as Map<String, dynamic>)
-          .argumentsTo(callId),
-      recordedUses.calls.expand((e) => e.references).map((e) => e.arguments),
+        jsonDecode(recordedUsesJson) as Map<String, Object?>,
+      ).constArgumentsFor(
+        Identifier(
+          importUri:
+              Uri.parse(
+                'file://lib/_internal/js_runtime/lib/js_helper.dart',
+              ).toString(),
+          scope: 'MyClass',
+          name: 'get:loadDeferredLibrary',
+        ),
+        '''
+void loadDeferredLibrary(String s, bool b, int i, {required String singer, String? character})''',
+      ).length,
+      2,
     );
   });
 
   test('All API instances', () {
-    final references =
-        recordedUses.instances.expand((instance) => instance.references);
-    final instances = RecordedUsages.fromJson(
-            jsonDecode(recordedUsesJson) as Map<String, dynamic>)
-        .instancesOf(instanceId);
-    expect(instances, references);
+    final instance =
+        RecordedUsages.fromJson(
+              jsonDecode(recordedUsesJson) as Map<String, Object?>,
+            )
+            .constantsOf(
+              Identifier(
+                importUri:
+                    Uri.parse(
+                      'file://lib/_internal/js_runtime/lib/js_helper.dart',
+                    ).toString(),
+                name: 'MyAnnotation',
+              ),
+            )
+            .first;
+    final instanceMap =
+        recordedUses.instancesForDefinition.values
+            .expand((usage) => usage)
+            .map(
+              (instance) => instance.instanceConstant.fields.map(
+                (key, constant) => MapEntry(key, constant.toValue()),
+              ),
+            )
+            .first;
+    for (final entry in instanceMap.entries) {
+      expect(instance[entry.key], entry.value);
+    }
   });
 
   test('Specific API calls', () {
-    final callId = Identifier(
-      importUri: Uri.parse('file://lib/_internal/js_runtime/lib/js_helper.dart')
-          .toString(),
-      parent: 'MyClass',
-      name: 'get:loadDeferredLibrary',
-    );
-    final arguments = RecordedUsages.fromJson(
-            jsonDecode(recordedUsesJson) as Map<String, dynamic>)
-        .argumentsTo(callId)!
-        .toList();
-    expect(
-      arguments[0].constArguments.named,
-      const {
-        'leroy': StringConstant('jenkins'),
-        'freddy': StringConstant('mercury'),
-      },
-    );
-    expect(
-      arguments[0].constArguments.positional,
-      const {
-        0: StringConstant('lib_SHA1'),
-        1: BoolConstant(false),
-        2: IntConstant(1)
-      },
-    );
-    expect(arguments[1].constArguments.named, const {
-      'leroy': StringConstant('jenkins'),
-      'albert': ListConstant([
-        StringConstant('camus'),
-        ListConstant([
-          StringConstant('einstein'),
-          StringConstant('insert'),
-          BoolConstant(false),
-        ]),
-        StringConstant('einstein'),
-      ]),
-    });
-    expect(arguments[1].constArguments.positional, const {
-      0: StringConstant('lib_SHA1'),
-      2: IntConstant(0),
-      4: MapConstant({'key': IntConstant(99)})
-    });
+    var arguments =
+        RecordedUsages.fromJson(
+          jsonDecode(recordedUsesJson) as Map<String, Object?>,
+        ).constArgumentsFor(
+          Identifier(
+            importUri:
+                Uri.parse(
+                  'file://lib/_internal/js_runtime/lib/js_helper.dart',
+                ).toString(),
+            scope: 'MyClass',
+            name: 'get:loadDeferredLibrary',
+          ),
+          '''
+void loadDeferredLibrary(String s, bool b, int i, {required String freddy, String? leroy})''',
+        ).toList();
+    var (named: named0, positional: positional0) = arguments[0];
+    expect(named0, const {'freddy': 'mercury', 'leroy': 'jenkins'});
+    expect(positional0, const ['lib_SHA1', false, 1]);
+    var (named: named1, positional: positional1) = arguments[1];
+    expect(named1, const {'freddy': 0, 'leroy': 'jenkins'});
+    expect(positional1, const [
+      [
+        'camus',
+        ['einstein', 'insert', false],
+        'einstein',
+      ],
+      'lib_SHA1',
+      {'key': 99},
+    ]);
   });
 
   test('Specific API instances', () {
-    final instanceId = Identifier(
-      importUri: Uri.parse('file://lib/_internal/js_runtime/lib/js_helper.dart')
-          .toString(),
-      name: 'MyAnnotation',
-    );
-    expect(
-      RecordedUsages.fromJson(
-              jsonDecode(recordedUsesJson) as Map<String, dynamic>)
-          .instancesOf(instanceId)
-          ?.first,
-      InstanceReference(
-        instanceConstant: const InstanceConstant(
-          fields: {'a': IntConstant(42), 'b': NullConstant()},
-        ),
-        location: Location(uri: instanceId.importUri, line: 40, column: 30),
-        loadingUnit: 3.toString(),
-      ),
-    );
+    final instance =
+        RecordedUsages.fromJson(
+              jsonDecode(recordedUsesJson) as Map<String, Object?>,
+            )
+            .constantsOf(
+              Identifier(
+                importUri:
+                    Uri.parse(
+                      'file://lib/_internal/js_runtime/lib/js_helper.dart',
+                    ).toString(),
+                name: 'MyAnnotation',
+              ),
+            )
+            .first;
+    expect(instance['a'], 42);
+    expect(instance['b'], null);
   });
 
   test('HasNonConstInstance', () {
-    final id = const Identifier(
-      importUri: 'package:drop_dylib_recording/src/drop_dylib_recording.dart',
-      name: 'getMathMethod',
-    );
-
     expect(
-        RecordedUsages.fromJson(
-                jsonDecode(recordedUsesJson2) as Map<String, dynamic>)
-            .hasNonConstArguments(id),
-        false);
+      RecordedUsages.fromJson(
+        jsonDecode(recordedUsesJson2) as Map<String, Object?>,
+      ).hasNonConstArguments(
+        const Identifier(
+          importUri:
+              'package:drop_dylib_recording/src/drop_dylib_recording.dart',
+          name: 'getMathMethod',
+        ),
+      ),
+      false,
+    );
   });
 }
diff --git a/pkg/record_use/test_data/drop_dylib_recording/hook/build.dart b/pkg/record_use/test_data/drop_dylib_recording/hook/build.dart
index cfbc206..20c3924 100644
--- a/pkg/record_use/test_data/drop_dylib_recording/hook/build.dart
+++ b/pkg/record_use/test_data/drop_dylib_recording/hook/build.dart
@@ -13,8 +13,7 @@
       ..onRecord.listen((record) {
         print('${record.level.name}: ${record.time}: ${record.message}');
       });
-    final routing =
-        input.config.linkingEnabled
+    final routing = input.config.linkingEnabled
         ? [ToLinkHook(input.packageName)]
         : const [ToAppBundle()];
     await CBuilder.library(
diff --git a/pkg/record_use/test_data/drop_dylib_recording/hook/link.dart b/pkg/record_use/test_data/drop_dylib_recording/hook/link.dart
index 8f3dbc2..7336470 100644
--- a/pkg/record_use/test_data/drop_dylib_recording/hook/link.dart
+++ b/pkg/record_use/test_data/drop_dylib_recording/hook/link.dart
@@ -8,30 +8,14 @@
 import 'package:native_assets_cli/code_assets.dart';
 import 'package:record_use/record_use.dart';
 
-final callIdAdd = const Identifier(
-  importUri: 'package:drop_dylib_recording/src/drop_dylib_recording.dart',
-  parent: 'MyMath',
-  name: 'add',
-);
-
-final callIdMultiply = const Identifier(
-  importUri: 'package:drop_dylib_recording/src/drop_dylib_recording.dart',
-  parent: 'MyMath',
-  name: 'multiply',
-);
-
-final instanceId = const Identifier(
-  importUri: 'package:drop_dylib_recording/src/drop_dylib_recording.dart',
-  name: 'RecordCallToC',
-);
-
 void main(List<String> arguments) async {
   await link(arguments, (input, output) async {
-    final file = File.fromUri(input.recordedUsagesFile!);
-    final string = await file.readAsString();
-    final usages =
-        RecordedUsages.fromJson(jsonDecode(string) as Map<String, dynamic>);
-
+    final recordedUsagesFile = input.recordedUsagesFile;
+    if (recordedUsagesFile == null) {
+      throw ArgumentError(
+          'Enable the --enable-experiments=record-use experiment to use this app.');
+    }
+    final usages = await recordedUsages(recordedUsagesFile);
     final codeAssets = input.assets.code;
     print('Received assets: ${codeAssets.map((a) => a.id).join(', ')}.');
 
@@ -42,26 +26,31 @@
 
     final dataLines = <String>[];
     // Tree-shake unused assets using calls
-    for (var callId in [callIdAdd, callIdMultiply]) {
-      var arguments = usages.argumentsTo(callId);
-      if (arguments?.isNotEmpty ?? false) {
-        final argument =
-            (arguments!.first.constArguments.positional[0] as IntConstant)
-                .value;
-        dataLines.add('Argument to "${callId.name}": $argument');
-        symbols.add(callId.name);
+    for (final methodName in ['add', 'multiply']) {
+      final calls = usages.constArgumentsFor(
+          Identifier(
+            importUri:
+                'package:drop_dylib_recording/src/drop_dylib_recording.dart',
+            scope: 'MyMath',
+            name: methodName,
+          ),
+          'int add(int a, int b)');
+      for (var call in calls) {
+        dataLines.add(
+            'A call was made to "$methodName" with the arguments (${call.positional[0] as int},${call.positional[1] as int})');
+        symbols.add(methodName);
       }
     }
 
     argumentsFile.writeAsStringSync(dataLines.join('\n'));
 
     // Tree-shake unused assets
-    final instances = usages.instancesOf(instanceId) ?? [];
+    final instances = usages.constantsOf(Identifier(
+      importUri: 'package:drop_dylib_recording/src/drop_dylib_recording.dart',
+      name: 'RecordCallToC',
+    ));
     for (final instance in instances) {
-      final symbol =
-          (instance.instanceConstant.fields.values.first as StringConstant)
-              .value;
-
+      final symbol = instance['symbol'] as String;
       symbols.add(symbol);
     }
 
@@ -73,6 +62,14 @@
     print('Keeping only ${neededCodeAssets.map((e) => e.id).join(', ')}.');
     output.assets.code.addAll(neededCodeAssets);
 
-    output.addDependency(input.packageRoot.resolve('hook/link.dart'));
+    output.addDependency(recordedUsagesFile);
   });
 }
+
+Future<RecordedUsages> recordedUsages(Uri recordedUsagesFile) async {
+  final file = File.fromUri(recordedUsagesFile);
+  final string = await file.readAsString();
+  final usages =
+      RecordedUsages.fromJson(jsonDecode(string) as Map<String, Object?>);
+  return usages;
+}
diff --git a/pkg/vm/lib/transformations/record_use/constant_collector.dart b/pkg/vm/lib/transformations/record_use/constant_collector.dart
index e204ed1..a1d77fab 100644
--- a/pkg/vm/lib/transformations/record_use/constant_collector.dart
+++ b/pkg/vm/lib/transformations/record_use/constant_collector.dart
@@ -79,8 +79,9 @@
   void visitInstanceConstant(InstanceConstant constant) {
     assert(_expression != null);
     final classNode = constant.classNode;
-    if (_hasRecordUseAnnotation[classNode] ??=
-        recordUse.findRecordUseAnnotation(classNode).isNotEmpty) {
+    if (_hasRecordUseAnnotation[classNode] ??= recordUse.hasRecordUseAnnotation(
+      classNode,
+    )) {
       collector(_expression!, constant);
     }
     for (final value in constant.fieldValues.values) {
diff --git a/pkg/vm/lib/transformations/record_use/record_call.dart b/pkg/vm/lib/transformations/record_use/record_call.dart
index d2e8959..8452252 100644
--- a/pkg/vm/lib/transformations/record_use/record_call.dart
+++ b/pkg/vm/lib/transformations/record_use/record_call.dart
@@ -2,7 +2,6 @@
 // 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:collection/collection.dart';
 import 'package:front_end/src/kernel/record_use.dart' as recordUse;
 import 'package:kernel/ast.dart' as ast;
 import 'package:record_use/record_use_internal.dart';
@@ -13,14 +12,15 @@
 /// * static or top-level method calls through [recordStaticInvocation]
 /// * tear-offs through [recordConstantExpression]
 ///
-/// The result of adding calls can be fetched from [foundCalls].
+/// The result of adding calls can be fetched from [callsForMethod].
 class CallRecorder {
-  /// The collection of recorded calls found so far.
-  Iterable<Usage<CallReference>> get foundCalls => _callsForMethod.values;
+  /// Keep track of the calls which are recorded, to easily add newly found
+  /// ones.
+  final Map<Identifier, List<CallReference>> callsForMethod = {};
 
   /// Keep track of the calls which are recorded, to easily add newly found
   /// ones.
-  final Map<ast.Procedure, Usage<CallReference>> _callsForMethod = {};
+  final Map<Identifier, String> loadingUnitForDefinition = {};
 
   /// The ordered list of loading units to retrieve the loading unit index from.
   final List<LoadingUnit> _loadingUnits;
@@ -28,16 +28,18 @@
   /// The source uri to base relative URIs off of.
   final Uri _source;
 
+  /// Whether to save line and column info as well as the URI.
+  //TODO(mosum): add verbose mode to enable this
+  bool exactLocation = false;
+
   CallRecorder(this._source, this._loadingUnits);
 
   /// Will record a static invocation if it is annotated with `@RecordUse`.
   void recordStaticInvocation(ast.StaticInvocation node) {
-    final annotations = recordUse.findRecordUseAnnotation(node.target);
-    if (annotations.isNotEmpty) {
-      final call = _getCall(node.target);
-
+    if (recordUse.hasRecordUseAnnotation(node.target)) {
       // Collect the (int, bool, double, or String) arguments passed in the call.
-      call.references.add(_createCallReference(node));
+      final createCallReference = _createCallReference(node);
+      _addToUsage(node.target, createCallReference);
     }
   }
 
@@ -45,51 +47,34 @@
   void recordConstantExpression(ast.ConstantExpression node) {
     final constant = node.constant;
     if (constant is ast.StaticTearOffConstant) {
-      final hasRecordUseAnnotation =
-          recordUse.findRecordUseAnnotation(constant.target).isNotEmpty;
+      final hasRecordUseAnnotation = recordUse.hasRecordUseAnnotation(
+        constant.target,
+      );
       if (hasRecordUseAnnotation) {
-        _recordTearOff(constant, node);
+        _addToUsage(
+          constant.target,
+          CallTearOff(
+            loadingUnit: loadingUnitForNode(node, _loadingUnits).toString(),
+            location: node.location!.recordLocation(_source, exactLocation),
+          ),
+        );
       }
     }
   }
 
-  void _recordTearOff(
-    ast.StaticTearOffConstant constant,
-    ast.ConstantExpression node,
-  ) {
-    final call = _getCall(constant.target);
-    final reference = _collectTearOff(constant, node);
-    call.references.add(reference);
-  }
-
-  /// Record a tear off as a call with all non-const arguments.
-  CallReference _collectTearOff(
-    ast.StaticTearOffConstant constant,
-    ast.TreeNode node,
-  ) {
-    final function = constant.target.function;
-    final nonConstArguments = NonConstArguments(
-      named:
-          function.namedParameters.map((parameter) => parameter.name!).toList(),
-      positional: List.generate(
-        function.positionalParameters.length,
-        (index) => index,
-      ),
-    );
-    return CallReference(
-      location: node.location!.recordLocation(_source),
-      arguments: Arguments(nonConstArguments: nonConstArguments),
-    );
-  }
-
   /// Collect the name and definition location of the invocation. This is
   /// shared across multiple calls to the same method.
-  Usage _getCall(ast.Procedure target) {
-    final definition = _definitionFromMember(target);
-    return _callsForMethod[target] ??= Usage(
-      definition: definition,
-      references: [],
+  void _addToUsage(ast.Procedure target, CallReference call) {
+    var (:identifier, :loadingUnit) = _definitionFromMember(target);
+    callsForMethod.update(
+      identifier,
+      (usage) => usage..add(call),
+      ifAbsent: () => [call],
     );
+    loadingUnitForDefinition.update(identifier, (value) {
+      assert(value == loadingUnit);
+      return value;
+    }, ifAbsent: () => loadingUnit);
   }
 
   CallReference _createCallReference(ast.StaticInvocation node) {
@@ -101,49 +86,47 @@
       argumentStart = 0;
     }
 
-    final positionalArguments = node.arguments.positional
-        .skip(argumentStart)
-        .mapIndexed((i, argument) => MapEntry(i, _evaluateLiteral(argument)));
-    final namedArguments = node.arguments.named.map(
-      (argument) => MapEntry(argument.name, _evaluateLiteral(argument.value)),
-    );
+    final positionalArguments =
+        node.arguments.positional
+            .skip(argumentStart)
+            .map((argument) => _evaluateLiteral(argument))
+            .toList();
 
-    // Group by the evaluated literal - if it exists, the argument was const.
-    final positionalGrouped = _groupByNull(positionalArguments);
-    final namedGrouped = _groupByNull(namedArguments);
+    final namedArguments = {
+      for (final argument in node.arguments.named)
+        argument.name: _evaluateLiteral(argument.value),
+    };
 
-    return CallReference(
-      location: node.location!.recordLocation(_source),
+    // Fill up with the default values
+    for (final parameter in node.target.function.namedParameters) {
+      final initializer = parameter.initializer;
+      final name = parameter.name;
+      if (initializer != null &&
+          name != null &&
+          !namedArguments.containsKey(name)) {
+        namedArguments[name] = _evaluateLiteral(initializer);
+      }
+    }
+    for (
+      var i = positionalArguments.length;
+      i < node.target.function.positionalParameters.length;
+      i++
+    ) {
+      final parameter = node.target.function.positionalParameters[i];
+      final initializer = parameter.initializer;
+      if (initializer != null) {
+        positionalArguments.add(_evaluateLiteral(initializer));
+      }
+    }
+
+    return CallWithArguments(
+      positionalArguments: positionalArguments,
+      namedArguments: namedArguments,
       loadingUnit: loadingUnitForNode(node, _loadingUnits).toString(),
-      arguments: Arguments(
-        constArguments: ConstArguments(
-          positional:
-              positionalGrouped[false] != null
-                  ? Map.fromEntries(
-                    positionalGrouped[false]!.map(
-                      (e) => MapEntry(e.key, e.value!),
-                    ),
-                  )
-                  : null,
-          named:
-              namedGrouped[false] != null
-                  ? Map.fromEntries(
-                    namedGrouped[false]!.map((e) => MapEntry(e.key, e.value!)),
-                  )
-                  : null,
-        ),
-        nonConstArguments: NonConstArguments(
-          positional: positionalGrouped[true]?.map((e) => e.key).toList(),
-          named: namedGrouped[true]?.map((e) => e.key).toList(),
-        ),
-      ),
+      location: node.location!.recordLocation(_source, exactLocation),
     );
   }
 
-  Map<bool, List<MapEntry<T, Constant?>>> _groupByNull<T>(
-    Iterable<MapEntry<T, Constant?>> arguments,
-  ) => groupBy(arguments, (entry) => entry.value == null);
-
   Constant? _evaluateLiteral(ast.Expression expression) {
     if (expression is ast.BasicLiteral) {
       return evaluateLiteral(expression);
@@ -154,17 +137,18 @@
     }
   }
 
-  Definition _definitionFromMember(ast.Member target) {
+  ({Identifier identifier, String loadingUnit}) _definitionFromMember(
+    ast.Member target,
+  ) {
     final enclosingLibrary = target.enclosingLibrary;
     String file = getImportUri(enclosingLibrary, _source);
 
-    return Definition(
+    return (
       identifier: Identifier(
         importUri: file,
-        parent: target.enclosingClass?.name,
+        scope: target.enclosingClass?.name,
         name: target.name.text,
       ),
-      location: target.location!.recordLocation(_source),
       loadingUnit:
           loadingUnitForNode(enclosingLibrary, _loadingUnits).toString(),
     );
diff --git a/pkg/vm/lib/transformations/record_use/record_instance.dart b/pkg/vm/lib/transformations/record_use/record_instance.dart
index 0ae0926..35c0229 100644
--- a/pkg/vm/lib/transformations/record_use/record_instance.dart
+++ b/pkg/vm/lib/transformations/record_use/record_instance.dart
@@ -10,15 +10,15 @@
 import 'constant_collector.dart';
 
 /// Record a const instance by calling [recordConstantExpression]. After all the
-/// const instances have been recorded, retrieve them using [foundInstances].
+/// const instances have been recorded, retrieve them using [instancesForClass].
 class InstanceRecorder {
-  /// The collection of recorded instances found so far.
-  Iterable<Usage<InstanceReference>> get foundInstances =>
-      _instancesForClass.values;
-
   /// Keep track of the classes which are recorded, to easily add found
   /// instances.
-  final Map<ast.Class, Usage<InstanceReference>> _instancesForClass = {};
+  final Map<Identifier, List<InstanceReference>> instancesForClass = {};
+
+  /// Keep track of the calls which are recorded, to easily add newly found
+  /// ones.
+  final Map<Identifier, String> loadingUnitForDefinition = {};
 
   /// The ordered list of loading units to retrieve the loading unit index from.
   final List<LoadingUnit> _loadingUnits;
@@ -29,6 +29,10 @@
   /// A visitor traversing and collecting constants.
   late final ConstantCollector collector;
 
+  /// Whether to save line and column info as well as the URI.
+  //TODO(mosum): add verbose mode to enable this
+  bool exactLocation = false;
+
   InstanceRecorder(this._source, this._loadingUnits) {
     collector = ConstantCollector.collectWith(_collectInstance);
   }
@@ -40,33 +44,33 @@
     ast.ConstantExpression expression,
     ast.InstanceConstant constant,
   ) {
-    // Collect the name and definition location of the invocation. This is
-    // shared across multiple calls to the same method.
-    final existingInstance = _getCall(constant.classNode);
-
-    // Collect the (int, bool, double, or String) arguments passed in the call.
-    existingInstance.references.add(
-      _createInstanceReference(expression, constant),
-    );
+    final instance = _createInstanceReference(expression, constant);
+    _addToUsage(constant.classNode, instance);
   }
 
   /// Collect the name and definition location of the invocation. This is
   /// shared across multiple calls to the same method.
-  Usage<InstanceReference> _getCall(ast.Class cls) {
-    final definition = _definitionFromClass(cls);
-    return _instancesForClass[cls] ??= Usage(
-      definition: definition,
-      references: [],
+  void _addToUsage(ast.Class cls, InstanceReference instance) {
+    var (:identifier, :loadingUnit) = _definitionFromClass(cls);
+    instancesForClass.update(
+      identifier,
+      (usage) => usage..add(instance),
+      ifAbsent: () => [instance],
     );
+    loadingUnitForDefinition.update(identifier, (value) {
+      assert(value == loadingUnit);
+      return value;
+    }, ifAbsent: () => loadingUnit);
   }
 
-  Definition _definitionFromClass(ast.Class cls) {
+  ({Identifier identifier, String loadingUnit}) _definitionFromClass(
+    ast.Class cls,
+  ) {
     final enclosingLibrary = cls.enclosingLibrary;
     final file = getImportUri(enclosingLibrary, _source);
 
-    return Definition(
+    return (
       identifier: Identifier(importUri: file, name: cls.name),
-      location: cls.location!.recordLocation(_source),
       loadingUnit:
           loadingUnitForNode(cls.enclosingLibrary, _loadingUnits).toString(),
     );
@@ -76,7 +80,7 @@
     ast.ConstantExpression expression,
     ast.InstanceConstant constant,
   ) => InstanceReference(
-    location: expression.location!.recordLocation(_source),
+    location: expression.location!.recordLocation(_source, exactLocation),
     instanceConstant: _fieldsFromConstant(constant),
     loadingUnit: loadingUnitForNode(expression, _loadingUnits).toString(),
   );
diff --git a/pkg/vm/lib/transformations/record_use/record_use.dart b/pkg/vm/lib/transformations/record_use/record_use.dart
index 5515220..b58e957 100644
--- a/pkg/vm/lib/transformations/record_use/record_use.dart
+++ b/pkg/vm/lib/transformations/record_use/record_use.dart
@@ -36,15 +36,24 @@
       component.metadata[tag] as LoadingUnitsMetadataRepository;
   final loadingUnits = loadingMetadata.mapping[component]?.loadingUnits ?? [];
 
-  final staticCallRecorder = CallRecorder(source, loadingUnits);
-  final instanceUseRecorder = InstanceRecorder(source, loadingUnits);
-  component.accept(_RecordUseVisitor(staticCallRecorder, instanceUseRecorder));
+  final callRecorder = CallRecorder(source, loadingUnits);
+  final instanceRecorder = InstanceRecorder(source, loadingUnits);
+  component.accept(_RecordUseVisitor(callRecorder, instanceRecorder));
 
   final usages = _usages(
-    staticCallRecorder.foundCalls,
-    instanceUseRecorder.foundInstances,
+    callRecorder.callsForMethod,
+    instanceRecorder.instancesForClass,
+    mergeMaps(
+      callRecorder.loadingUnitForDefinition,
+      instanceRecorder.loadingUnitForDefinition,
+      value: (p0, p1) {
+        // The loading units for the same definition should be the same
+        assert(p0 == p1);
+        return p0;
+      },
+    ),
   );
-  var usagesStorageFormat = usages.toJson();
+  final usagesStorageFormat = usages.toJson();
   File.fromUri(recordedUsagesFile).writeAsStringSync(
     JsonEncoder.withIndent('  ').convert(usagesStorageFormat),
   );
@@ -74,18 +83,29 @@
   }
 }
 
-UsageRecord _usages(
-  Iterable<Usage<CallReference>> calls,
-  Iterable<Usage<InstanceReference>> instances,
+Recordings _usages(
+  Map<Identifier, List<CallReference>> calls,
+  Map<Identifier, List<InstanceReference>> instances,
+  Map<Identifier, String> loadingUnitForDefinition,
 ) {
-  return UsageRecord(
-    metadata: Metadata(
-      comment:
+  return Recordings(
+    metadata: Metadata.fromJson({
+      'comment':
           'Recorded usages of objects tagged with a `RecordUse` annotation',
-      version: Version(0, 1, 0),
+      'version': Version(0, 2, 0).toString(),
+    }),
+    callsForDefinition: calls.map(
+      (key, value) => MapEntry(
+        Definition(identifier: key, loadingUnit: loadingUnitForDefinition[key]),
+        value,
+      ),
     ),
-    calls: calls.toList(),
-    instances: instances.toList(),
+    instancesForDefinition: instances.map(
+      (key, value) => MapEntry(
+        Definition(identifier: key, loadingUnit: loadingUnitForDefinition[key]),
+        value,
+      ),
+    ),
   );
 }
 
@@ -135,10 +155,10 @@
     throw UnsupportedError('$constantType is not supported for recording.');
 
 extension RecordUseLocation on ast.Location {
-  Location recordLocation(Uri source) => Location(
+  Location recordLocation(Uri source, bool exactLocation) => Location(
     uri: relativizeUri(source, this.file, Platform.isWindows),
-    line: line,
-    column: column,
+    line: exactLocation ? line : null,
+    column: exactLocation ? column : null,
   );
 }
 
diff --git a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
index ce30bb0..69d52f4 100644
--- a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
+++ b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
@@ -6,7 +6,7 @@
 import 'package:kernel/core_types.dart';
 import 'package:kernel/type_environment.dart';
 import 'package:front_end/src/api_unstable/vm.dart' show isExtensionTypeThis;
-import 'package:front_end/src/api_prototype/record_use.dart' as RecordUse;
+import 'package:front_end/src/api_prototype/record_use.dart' as recordUse;
 
 import 'analysis.dart';
 import 'table_selector_assigner.dart';
@@ -223,8 +223,7 @@
     /// Disable signature shaking for annotated methods, to prevent removal of
     /// parameters. The consumers of recorded_usages.json expect constant
     /// argument values to be present for all parameters.
-    if (member is Procedure &&
-        RecordUse.findRecordUseAnnotation(member).isNotEmpty) {
+    if (member is Procedure && recordUse.hasRecordUseAnnotation(member)) {
       isChecked = true;
     }
   }
@@ -268,7 +267,8 @@
             .isMemberReferencedFromNativeCode(member) ||
         shaker.typeFlowAnalysis.nativeCodeOracle.isRecognized(member) ||
         member.isExternal ||
-        member.name.text == '==') {
+        member.name.text == '==' ||
+        recordUse.hasRecordUseAnnotation(member)) {
       info.eligible = false;
     }
   }
diff --git a/pkg/vm/test/transformations/record_use_test.dart b/pkg/vm/test/transformations/record_use_test.dart
index fc4c5df..c597316 100644
--- a/pkg/vm/test/transformations/record_use_test.dart
+++ b/pkg/vm/test/transformations/record_use_test.dart
@@ -79,14 +79,12 @@
     final testCasesDir = Directory.fromUri(
       _pkgVmDir.resolve('testcases/transformations/record_use/'),
     );
-
     for (var file
         in testCasesDir
             .listSync(recursive: true, followLinks: false)
             .reversed) {
       if (file.path.endsWith('.dart') &&
           !file.path.contains('helper') &&
-          !file.path.contains('instance_complex') &&
           (filter == null || file.path.contains(filter))) {
         test(
           '${file.path} aot',
diff --git a/pkg/vm/testcases/transformations/record_use/complex.dart.json.expect b/pkg/vm/testcases/transformations/record_use/complex.dart.json.expect
index f8087c4..b9496ea 100644
--- a/pkg/vm/testcases/transformations/record_use/complex.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/complex.dart.json.expect
@@ -1,58 +1,41 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "complex.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "parent": "OtherClass",
-      "name": "generate"
-    }
-  ],
   "constants": [
     {
       "type": "int",
       "value": 42
     }
   ],
-  "calls": [
+  "locations": [
+    {
+      "uri": "complex.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0,
-          "line": 24,
-          "column": 25
+        "identifier": {
+          "uri": "complex.dart",
+          "scope": "OtherClass",
+          "name": "generate"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "calls": [
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "4": 0
-              }
-            },
-            "nonConst": {
-              "positional": [
-                0,
-                1,
-                2,
-                3
-              ]
-            }
-          },
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 20,
-            "column": 18
-          }
+          "type": "with_arguments",
+          "positional": [
+            null,
+            null,
+            null,
+            null,
+            0
+          ],
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     }
diff --git a/pkg/vm/testcases/transformations/record_use/different.dart.json.expect b/pkg/vm/testcases/transformations/record_use/different.dart.json.expect
index d95dcdd..e463d4d 100644
--- a/pkg/vm/testcases/transformations/record_use/different.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/different.dart.json.expect
@@ -1,9 +1,6 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
-  },
-  "uris": [],
-  "ids": [],
-  "constants": []
+    "version": "0.2.0"
+  }
 }
\ No newline at end of file
diff --git a/pkg/vm/testcases/transformations/record_use/extension.dart.json.expect b/pkg/vm/testcases/transformations/record_use/extension.dart.json.expect
index 7440708..a911545 100644
--- a/pkg/vm/testcases/transformations/record_use/extension.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/extension.dart.json.expect
@@ -1,49 +1,36 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "extension.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "name": "_extension#0|callWithArgs"
-    }
-  ],
   "constants": [
     {
       "type": "String",
       "value": "42"
     }
   ],
-  "calls": [
+  "locations": [
+    {
+      "uri": "extension.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0,
-          "line": 15,
-          "column": 8
+        "identifier": {
+          "uri": "extension.dart",
+          "name": "_extension#0|callWithArgs"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "calls": [
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "0": 0
-              }
-            }
-          },
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 8,
-            "column": 15
-          }
+          "type": "with_arguments",
+          "positional": [
+            0
+          ],
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     }
diff --git a/pkg/vm/testcases/transformations/record_use/instance_class.dart.json.expect b/pkg/vm/testcases/transformations/record_use/instance_class.dart.json.expect
index 799526f..937c503 100644
--- a/pkg/vm/testcases/transformations/record_use/instance_class.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/instance_class.dart.json.expect
@@ -1,17 +1,8 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "instance_class.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "name": "MyClass"
-    }
-  ],
   "constants": [
     {
       "type": "int",
@@ -24,26 +15,25 @@
       }
     }
   ],
-  "instances": [
+  "locations": [
+    {
+      "uri": "instance_class.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0,
-          "line": 15,
-          "column": 7
+        "identifier": {
+          "uri": "instance_class.dart",
+          "name": "MyClass"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "instances": [
         {
-          "instanceConstant": 1,
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 11,
-            "column": 2
-          }
+          "constant_index": 1,
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     }
diff --git a/pkg/vm/testcases/transformations/record_use/instance_complex.dart.json.expect b/pkg/vm/testcases/transformations/record_use/instance_complex.dart.json.expect
index 8f9d5ce..e8eb867 100644
--- a/pkg/vm/testcases/transformations/record_use/instance_complex.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/instance_complex.dart.json.expect
@@ -1,17 +1,8 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "instance_complex.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "name": "MyClass"
-    }
-  ],
   "constants": [
     {
       "type": "int",
@@ -66,26 +57,25 @@
       }
     }
   ],
-  "instances": [
+  "locations": [
+    {
+      "uri": "instance_complex.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0,
-          "line": 24,
-          "column": 7
+        "identifier": {
+          "uri": "instance_complex.dart",
+          "name": "MyClass"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "instances": [
         {
-          "instanceConstant": 9,
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 11,
-            "column": 2
-          }
+          "constant_index": 9,
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     }
diff --git a/pkg/vm/testcases/transformations/record_use/instance_duplicates.dart.json.expect b/pkg/vm/testcases/transformations/record_use/instance_duplicates.dart.json.expect
index 9559444..815b624 100644
--- a/pkg/vm/testcases/transformations/record_use/instance_duplicates.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/instance_duplicates.dart.json.expect
@@ -1,17 +1,8 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "instance_duplicates.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "name": "MyClass"
-    }
-  ],
   "constants": [
     {
       "type": "int",
@@ -34,35 +25,30 @@
       }
     }
   ],
-  "instances": [
+  "locations": [
+    {
+      "uri": "instance_duplicates.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0,
-          "line": 14,
-          "column": 7
+        "identifier": {
+          "uri": "instance_duplicates.dart",
+          "name": "MyClass"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "instances": [
         {
-          "instanceConstant": 1,
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 8,
-            "column": 15
-          }
+          "constant_index": 1,
+          "loading_unit": "1",
+          "@": 0
         },
         {
-          "instanceConstant": 3,
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 10,
-            "column": 15
-          }
+          "constant_index": 3,
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     }
diff --git a/pkg/vm/testcases/transformations/record_use/instance_method.dart.json.expect b/pkg/vm/testcases/transformations/record_use/instance_method.dart.json.expect
index e3ff3df..4fb90b6 100644
--- a/pkg/vm/testcases/transformations/record_use/instance_method.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/instance_method.dart.json.expect
@@ -1,17 +1,8 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "instance_method.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "name": "MyClass"
-    }
-  ],
   "constants": [
     {
       "type": "int",
@@ -24,26 +15,25 @@
       }
     }
   ],
-  "instances": [
+  "locations": [
+    {
+      "uri": "instance_method.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0,
-          "line": 17,
-          "column": 7
+        "identifier": {
+          "uri": "instance_method.dart",
+          "name": "MyClass"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "instances": [
         {
-          "instanceConstant": 1,
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 11,
-            "column": 2
-          }
+          "constant_index": 1,
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     }
diff --git a/pkg/vm/testcases/transformations/record_use/instance_not_annotation.dart.json.expect b/pkg/vm/testcases/transformations/record_use/instance_not_annotation.dart.json.expect
index f2d8bb1..b15ce8e 100644
--- a/pkg/vm/testcases/transformations/record_use/instance_not_annotation.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/instance_not_annotation.dart.json.expect
@@ -1,42 +1,32 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "instance_not_annotation.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "name": "MyClass"
-    }
-  ],
   "constants": [
     {
       "type": "Instance"
     }
   ],
-  "instances": [
+  "locations": [
+    {
+      "uri": "instance_not_annotation.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0,
-          "line": 13,
-          "column": 7
+        "identifier": {
+          "uri": "instance_not_annotation.dart",
+          "name": "MyClass"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "instances": [
         {
-          "instanceConstant": 0,
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 9,
-            "column": 9
-          }
+          "constant_index": 0,
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     }
diff --git a/pkg/vm/testcases/transformations/record_use/loading_units_multiple.dart.json.expect b/pkg/vm/testcases/transformations/record_use/loading_units_multiple.dart.json.expect
index 049870b..6bc799f 100644
--- a/pkg/vm/testcases/transformations/record_use/loading_units_multiple.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/loading_units_multiple.dart.json.expect
@@ -1,67 +1,48 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "loading_units_multiple_helper_shared.dart",
-    "loading_units_multiple.dart",
-    "loading_units_multiple_helper.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "parent": "SomeClass",
-      "name": "someStaticMethod"
-    }
-  ],
   "constants": [
     {
       "type": "int",
       "value": 42
     }
   ],
-  "calls": [
+  "locations": [
+    {
+      "uri": "loading_units_multiple.dart"
+    },
+    {
+      "uri": "loading_units_multiple_helper.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0,
-          "line": 9,
-          "column": 15
+        "identifier": {
+          "uri": "loading_units_multiple_helper_shared.dart",
+          "scope": "SomeClass",
+          "name": "someStaticMethod"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "calls": [
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "0": 0
-              }
-            }
-          },
-          "loadingUnit": "1",
-          "@": {
-            "uri": 1,
-            "line": 12,
-            "column": 13
-          }
+          "type": "with_arguments",
+          "positional": [
+            0
+          ],
+          "loading_unit": "1",
+          "@": 0
         },
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "0": 0
-              }
-            }
-          },
-          "loadingUnit": "2",
-          "@": {
-            "uri": 2,
-            "line": 8,
-            "column": 13
-          }
+          "type": "with_arguments",
+          "positional": [
+            0
+          ],
+          "loading_unit": "2",
+          "@": 1
         }
       ]
     }
diff --git a/pkg/vm/testcases/transformations/record_use/loading_units_simple.dart.json.expect b/pkg/vm/testcases/transformations/record_use/loading_units_simple.dart.json.expect
index e1708ee..0a46bc9 100644
--- a/pkg/vm/testcases/transformations/record_use/loading_units_simple.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/loading_units_simple.dart.json.expect
@@ -1,84 +1,60 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "loading_units_simple.dart",
-    "loading_units_simple_helper.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "parent": "SomeClass",
-      "name": "someStaticMethod"
-    },
-    {
-      "uri": 1,
-      "parent": "SomeClass",
-      "name": "someStaticMethod"
-    }
-  ],
   "constants": [
     {
       "type": "int",
       "value": 42
     }
   ],
-  "calls": [
+  "locations": [
+    {
+      "uri": "loading_units_simple.dart"
+    },
+    {
+      "uri": "loading_units_simple_helper.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0,
-          "line": 23,
-          "column": 15
+        "identifier": {
+          "uri": "loading_units_simple.dart",
+          "scope": "SomeClass",
+          "name": "someStaticMethod"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "calls": [
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "0": 0
-              }
-            }
-          },
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 14,
-            "column": 13
-          }
+          "type": "with_arguments",
+          "positional": [
+            0
+          ],
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     },
     {
       "definition": {
-        "id": 1,
-        "@": {
-          "uri": 1,
-          "line": 13,
-          "column": 15
+        "identifier": {
+          "uri": "loading_units_simple_helper.dart",
+          "scope": "SomeClass",
+          "name": "someStaticMethod"
         },
-        "loadingUnit": "2"
+        "loading_unit": "2"
       },
-      "references": [
+      "calls": [
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "0": 0
-              }
-            }
-          },
-          "loadingUnit": "2",
-          "@": {
-            "uri": 1,
-            "line": 8,
-            "column": 13
-          }
+          "type": "with_arguments",
+          "positional": [
+            0
+          ],
+          "loading_unit": "2",
+          "@": 1
         }
       ]
     }
diff --git a/pkg/vm/testcases/transformations/record_use/named_and_positional.dart b/pkg/vm/testcases/transformations/record_use/named_and_positional.dart
new file mode 100644
index 0000000..cb412cc
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/named_and_positional.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2023, 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:meta/meta.dart' show RecordUse;
+
+void main() {
+  print(SomeClass.someStaticMethod(3));
+  print(SomeClass.someStaticMethod(5, k: 1));
+  print(SomeClass.someStaticMethod(5, l: 2));
+  print(SomeClass.someStaticMethod(5, l: 2, k: 4));
+}
+
+class SomeClass {
+  @RecordUse()
+  static someStaticMethod(int i, {int? l, int k = 3}) {
+    return i + 1;
+  }
+}
diff --git a/pkg/vm/testcases/transformations/record_use/named_and_positional.dart.aot.expect b/pkg/vm/testcases/transformations/record_use/named_and_positional.dart.aot.expect
new file mode 100644
index 0000000..cc6ba32
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/named_and_positional.dart.aot.expect
@@ -0,0 +1,29 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+import "package:meta/meta.dart" as meta;
+
+import "package:meta/meta.dart" show RecordUse;
+
+abstract class SomeClass extends core::Object {
+
+  [@vm.inferred-return-type.metadata=int]
+  [@vm.unboxing-info.metadata=(i)->i]
+  @#C1
+  static method someStaticMethod([@vm.inferred-arg-type.metadata=dart.core::_Smi] core::int i, {[@vm.inferred-arg-type.metadata=dart.core::_Smi?] core::int? l = #C2, [@vm.inferred-arg-type.metadata=dart.core::_Smi] core::int k = #C3}) → dynamic {
+    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int};
+  }
+}
+
+[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
+static method main() → void {
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod(3));
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod(5, k: 1));
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod(5, l: 2));
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod(5, l: 2, k: 4));
+}
+constants  {
+  #C1 = meta::RecordUse {}
+  #C2 = null
+  #C3 = 3
+}
diff --git a/pkg/vm/testcases/transformations/record_use/named_and_positional.dart.json.expect b/pkg/vm/testcases/transformations/record_use/named_and_positional.dart.json.expect
new file mode 100644
index 0000000..8173d9f
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/named_and_positional.dart.json.expect
@@ -0,0 +1,98 @@
+{
+  "metadata": {
+    "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
+    "version": "0.2.0"
+  },
+  "constants": [
+    {
+      "type": "int",
+      "value": 3
+    },
+    {
+      "type": "Null"
+    },
+    {
+      "type": "int",
+      "value": 5
+    },
+    {
+      "type": "int",
+      "value": 1
+    },
+    {
+      "type": "int",
+      "value": 2
+    },
+    {
+      "type": "int",
+      "value": 4
+    }
+  ],
+  "locations": [
+    {
+      "uri": "named_and_positional.dart"
+    }
+  ],
+  "recordings": [
+    {
+      "definition": {
+        "identifier": {
+          "uri": "named_and_positional.dart",
+          "scope": "SomeClass",
+          "name": "someStaticMethod"
+        },
+        "loading_unit": "1"
+      },
+      "calls": [
+        {
+          "type": "with_arguments",
+          "positional": [
+            0
+          ],
+          "named": {
+            "l": 1,
+            "k": 0
+          },
+          "loading_unit": "1",
+          "@": 0
+        },
+        {
+          "type": "with_arguments",
+          "positional": [
+            2
+          ],
+          "named": {
+            "k": 3,
+            "l": 1
+          },
+          "loading_unit": "1",
+          "@": 0
+        },
+        {
+          "type": "with_arguments",
+          "positional": [
+            2
+          ],
+          "named": {
+            "l": 4,
+            "k": 0
+          },
+          "loading_unit": "1",
+          "@": 0
+        },
+        {
+          "type": "with_arguments",
+          "positional": [
+            2
+          ],
+          "named": {
+            "l": 4,
+            "k": 5
+          },
+          "loading_unit": "1",
+          "@": 0
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/pkg/vm/testcases/transformations/record_use/named_both.dart b/pkg/vm/testcases/transformations/record_use/named_both.dart
new file mode 100644
index 0000000..cb90355
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/named_both.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2023, 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:meta/meta.dart' show RecordUse;
+
+void main() {
+  print(SomeClass.someStaticMethod(i: 3));
+  print(SomeClass.someStaticMethod(i: 5, k: 1));
+  print(SomeClass.someStaticMethod(i: 5, l: 2));
+  print(SomeClass.someStaticMethod(i: 5, l: 2, k: 4));
+}
+
+class SomeClass {
+  @RecordUse()
+  static someStaticMethod({required int i, int? l, int k = 3}) {
+    return i + 1;
+  }
+}
diff --git a/pkg/vm/testcases/transformations/record_use/named_both.dart.aot.expect b/pkg/vm/testcases/transformations/record_use/named_both.dart.aot.expect
new file mode 100644
index 0000000..3161222
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/named_both.dart.aot.expect
@@ -0,0 +1,29 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+import "package:meta/meta.dart" as meta;
+
+import "package:meta/meta.dart" show RecordUse;
+
+abstract class SomeClass extends core::Object {
+
+  [@vm.inferred-return-type.metadata=int]
+  [@vm.unboxing-info.metadata=()->i]
+  @#C1
+  static method someStaticMethod({[@vm.inferred-arg-type.metadata=dart.core::_Smi] required core::int i, [@vm.inferred-arg-type.metadata=dart.core::_Smi?] core::int? l = #C2, [@vm.inferred-arg-type.metadata=dart.core::_Smi] core::int k = #C3}) → dynamic {
+    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int};
+  }
+}
+
+[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
+static method main() → void {
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod(i: 3));
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod(i: 5, k: 1));
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod(i: 5, l: 2));
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod(i: 5, l: 2, k: 4));
+}
+constants  {
+  #C1 = meta::RecordUse {}
+  #C2 = null
+  #C3 = 3
+}
diff --git a/pkg/vm/testcases/transformations/record_use/named_both.dart.json.expect b/pkg/vm/testcases/transformations/record_use/named_both.dart.json.expect
new file mode 100644
index 0000000..6554aa1
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/named_both.dart.json.expect
@@ -0,0 +1,90 @@
+{
+  "metadata": {
+    "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
+    "version": "0.2.0"
+  },
+  "constants": [
+    {
+      "type": "int",
+      "value": 3
+    },
+    {
+      "type": "Null"
+    },
+    {
+      "type": "int",
+      "value": 5
+    },
+    {
+      "type": "int",
+      "value": 1
+    },
+    {
+      "type": "int",
+      "value": 2
+    },
+    {
+      "type": "int",
+      "value": 4
+    }
+  ],
+  "locations": [
+    {
+      "uri": "named_both.dart"
+    }
+  ],
+  "recordings": [
+    {
+      "definition": {
+        "identifier": {
+          "uri": "named_both.dart",
+          "scope": "SomeClass",
+          "name": "someStaticMethod"
+        },
+        "loading_unit": "1"
+      },
+      "calls": [
+        {
+          "type": "with_arguments",
+          "named": {
+            "i": 0,
+            "l": 1,
+            "k": 0
+          },
+          "loading_unit": "1",
+          "@": 0
+        },
+        {
+          "type": "with_arguments",
+          "named": {
+            "i": 2,
+            "k": 3,
+            "l": 1
+          },
+          "loading_unit": "1",
+          "@": 0
+        },
+        {
+          "type": "with_arguments",
+          "named": {
+            "i": 2,
+            "l": 4,
+            "k": 0
+          },
+          "loading_unit": "1",
+          "@": 0
+        },
+        {
+          "type": "with_arguments",
+          "named": {
+            "i": 2,
+            "l": 4,
+            "k": 5
+          },
+          "loading_unit": "1",
+          "@": 0
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/pkg/vm/testcases/transformations/record_use/named_optional.dart b/pkg/vm/testcases/transformations/record_use/named_optional.dart
new file mode 100644
index 0000000..05f37b1
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/named_optional.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2023, 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:meta/meta.dart' show RecordUse;
+
+void main() {
+  print(SomeClass.someStaticMethod(i: 3));
+  print(SomeClass.someStaticMethod());
+}
+
+class SomeClass {
+  @RecordUse()
+  static someStaticMethod({int i = 4}) {
+    return i + 1;
+  }
+}
diff --git a/pkg/vm/testcases/transformations/record_use/named_optional.dart.aot.expect b/pkg/vm/testcases/transformations/record_use/named_optional.dart.aot.expect
new file mode 100644
index 0000000..0745099
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/named_optional.dart.aot.expect
@@ -0,0 +1,26 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+import "package:meta/meta.dart" as meta;
+
+import "package:meta/meta.dart" show RecordUse;
+
+abstract class SomeClass extends core::Object {
+
+  [@vm.inferred-return-type.metadata=int]
+  [@vm.unboxing-info.metadata=()->i]
+  @#C1
+  static method someStaticMethod({[@vm.inferred-arg-type.metadata=dart.core::_Smi] core::int i = #C2}) → dynamic {
+    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int};
+  }
+}
+
+[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
+static method main() → void {
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod(i: 3));
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod());
+}
+constants  {
+  #C1 = meta::RecordUse {}
+  #C2 = 4
+}
diff --git a/pkg/vm/testcases/transformations/record_use/named_optional.dart.json.expect b/pkg/vm/testcases/transformations/record_use/named_optional.dart.json.expect
new file mode 100644
index 0000000..6ab0085
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/named_optional.dart.json.expect
@@ -0,0 +1,51 @@
+{
+  "metadata": {
+    "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
+    "version": "0.2.0"
+  },
+  "constants": [
+    {
+      "type": "int",
+      "value": 3
+    },
+    {
+      "type": "int",
+      "value": 4
+    }
+  ],
+  "locations": [
+    {
+      "uri": "named_optional.dart"
+    }
+  ],
+  "recordings": [
+    {
+      "definition": {
+        "identifier": {
+          "uri": "named_optional.dart",
+          "scope": "SomeClass",
+          "name": "someStaticMethod"
+        },
+        "loading_unit": "1"
+      },
+      "calls": [
+        {
+          "type": "with_arguments",
+          "named": {
+            "i": 0
+          },
+          "loading_unit": "1",
+          "@": 0
+        },
+        {
+          "type": "with_arguments",
+          "named": {
+            "i": 1
+          },
+          "loading_unit": "1",
+          "@": 0
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/pkg/vm/testcases/transformations/record_use/named_required.dart b/pkg/vm/testcases/transformations/record_use/named_required.dart
new file mode 100644
index 0000000..cedddc6
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/named_required.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2023, 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:meta/meta.dart' show RecordUse;
+
+void main() {
+  print(SomeClass.someStaticMethod(i: 3));
+  print(SomeClass.someStaticMethod(i: 5));
+}
+
+class SomeClass {
+  @RecordUse()
+  static someStaticMethod({required int i}) {
+    return i + 1;
+  }
+}
diff --git a/pkg/vm/testcases/transformations/record_use/named_required.dart.aot.expect b/pkg/vm/testcases/transformations/record_use/named_required.dart.aot.expect
new file mode 100644
index 0000000..758584b
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/named_required.dart.aot.expect
@@ -0,0 +1,25 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+import "package:meta/meta.dart" as meta;
+
+import "package:meta/meta.dart" show RecordUse;
+
+abstract class SomeClass extends core::Object {
+
+  [@vm.inferred-return-type.metadata=int]
+  [@vm.unboxing-info.metadata=()->i]
+  @#C1
+  static method someStaticMethod({[@vm.inferred-arg-type.metadata=dart.core::_Smi] required core::int i}) → dynamic {
+    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int};
+  }
+}
+
+[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
+static method main() → void {
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod(i: 3));
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod(i: 5));
+}
+constants  {
+  #C1 = meta::RecordUse {}
+}
diff --git a/pkg/vm/testcases/transformations/record_use/named_required.dart.json.expect b/pkg/vm/testcases/transformations/record_use/named_required.dart.json.expect
new file mode 100644
index 0000000..2b9cd08
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/named_required.dart.json.expect
@@ -0,0 +1,51 @@
+{
+  "metadata": {
+    "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
+    "version": "0.2.0"
+  },
+  "constants": [
+    {
+      "type": "int",
+      "value": 3
+    },
+    {
+      "type": "int",
+      "value": 5
+    }
+  ],
+  "locations": [
+    {
+      "uri": "named_required.dart"
+    }
+  ],
+  "recordings": [
+    {
+      "definition": {
+        "identifier": {
+          "uri": "named_required.dart",
+          "scope": "SomeClass",
+          "name": "someStaticMethod"
+        },
+        "loading_unit": "1"
+      },
+      "calls": [
+        {
+          "type": "with_arguments",
+          "named": {
+            "i": 0
+          },
+          "loading_unit": "1",
+          "@": 0
+        },
+        {
+          "type": "with_arguments",
+          "named": {
+            "i": 1
+          },
+          "loading_unit": "1",
+          "@": 0
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/pkg/vm/testcases/transformations/record_use/nested.dart.json.expect b/pkg/vm/testcases/transformations/record_use/nested.dart.json.expect
index 560496d..eb0bfe4 100644
--- a/pkg/vm/testcases/transformations/record_use/nested.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/nested.dart.json.expect
@@ -1,21 +1,8 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "nested.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "name": "MyClass"
-    },
-    {
-      "uri": 0,
-      "name": "MyOtherClass"
-    }
-  ],
   "constants": [
     {
       "type": "int",
@@ -41,57 +28,46 @@
       "type": "Instance"
     }
   ],
-  "instances": [
+  "locations": [
+    {
+      "uri": "nested.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0,
-          "line": 16,
-          "column": 7
+        "identifier": {
+          "uri": "nested.dart",
+          "name": "MyClass"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "instances": [
         {
-          "instanceConstant": 1,
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 12,
-            "column": 9
-          }
+          "constant_index": 1,
+          "loading_unit": "1",
+          "@": 0
         },
         {
-          "instanceConstant": 3,
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 12,
-            "column": 9
-          }
+          "constant_index": 3,
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     },
     {
       "definition": {
-        "id": 1,
-        "@": {
-          "uri": 0,
-          "line": 23,
-          "column": 7
+        "identifier": {
+          "uri": "nested.dart",
+          "name": "MyOtherClass"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "instances": [
         {
-          "instanceConstant": 4,
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 12,
-            "column": 9
-          }
+          "constant_index": 4,
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     }
diff --git a/pkg/vm/testcases/transformations/record_use/partfile_main.dart.json.expect b/pkg/vm/testcases/transformations/record_use/partfile_main.dart.json.expect
index 397f6bc..7401831 100644
--- a/pkg/vm/testcases/transformations/record_use/partfile_main.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/partfile_main.dart.json.expect
@@ -1,51 +1,37 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "partfile_main.dart",
-    "partfile_helper.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "parent": "SomeClass",
-      "name": "someStaticMethod"
-    }
-  ],
   "constants": [
     {
       "type": "int",
       "value": 42
     }
   ],
-  "calls": [
+  "locations": [
+    {
+      "uri": "partfile_main.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 1,
-          "line": 9,
-          "column": 10
+        "identifier": {
+          "uri": "partfile_main.dart",
+          "scope": "SomeClass",
+          "name": "someStaticMethod"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "calls": [
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "0": 0
-              }
-            }
-          },
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 9,
-            "column": 19
-          }
+          "type": "with_arguments",
+          "positional": [
+            0
+          ],
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     }
diff --git a/pkg/vm/testcases/transformations/record_use/positional_both.dart b/pkg/vm/testcases/transformations/record_use/positional_both.dart
new file mode 100644
index 0000000..4277e30
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/positional_both.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2023, 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:meta/meta.dart' show RecordUse;
+
+void main() {
+  print(SomeClass.someStaticMethod(5, 3));
+  print(SomeClass.someStaticMethod(6));
+}
+
+class SomeClass {
+  @RecordUse()
+  static someStaticMethod(int k, [int i = 4]) {
+    return i + 1;
+  }
+}
diff --git a/pkg/vm/testcases/transformations/record_use/positional_both.dart.aot.expect b/pkg/vm/testcases/transformations/record_use/positional_both.dart.aot.expect
new file mode 100644
index 0000000..ae0525d
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/positional_both.dart.aot.expect
@@ -0,0 +1,26 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+import "package:meta/meta.dart" as meta;
+
+import "package:meta/meta.dart" show RecordUse;
+
+abstract class SomeClass extends core::Object {
+
+  [@vm.inferred-return-type.metadata=int]
+  [@vm.unboxing-info.metadata=(i)->i]
+  @#C1
+  static method someStaticMethod([@vm.inferred-arg-type.metadata=dart.core::_Smi] core::int k, [[@vm.inferred-arg-type.metadata=dart.core::_Smi] core::int i = #C2]) → dynamic {
+    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int};
+  }
+}
+
+[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
+static method main() → void {
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod(5, 3));
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod(6));
+}
+constants  {
+  #C1 = meta::RecordUse {}
+  #C2 = 4
+}
diff --git a/pkg/vm/testcases/transformations/record_use/positional_both.dart.json.expect b/pkg/vm/testcases/transformations/record_use/positional_both.dart.json.expect
new file mode 100644
index 0000000..a12ed12
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/positional_both.dart.json.expect
@@ -0,0 +1,61 @@
+{
+  "metadata": {
+    "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
+    "version": "0.2.0"
+  },
+  "constants": [
+    {
+      "type": "int",
+      "value": 5
+    },
+    {
+      "type": "int",
+      "value": 3
+    },
+    {
+      "type": "int",
+      "value": 6
+    },
+    {
+      "type": "int",
+      "value": 4
+    }
+  ],
+  "locations": [
+    {
+      "uri": "positional_both.dart"
+    }
+  ],
+  "recordings": [
+    {
+      "definition": {
+        "identifier": {
+          "uri": "positional_both.dart",
+          "scope": "SomeClass",
+          "name": "someStaticMethod"
+        },
+        "loading_unit": "1"
+      },
+      "calls": [
+        {
+          "type": "with_arguments",
+          "positional": [
+            0,
+            1
+          ],
+          "loading_unit": "1",
+          "@": 0
+        },
+        {
+          "type": "with_arguments",
+          "positional": [
+            2,
+            3
+          ],
+          "loading_unit": "1",
+          "@": 0
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/pkg/vm/testcases/transformations/record_use/positional_optional.dart b/pkg/vm/testcases/transformations/record_use/positional_optional.dart
new file mode 100644
index 0000000..5c09560
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/positional_optional.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2023, 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:meta/meta.dart' show RecordUse;
+
+void main() {
+  print(SomeClass.someStaticMethod(3));
+  print(SomeClass.someStaticMethod());
+}
+
+class SomeClass {
+  @RecordUse()
+  static someStaticMethod([int i = 4]) {
+    return i + 1;
+  }
+}
diff --git a/pkg/vm/testcases/transformations/record_use/positional_optional.dart.aot.expect b/pkg/vm/testcases/transformations/record_use/positional_optional.dart.aot.expect
new file mode 100644
index 0000000..8ded2fbf
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/positional_optional.dart.aot.expect
@@ -0,0 +1,26 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+import "package:meta/meta.dart" as meta;
+
+import "package:meta/meta.dart" show RecordUse;
+
+abstract class SomeClass extends core::Object {
+
+  [@vm.inferred-return-type.metadata=int]
+  [@vm.unboxing-info.metadata=()->i]
+  @#C1
+  static method someStaticMethod([[@vm.inferred-arg-type.metadata=dart.core::_Smi] core::int i = #C2]) → dynamic {
+    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int};
+  }
+}
+
+[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
+static method main() → void {
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod(3));
+  core::print([@vm.inferred-type.metadata=int] self::SomeClass::someStaticMethod());
+}
+constants  {
+  #C1 = meta::RecordUse {}
+  #C2 = 4
+}
diff --git a/pkg/vm/testcases/transformations/record_use/positional_optional.dart.json.expect b/pkg/vm/testcases/transformations/record_use/positional_optional.dart.json.expect
new file mode 100644
index 0000000..9bf24a4
--- /dev/null
+++ b/pkg/vm/testcases/transformations/record_use/positional_optional.dart.json.expect
@@ -0,0 +1,51 @@
+{
+  "metadata": {
+    "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
+    "version": "0.2.0"
+  },
+  "constants": [
+    {
+      "type": "int",
+      "value": 3
+    },
+    {
+      "type": "int",
+      "value": 4
+    }
+  ],
+  "locations": [
+    {
+      "uri": "positional_optional.dart"
+    }
+  ],
+  "recordings": [
+    {
+      "definition": {
+        "identifier": {
+          "uri": "positional_optional.dart",
+          "scope": "SomeClass",
+          "name": "someStaticMethod"
+        },
+        "loading_unit": "1"
+      },
+      "calls": [
+        {
+          "type": "with_arguments",
+          "positional": [
+            0
+          ],
+          "loading_unit": "1",
+          "@": 0
+        },
+        {
+          "type": "with_arguments",
+          "positional": [
+            1
+          ],
+          "loading_unit": "1",
+          "@": 0
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/pkg/vm/testcases/transformations/record_use/simple.dart.json.expect b/pkg/vm/testcases/transformations/record_use/simple.dart.json.expect
index 72d9f63..f78583c 100644
--- a/pkg/vm/testcases/transformations/record_use/simple.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/simple.dart.json.expect
@@ -1,50 +1,37 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "simple.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "parent": "SomeClass",
-      "name": "someStaticMethod"
-    }
-  ],
   "constants": [
     {
       "type": "int",
       "value": 42
     }
   ],
-  "calls": [
+  "locations": [
+    {
+      "uri": "simple.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0,
-          "line": 13,
-          "column": 10
+        "identifier": {
+          "uri": "simple.dart",
+          "scope": "SomeClass",
+          "name": "someStaticMethod"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "calls": [
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "0": 0
-              }
-            }
-          },
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 8,
-            "column": 19
-          }
+          "type": "with_arguments",
+          "positional": [
+            0
+          ],
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     }
diff --git a/pkg/vm/testcases/transformations/record_use/tearoff.dart.json.expect b/pkg/vm/testcases/transformations/record_use/tearoff.dart.json.expect
index 7699d75..777ad9e 100644
--- a/pkg/vm/testcases/transformations/record_use/tearoff.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/tearoff.dart.json.expect
@@ -1,45 +1,28 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "tearoff.dart"
-  ],
-  "ids": [
+  "locations": [
     {
-      "uri": 0,
-      "parent": "SomeClass",
-      "name": "someStaticMethod"
+      "uri": "tearoff.dart"
     }
   ],
-  "constants": [],
-  "calls": [
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0,
-          "line": 15,
-          "column": 10
+        "identifier": {
+          "uri": "tearoff.dart",
+          "scope": "SomeClass",
+          "name": "someStaticMethod"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "calls": [
         {
-          "arguments": {
-            "nonConst": {
-              "positional": [
-                0
-              ]
-            }
-          },
-          "loadingUnit": null,
-          "@": {
-            "uri": 0,
-            "line": 11,
-            "column": 27
-          }
+          "type": "tearoff",
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     }
diff --git a/pkg/vm/testcases/transformations/record_use/top_level_method.dart.json.expect b/pkg/vm/testcases/transformations/record_use/top_level_method.dart.json.expect
index e0a2a0a..c3cf404 100644
--- a/pkg/vm/testcases/transformations/record_use/top_level_method.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/top_level_method.dart.json.expect
@@ -1,49 +1,36 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "top_level_method.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "name": "someTopLevelMethod"
-    }
-  ],
   "constants": [
     {
       "type": "int",
       "value": 42
     }
   ],
-  "calls": [
+  "locations": [
+    {
+      "uri": "top_level_method.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0,
-          "line": 12,
-          "column": 5
+        "identifier": {
+          "uri": "top_level_method.dart",
+          "name": "someTopLevelMethod"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "calls": [
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "0": 0
-              }
-            }
-          },
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 8,
-            "column": 9
-          }
+          "type": "with_arguments",
+          "positional": [
+            0
+          ],
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     }
diff --git a/pkg/vm/testcases/transformations/record_use/types_of_arguments.dart.json.expect b/pkg/vm/testcases/transformations/record_use/types_of_arguments.dart.json.expect
index 82ab669..64c863f 100644
--- a/pkg/vm/testcases/transformations/record_use/types_of_arguments.dart.json.expect
+++ b/pkg/vm/testcases/transformations/record_use/types_of_arguments.dart.json.expect
@@ -1,18 +1,8 @@
 {
   "metadata": {
     "comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
-    "version": "0.1.0"
+    "version": "0.2.0"
   },
-  "uris": [
-    "types_of_arguments.dart"
-  ],
-  "ids": [
-    {
-      "uri": 0,
-      "parent": "SomeClass",
-      "name": "someStaticMethod"
-    }
-  ],
   "constants": [
     {
       "type": "int",
@@ -67,107 +57,69 @@
       }
     }
   ],
-  "calls": [
+  "locations": [
+    {
+      "uri": "types_of_arguments.dart"
+    }
+  ],
+  "recordings": [
     {
       "definition": {
-        "id": 0,
-        "@": {
-          "uri": 0,
-          "line": 24,
-          "column": 17
+        "identifier": {
+          "uri": "types_of_arguments.dart",
+          "scope": "SomeClass",
+          "name": "someStaticMethod"
         },
-        "loadingUnit": "1"
+        "loading_unit": "1"
       },
-      "references": [
+      "calls": [
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "0": 0
-              }
-            }
-          },
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 8,
-            "column": 19
-          }
+          "type": "with_arguments",
+          "positional": [
+            0
+          ],
+          "loading_unit": "1",
+          "@": 0
         },
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "0": 1
-              }
-            }
-          },
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 9,
-            "column": 19
-          }
+          "type": "with_arguments",
+          "positional": [
+            1
+          ],
+          "loading_unit": "1",
+          "@": 0
         },
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "0": 2
-              }
-            }
-          },
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 10,
-            "column": 19
-          }
+          "type": "with_arguments",
+          "positional": [
+            2
+          ],
+          "loading_unit": "1",
+          "@": 0
         },
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "0": 3
-              }
-            }
-          },
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 11,
-            "column": 19
-          }
+          "type": "with_arguments",
+          "positional": [
+            3
+          ],
+          "loading_unit": "1",
+          "@": 0
         },
         {
-          "arguments": {
-            "const": {
-              "positional": {
-                "0": 10
-              }
-            }
-          },
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 13,
-            "column": 15
-          }
+          "type": "with_arguments",
+          "positional": [
+            10
+          ],
+          "loading_unit": "1",
+          "@": 0
         },
         {
-          "arguments": {
-            "nonConst": {
-              "positional": [
-                0
-              ]
-            }
-          },
-          "loadingUnit": "1",
-          "@": {
-            "uri": 0,
-            "line": 19,
-            "column": 19
-          }
+          "type": "with_arguments",
+          "positional": [
+            null
+          ],
+          "loading_unit": "1",
+          "@": 0
         }
       ]
     }
diff --git a/tools/VERSION b/tools/VERSION
index e7c998d..0b1d217 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 3
 MINOR 9
 PATCH 0
-PRERELEASE 64
+PRERELEASE 65
 PRERELEASE_PATCH 0