Version 2.16.0-147.0.dev

Merge commit 'bc0d63a93c68c5dc8e35c43b14d94b50b0b999d1' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
index 0391099..192c94c 100644
--- a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
@@ -432,35 +432,6 @@
     }
   }
 
-  /// Given an [argumentList] and the [executableElement] that will be invoked
-  /// using those argument, compute the list of parameters that correspond to
-  /// the list of arguments. An error will be reported if any of the arguments
-  /// cannot be matched to a parameter. Return the parameters that correspond to
-  /// the arguments, or `null` if no correspondence could be computed.
-  ///
-  /// TODO(scheglov) this is duplicate
-  List<ParameterElement?>? _resolveArgumentsToFunction(
-      ArgumentList argumentList, ExecutableElement? executableElement) {
-    if (executableElement == null) {
-      return null;
-    }
-    List<ParameterElement> parameters = executableElement.parameters;
-    return _resolveArgumentsToParameters(argumentList, parameters);
-  }
-
-  /// Given an [argumentList] and the [parameters] related to the element that
-  /// will be invoked using those arguments, compute the list of parameters that
-  /// correspond to the list of arguments. An error will be reported if any of
-  /// the arguments cannot be matched to a parameter. Return the parameters that
-  /// correspond to the arguments.
-  ///
-  /// TODO(scheglov) this is duplicate
-  List<ParameterElement?> _resolveArgumentsToParameters(
-      ArgumentList argumentList, List<ParameterElement> parameters) {
-    return ResolverVisitor.resolveArgumentsToParameters(
-        argumentList, parameters, _errorReporter.reportErrorForNode);
-  }
-
   void _resolveConstructorInvocationArguments(AnnotationImpl node) {
     var argumentList = node.arguments;
     // error will be reported in ConstantVerifier
@@ -470,10 +441,12 @@
     // resolve arguments to parameters
     var constructor = node.element;
     if (constructor is ConstructorElement) {
-      var parameters = _resolveArgumentsToFunction(argumentList, constructor);
-      if (parameters != null) {
-        argumentList.correspondingStaticParameters = parameters;
-      }
+      argumentList.correspondingStaticParameters =
+          ResolverVisitor.resolveArgumentsToParameters(
+        argumentList: argumentList,
+        parameters: constructor.parameters,
+        errorReporter: _errorReporter,
+      );
     }
   }
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
index f824a1e..481ceb7 100644
--- a/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
@@ -88,7 +88,9 @@
         // Fix up the parameter elements based on inferred method.
         arguments.correspondingStaticParameters =
             ResolverVisitor.resolveArgumentsToParameters(
-                arguments, inferred.parameters, null);
+          argumentList: arguments,
+          parameters: inferred.parameters,
+        );
 
         constructorName.type2.type = inferred.returnType;
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
index d7a8fd2..901f6f8 100644
--- a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
@@ -190,7 +190,9 @@
       // Fix up the parameter elements based on inferred method.
       arguments.correspondingStaticParameters =
           ResolverVisitor.resolveArgumentsToParameters(
-              arguments, inferred.parameters, null);
+        argumentList: arguments,
+        parameters: inferred.parameters,
+      );
       node.staticInvokeType = inferred;
     }
   }
@@ -381,7 +383,9 @@
     // Get the parameters that correspond to the uninstantiated generic.
     List<ParameterElement?> rawParameters =
         ResolverVisitor.resolveArgumentsToParameters(
-            argumentList, rawType.parameters, null);
+      argumentList: argumentList,
+      parameters: rawType.parameters,
+    );
 
     List<ParameterElement> params = <ParameterElement>[];
     List<DartType> argTypes = <DartType>[];
@@ -537,9 +541,9 @@
     FunctionType invokeType,
   ) {
     var parameters = ResolverVisitor.resolveArgumentsToParameters(
-      argumentList,
-      invokeType.parameters,
-      _errorReporter.reportErrorForNode,
+      argumentList: argumentList,
+      parameters: invokeType.parameters,
+      errorReporter: _errorReporter,
     );
     argumentList.correspondingStaticParameters = parameters;
   }
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 344c5e7..2dc6017 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -457,28 +457,10 @@
     if (executableElement == null) {
       return null;
     }
-    List<ParameterElement> parameters = executableElement.parameters;
-    return _resolveArgumentsToParameters(
-      argumentList,
-      parameters,
-      enclosingConstructor: enclosingConstructor,
-    );
-  }
-
-  /// Given an [argumentList] and the [parameters] related to the element that
-  /// will be invoked using those arguments, compute the list of parameters that
-  /// correspond to the list of arguments. An error will be reported if any of
-  /// the arguments cannot be matched to a parameter. Return the parameters that
-  /// correspond to the arguments.
-  List<ParameterElement?> _resolveArgumentsToParameters(
-    ArgumentList argumentList,
-    List<ParameterElement> parameters, {
-    ConstructorDeclaration? enclosingConstructor,
-  }) {
     return ResolverVisitor.resolveArgumentsToParameters(
-      argumentList,
-      parameters,
-      _errorReporter.reportErrorForNode,
+      argumentList: argumentList,
+      parameters: executableElement.parameters,
+      errorReporter: _errorReporter,
       enclosingConstructor: enclosingConstructor,
     );
   }
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index ad495d9..aef17ef 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2324,17 +2324,12 @@
   /// will be invoked using those arguments, compute the list of parameters that
   /// correspond to the list of arguments.
   ///
-  /// An error will be reported to [onError] if any of the arguments cannot be
-  /// matched to a parameter. onError will be provided the node of the first
-  /// argument that is not matched. onError can be null to ignore the error.
-  ///
   /// Returns the parameters that correspond to the arguments. If no parameter
   /// matched an argument, that position will be `null` in the list.
-  static List<ParameterElement?> resolveArgumentsToParameters(
-    ArgumentList argumentList,
-    List<ParameterElement> parameters,
-    void Function(ErrorCode errorCode, AstNode node, [List<Object> arguments])?
-        onError, {
+  static List<ParameterElement?> resolveArgumentsToParameters({
+    required ArgumentList argumentList,
+    required List<ParameterElement> parameters,
+    ErrorReporter? errorReporter,
     ConstructorDeclaration? enclosingConstructor,
   }) {
     if (parameters.isEmpty && argumentList.arguments.isEmpty) {
@@ -2375,20 +2370,16 @@
         String name = nameNode.name;
         var element = namedParameters != null ? namedParameters[name] : null;
         if (element == null) {
-          if (onError != null) {
-            onError(CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER, nameNode,
-                [name]);
-          }
+          errorReporter?.reportErrorForNode(
+              CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER, nameNode, [name]);
         } else {
           resolvedParameters[i] = element;
           nameNode.staticElement = element;
         }
         usedNames ??= HashSet<String>();
         if (!usedNames.add(name)) {
-          if (onError != null) {
-            onError(CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, nameNode,
-                [name]);
-          }
+          errorReporter?.reportErrorForNode(
+              CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, nameNode, [name]);
         }
       } else {
         if (argument is SimpleIdentifier && argument.name.isEmpty) {
@@ -2411,8 +2402,8 @@
           var element = formalParameter.declaredElement
               as SuperFormalParameterElementImpl;
           if (formalParameter.isNamed) {
-            if (onError != null && element.superConstructorParameter == null) {
-              onError(
+            if (element.superConstructorParameter == null) {
+              errorReporter?.reportErrorForNode(
                 CompileTimeErrorCode
                     .SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED,
                 formalParameter.identifier,
@@ -2420,21 +2411,19 @@
             }
           } else {
             positionalArgumentCount++;
-            if (onError != null) {
-              if (hasExplicitPositionalArguments) {
-                onError(
-                  CompileTimeErrorCode
-                      .POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT,
-                  formalParameter.identifier,
-                );
-              }
-              if (element.superConstructorParameter == null) {
-                onError(
-                  CompileTimeErrorCode
-                      .SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL,
-                  formalParameter.identifier,
-                );
-              }
+            if (hasExplicitPositionalArguments) {
+              errorReporter?.reportErrorForNode(
+                CompileTimeErrorCode
+                    .POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT,
+                formalParameter.identifier,
+              );
+            }
+            if (element.superConstructorParameter == null) {
+              errorReporter?.reportErrorForNode(
+                CompileTimeErrorCode
+                    .SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL,
+                formalParameter.identifier,
+              );
             }
           }
         }
@@ -2442,10 +2431,10 @@
     }
 
     if (positionalArgumentCount < requiredParameterCount && noBlankArguments) {
-      if (onError != null) {
-        onError(CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS,
-            argumentList, [requiredParameterCount, positionalArgumentCount]);
-      }
+      errorReporter?.reportErrorForNode(
+          CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS,
+          argumentList,
+          [requiredParameterCount, positionalArgumentCount]);
     } else if (positionalArgumentCount > unnamedParameterCount &&
         noBlankArguments) {
       ErrorCode errorCode;
@@ -2457,8 +2446,8 @@
       } else {
         errorCode = CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS;
       }
-      if (onError != null && firstUnresolvedArgument != null) {
-        onError(errorCode, firstUnresolvedArgument,
+      if (firstUnresolvedArgument != null) {
+        errorReporter?.reportErrorForNode(errorCode, firstUnresolvedArgument,
             [unnamedParameterCount, positionalArgumentCount]);
       }
     }
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index bcd3487..11579a3 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -378,7 +378,9 @@
       // Fix up the parameter elements based on inferred method.
       arguments.correspondingStaticParameters =
           ResolverVisitor.resolveArgumentsToParameters(
-              arguments, inferred.parameters, null);
+        argumentList: arguments,
+        parameters: inferred.parameters,
+      );
       typeName.type = inferred.returnType;
       // Update the static element as well. This is used in some cases, such as
       // computing constant values. It is stored in two places.
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index e1b7997..39a7a01 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -4,6 +4,7 @@
 
 library front_end.compiler_options;
 
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
 import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
     show DiagnosticMessage, DiagnosticMessageHandler;
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
@@ -109,6 +110,12 @@
   /// file system.  TODO(paulberry): fix this.
   FileSystem fileSystem = StandardFileSystem.instance;
 
+  /// Function that creates a [MacroExecutor] if supported.
+  ///
+  /// This is an experimental feature.
+  Future<MacroExecutor> Function() macroExecutorProvider =
+      () async => throw 'Macro execution is not supported.';
+
   /// Whether to generate code for the SDK.
   ///
   /// By default the front end resolves components using a prebuilt SDK summary.
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 521d5ab..65088a1 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -8,6 +8,8 @@
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+
 import 'package:_fe_analyzer_shared/src/util/libraries_specification.dart'
     show
         LibrariesSpecification,
@@ -854,6 +856,9 @@
     }
   }
 
+  Future<MacroExecutor> Function() get macroExecutorProvider =>
+      _raw.macroExecutorProvider;
+
   CompilerOptions get rawOptionsForTesting => _raw;
 }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 3504c3a..7b98124 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -390,6 +390,7 @@
       loader.resolveParts();
       loader.computeMacroDeclarations();
       loader.computeLibraryScopes();
+      await loader.computeMacroApplications();
       setupTopAndBottomTypes();
       loader.resolveTypes();
       loader.computeVariances();
@@ -397,7 +398,6 @@
           dynamicType, nullType, bottomType, objectClassBuilder);
       List<SourceClassBuilder> sourceClassBuilders =
           loader.checkSemantics(objectClassBuilder);
-      loader.computeMacroApplications();
       loader.finishTypeVariables(objectClassBuilder, dynamicType);
       loader.createTypeInferenceEngine();
       loader.buildComponent();
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro.dart
index 65a8279..3055eea 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -2,7 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:kernel/ast.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+
+import '../builder/class_builder.dart';
+import '../builder/member_builder.dart';
+import '../source/source_class_builder.dart';
+import '../source/source_library_builder.dart';
 
 bool enableMacros = false;
 
@@ -17,7 +22,48 @@
 }
 
 class MacroApplicationData {
-  Map<Library, LibraryMacroApplicationData> libraryData = {};
+  Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData = {};
+
+  Future<void> loadMacroIds(
+      Future<MacroExecutor> Function() macroExecutorProvider) async {
+    MacroExecutor macroExecutor = await macroExecutorProvider();
+
+    Map<ClassBuilder, MacroClassIdentifier> classIdCache = {};
+
+    Map<MacroApplication, MacroInstanceIdentifier> instanceIdCache = {};
+
+    Future<void> ensureMacroClassIds(MacroApplications? applications) async {
+      if (applications != null) {
+        for (MacroApplication application in applications.macros) {
+          MacroClassIdentifier macroClass =
+              classIdCache[application.classBuilder] ??=
+                  await macroExecutor.loadMacro(
+                      application.classBuilder.library.importUri,
+                      application.classBuilder.name);
+          instanceIdCache[application] = await macroExecutor.instantiateMacro(
+              macroClass,
+              application.constructorName,
+              // TODO(johnniwinther): Support macro arguments.
+              new Arguments([], {}));
+        }
+      }
+    }
+
+    for (LibraryMacroApplicationData libraryData in libraryData.values) {
+      for (ClassMacroApplicationData classData
+          in libraryData.classData.values) {
+        await ensureMacroClassIds(classData.classApplications);
+        for (MacroApplications applications
+            in classData.memberApplications.values) {
+          await ensureMacroClassIds(applications);
+        }
+      }
+      for (MacroApplications applications
+          in libraryData.memberApplications.values) {
+        await ensureMacroClassIds(applications);
+      }
+    }
+  }
 }
 
 class MacroApplications {
@@ -27,19 +73,19 @@
 }
 
 class MacroApplication {
-  final Class cls;
+  final ClassBuilder classBuilder;
   final String constructorName;
   // TODO(johnniwinther): Add support for arguments.
 
-  MacroApplication(this.cls, this.constructorName);
+  MacroApplication(this.classBuilder, this.constructorName);
 }
 
 class LibraryMacroApplicationData {
-  Map<Class, ClassMacroApplicationData> classData = {};
-  Map<Member, MacroApplications> memberApplications = {};
+  Map<SourceClassBuilder, ClassMacroApplicationData> classData = {};
+  Map<MemberBuilder, MacroApplications> memberApplications = {};
 }
 
 class ClassMacroApplicationData {
   MacroApplications? classApplications;
-  Map<Member, MacroApplications> memberApplications = {};
+  Map<MemberBuilder, MacroApplications> memberApplications = {};
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro_annotation_parser.dart b/pkg/front_end/lib/src/fasta/kernel/macro_annotation_parser.dart
index 118e001..02b0dc4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro_annotation_parser.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro_annotation_parser.dart
@@ -155,7 +155,7 @@
           constructorName != null &&
           argumentsNode is _ArgumentsNode) {
         push(new _MacroApplicationNode(
-            new MacroApplication(macroClass.cls, constructorName)));
+            new MacroApplication(macroClass, constructorName)));
         return;
       }
     }
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 07b1207..2b0ad49 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -1387,7 +1387,7 @@
     }
   }
 
-  void computeMacroApplications() {
+  Future<void> computeMacroApplications() async {
     if (!enableMacros || _macroClassBuilder == null) return;
 
     MacroApplications? computeApplications(
@@ -1403,6 +1403,7 @@
       return result != null ? new MacroApplications(result) : null;
     }
 
+    MacroApplicationData macroApplicationData = new MacroApplicationData();
     for (SourceLibraryBuilder libraryBuilder in sourceLibraryBuilders) {
       // TODO(johnniwinther): Handle patch libraries.
       LibraryMacroApplicationData libraryMacroApplicationData =
@@ -1427,8 +1428,7 @@
                   memberBuilder.fileUri,
                   memberBuilder.metadata);
               if (macroApplications != null) {
-                classMacroApplicationData
-                        .memberApplications[memberBuilder.procedure] =
+                classMacroApplicationData.memberApplications[memberBuilder] =
                     macroApplications;
               }
             } else if (memberBuilder is SourceFieldBuilder) {
@@ -1438,8 +1438,7 @@
                   memberBuilder.fileUri,
                   memberBuilder.metadata);
               if (macroApplications != null) {
-                classMacroApplicationData
-                        .memberApplications[memberBuilder.field] =
+                classMacroApplicationData.memberApplications[memberBuilder] =
                     macroApplications;
               }
             }
@@ -1452,8 +1451,7 @@
                   memberBuilder.fileUri,
                   memberBuilder.metadata);
               if (macroApplications != null) {
-                classMacroApplicationData
-                        .memberApplications[memberBuilder.constructor] =
+                classMacroApplicationData.memberApplications[memberBuilder] =
                     macroApplications;
               }
             }
@@ -1461,7 +1459,7 @@
 
           if (classMacroApplicationData.classApplications != null ||
               classMacroApplicationData.memberApplications.isNotEmpty) {
-            libraryMacroApplicationData.classData[builder.cls] =
+            libraryMacroApplicationData.classData[builder] =
                 classMacroApplicationData;
           }
         } else if (builder is SourceProcedureBuilder) {
@@ -1471,7 +1469,7 @@
               builder.fileUri,
               builder.metadata);
           if (macroApplications != null) {
-            libraryMacroApplicationData.memberApplications[builder.procedure] =
+            libraryMacroApplicationData.memberApplications[builder] =
                 macroApplications;
           }
         } else if (builder is SourceFieldBuilder) {
@@ -1481,20 +1479,25 @@
               builder.fileUri,
               builder.metadata);
           if (macroApplications != null) {
-            libraryMacroApplicationData.memberApplications[builder.field] =
+            libraryMacroApplicationData.memberApplications[builder] =
                 macroApplications;
           }
         }
       }
       if (libraryMacroApplicationData.classData.isNotEmpty ||
           libraryMacroApplicationData.memberApplications.isNotEmpty) {
+        macroApplicationData.libraryData[libraryBuilder] =
+            libraryMacroApplicationData;
         if (retainDataForTesting) {
-          dataForTesting!
-                  .macroApplicationData.libraryData[libraryBuilder.library] =
+          dataForTesting!.macroApplicationData.libraryData[libraryBuilder] =
               libraryMacroApplicationData;
         }
       }
     }
+    if (macroApplicationData.libraryData.isNotEmpty) {
+      await macroApplicationData
+          .loadMacroIds(target.context.options.macroExecutorProvider);
+    }
   }
 
   void finishDeferredLoadTearoffs() {
diff --git a/pkg/front_end/test/macros/data/tests/applications.dart b/pkg/front_end/test/macros/data/tests/applications.dart
index 804253c..4201d8c 100644
--- a/pkg/front_end/test/macros/data/tests/applications.dart
+++ b/pkg/front_end/test/macros/data/tests/applications.dart
@@ -7,6 +7,23 @@
   package:_fe_analyzer_shared/src/macros/api.dart,
   package:macro/macro.dart,
   main.dart],
+ macroClassIds=[
+  package:macro/macro.dart/Macro1,
+  package:macro/macro.dart/Macro2,
+  package:macro/macro.dart/Macro3],
+ macroInstanceIds=[
+  package:macro/macro.dart/Macro1/(),
+  package:macro/macro.dart/Macro1/(),
+  package:macro/macro.dart/Macro1/named(),
+  package:macro/macro.dart/Macro2/(),
+  package:macro/macro.dart/Macro2/named(),
+  package:macro/macro.dart/Macro2/named(),
+  package:macro/macro.dart/Macro2/named(),
+  package:macro/macro.dart/Macro3/(),
+  package:macro/macro.dart/Macro3/(),
+  package:macro/macro.dart/Macro3/(),
+  package:macro/macro.dart/Macro3/named(),
+  package:macro/macro.dart/Macro3/named()],
  macrosAreApplied,
  macrosAreAvailable
 */
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart
index a710753..1a6c048 100644
--- a/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart
@@ -7,6 +7,8 @@
   apply_lib_dep.dart|macro_lib_dep.dart|main_lib_dep.dart|package:_fe_analyzer_shared/src/macros/api.dart,
   macro_lib.dart,
   apply_lib.dart|main.dart],
+ macroClassIds=[macro_lib.dart/Macro1],
+ macroInstanceIds=[macro_lib.dart/Macro1/()],
  macrosAreAvailable
 */
 
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart b/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
index 455b1b1..4aeb2a7 100644
--- a/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
@@ -8,6 +8,15 @@
   macro_lib1.dart|macro_lib2a.dart,
   macro_lib2b.dart,
   main.dart],
+ macroClassIds=[
+  macro_lib1.dart/Macro1,
+  macro_lib2a.dart/Macro2a,
+  macro_lib2b.dart/Macro2b],
+ macroInstanceIds=[
+  macro_lib1.dart/Macro1/(),
+  macro_lib2a.dart/Macro2a/(),
+  macro_lib2a.dart/Macro2a/(),
+  macro_lib2b.dart/Macro2b/()],
  macrosAreApplied,
  macrosAreAvailable
 */
diff --git a/pkg/front_end/test/macros/data/tests/use_macro_package.dart b/pkg/front_end/test/macros/data/tests/use_macro_package.dart
index 241eda8..691f58a 100644
--- a/pkg/front_end/test/macros/data/tests/use_macro_package.dart
+++ b/pkg/front_end/test/macros/data/tests/use_macro_package.dart
@@ -7,6 +7,18 @@
   package:_fe_analyzer_shared/src/macros/api.dart,
   package:macro/macro.dart,
   main.dart],
+ macroClassIds=[
+  package:macro/macro.dart/Macro1,
+  package:macro/macro.dart/Macro2,
+  package:macro/macro.dart/Macro3],
+ macroInstanceIds=[
+  package:macro/macro.dart/Macro1/(),
+  package:macro/macro.dart/Macro1/(),
+  package:macro/macro.dart/Macro1/(),
+  package:macro/macro.dart/Macro2/(),
+  package:macro/macro.dart/Macro2/(),
+  package:macro/macro.dart/Macro3/(),
+  package:macro/macro.dart/Macro3/()],
  macrosAreApplied,
  macrosAreAvailable
 */
diff --git a/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart b/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart
index 026aeb3..5bc5073 100644
--- a/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart
+++ b/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart
@@ -7,6 +7,15 @@
   package:_fe_analyzer_shared/src/macros/api.dart,
   macro_lib.dart,
   main.dart],
+ macroClassIds=[
+  macro_lib.dart/Macro1,
+  macro_lib.dart/Macro2],
+ macroInstanceIds=[
+  macro_lib.dart/Macro1/(),
+  macro_lib.dart/Macro1/(),
+  macro_lib.dart/Macro1/(),
+  macro_lib.dart/Macro2/(),
+  macro_lib.dart/Macro2/()],
  macrosAreApplied,
  macrosAreAvailable
 */
diff --git a/pkg/front_end/test/macros/macro_test.dart b/pkg/front_end/test/macros/macro_test.dart
index 463b0cf..7a4dee8 100644
--- a/pkg/front_end/test/macros/macro_test.dart
+++ b/pkg/front_end/test/macros/macro_test.dart
@@ -3,15 +3,19 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io' show Directory, Platform;
-
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
-
 import 'package:_fe_analyzer_shared/src/testing/features.dart';
+import 'package:front_end/src/api_prototype/compiler_options.dart';
 import 'package:front_end/src/api_prototype/experimental_flags.dart';
+import 'package:front_end/src/fasta/builder/class_builder.dart';
+import 'package:front_end/src/fasta/builder/library_builder.dart';
+import 'package:front_end/src/fasta/builder/member_builder.dart';
 import 'package:front_end/src/fasta/kernel/macro.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart';
-import 'package:kernel/ast.dart';
+import 'package:kernel/ast.dart' hide Arguments;
 
 Future<void> main(List<String> args) async {
   enableMacros = true;
@@ -22,12 +26,23 @@
       args: args,
       createUriForFileName: createUriForFileName,
       onFailure: onFailure,
-      runTest: runTestFor(const MacroDataComputer(), [
-        new TestConfig(cfeMarker, 'cfe',
+      runTest: runTestFor(const MacroDataComputer(), [new MacroTestConfig()]));
+}
+
+class MacroTestConfig extends TestConfig {
+  MacroTestConfig()
+      : super(cfeMarker, 'cfe',
             explicitExperimentalFlags: {ExperimentalFlag.macros: true},
             packageConfigUri:
-                Platform.script.resolve('data/package_config.json'))
-      ]));
+                Platform.script.resolve('data/package_config.json'));
+
+  @override
+  TestMacroExecutor customizeCompilerOptions(
+      CompilerOptions options, TestData testData) {
+    TestMacroExecutor macroExecutor = new TestMacroExecutor();
+    options.macroExecutorProvider = () async => macroExecutor;
+    return macroExecutor;
+  }
 }
 
 class MacroDataComputer extends DataComputer<Features> {
@@ -102,15 +117,28 @@
         .loader.dataForTesting!.macroApplicationData;
   }
 
+  TestMacroExecutor get macroExecutor => testResultData.customData;
+
   LibraryMacroApplicationData? getLibraryMacroApplicationData(Library library) {
-    return macroApplicationData.libraryData[library];
+    for (MapEntry<LibraryBuilder, LibraryMacroApplicationData> entry
+        in macroApplicationData.libraryData.entries) {
+      if (entry.key.library == library) {
+        return entry.value;
+      }
+    }
+    return null;
   }
 
   ClassMacroApplicationData? getClassMacroApplicationData(Class cls) {
     LibraryMacroApplicationData? applicationData =
         getLibraryMacroApplicationData(cls.enclosingLibrary);
     if (applicationData != null) {
-      return applicationData.classData[cls];
+      for (MapEntry<ClassBuilder, ClassMacroApplicationData> entry
+          in applicationData.classData.entries) {
+        if (entry.key.cls == cls) {
+          return entry.value;
+        }
+      }
     }
     return null;
   }
@@ -121,20 +149,31 @@
 
   MacroApplications? getMemberMacroApplications(Member member) {
     Class? enclosingClass = member.enclosingClass;
+    Map<MemberBuilder, MacroApplications>? memberApplications;
     if (enclosingClass != null) {
-      return getClassMacroApplicationData(enclosingClass)
-          ?.memberApplications[member];
+      memberApplications =
+          getClassMacroApplicationData(enclosingClass)?.memberApplications;
     } else {
-      return getLibraryMacroApplicationData(member.enclosingLibrary)
-          ?.memberApplications[member];
+      memberApplications =
+          getLibraryMacroApplicationData(member.enclosingLibrary)
+              ?.memberApplications;
     }
+    if (memberApplications != null) {
+      for (MapEntry<MemberBuilder, MacroApplications> entry
+          in memberApplications.entries) {
+        if (entry.key.member == member) {
+          return entry.value;
+        }
+      }
+    }
+    return null;
   }
 
   void registerMacroApplications(
       Features features, MacroApplications? macroApplications) {
     if (macroApplications != null) {
       for (MacroApplication application in macroApplications.macros) {
-        String className = application.cls.name;
+        String className = application.classBuilder.name;
         String constructorName = application.constructorName == ''
             ? 'new'
             : application.constructorName;
@@ -168,6 +207,12 @@
               Tags.compilationSequence, strongComponentToString(component));
         }
       }
+      for (_MacroClassIdentifier id in macroExecutor.macroClasses) {
+        features.addElement(Tags.macroClassIds, id.toText());
+      }
+      for (_MacroInstanceIdentifier id in macroExecutor.macroInstances) {
+        features.addElement(Tags.macroInstanceIds, id.toText());
+      }
     }
     List<String>? macroClasses =
         macroDeclarationData.macroDeclarations[node.importUri];
@@ -179,6 +224,7 @@
     if (getLibraryMacroApplicationData(node) != null) {
       features.add(Tags.macrosAreApplied);
     }
+
     return features;
   }
 
@@ -189,3 +235,99 @@
     return features;
   }
 }
+
+class TestMacroExecutor implements MacroExecutor {
+  List<_MacroClassIdentifier> macroClasses = [];
+  List<_MacroInstanceIdentifier> macroInstances = [];
+
+  @override
+  Future<String> buildAugmentationLibrary(
+      Iterable<MacroExecutionResult> macroResults) {
+    // TODO: implement buildAugmentationLibrary
+    throw UnimplementedError();
+  }
+
+  @override
+  void close() {
+    // TODO: implement close
+  }
+
+  @override
+  Future<MacroExecutionResult> executeDeclarationsPhase(
+      MacroInstanceIdentifier macro,
+      Declaration declaration,
+      TypeResolver typeResolver,
+      ClassIntrospector classIntrospector) {
+    // TODO: implement executeDeclarationsPhase
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<MacroExecutionResult> executeDefinitionsPhase(
+      MacroInstanceIdentifier macro,
+      Declaration declaration,
+      TypeResolver typeResolver,
+      ClassIntrospector classIntrospector,
+      TypeDeclarationResolver typeDeclarationResolver) {
+    // TODO: implement executeDefinitionsPhase
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<MacroExecutionResult> executeTypesPhase(
+      MacroInstanceIdentifier macro, Declaration declaration) {
+    // TODO: implement executeTypesPhase
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<MacroInstanceIdentifier> instantiateMacro(
+      MacroClassIdentifier macroClass,
+      String constructor,
+      Arguments arguments) async {
+    _MacroInstanceIdentifier id = new _MacroInstanceIdentifier(
+        macroClass as _MacroClassIdentifier, constructor, arguments);
+    macroInstances.add(id);
+    return id;
+  }
+
+  @override
+  Future<MacroClassIdentifier> loadMacro(Uri library, String name) async {
+    _MacroClassIdentifier id = new _MacroClassIdentifier(library, name);
+    macroClasses.add(id);
+    return id;
+  }
+}
+
+class _MacroClassIdentifier implements MacroClassIdentifier {
+  final Uri uri;
+  final String className;
+
+  _MacroClassIdentifier(this.uri, this.className);
+
+  String toText() => '${importUriToString(uri)}/${className}';
+
+  @override
+  int get hashCode => uri.hashCode * 13 + className.hashCode * 17;
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return other is _MacroClassIdentifier &&
+        uri == other.uri &&
+        className == other.className;
+  }
+
+  @override
+  String toString() => 'MacroClassIdentifier($uri,$className)';
+}
+
+class _MacroInstanceIdentifier implements MacroInstanceIdentifier {
+  final _MacroClassIdentifier macroClass;
+  final String constructor;
+  final Arguments arguments;
+
+  _MacroInstanceIdentifier(this.macroClass, this.constructor, this.arguments);
+
+  String toText() => '${macroClass.toText()}/${constructor}()';
+}
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index dd3fd3e..8d0de2f 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -996,6 +996,7 @@
 proto
 protobuf
 protocol
+provider
 ps
 pulled
 pure
diff --git a/tools/VERSION b/tools/VERSION
index f35e17b..4f3fdd7 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 146
+PRERELEASE 147
 PRERELEASE_PATCH 0
\ No newline at end of file