Version 2.16.0-37.0.dev

Merge commit '7e6d8e085f959c3dfe92630e8e874366102b02ef' into 'dev'
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 9e0e011..40a1882 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -423,6 +423,7 @@
       computeCoreTypes();
       loader.buildClassHierarchy(myClasses, objectClassBuilder);
       loader.computeHierarchy();
+      loader.computeMacroDeclarations(myClasses);
       loader.computeShowHideElements();
       loader.installTypedefTearOffs();
       loader.performTopLevelInference(myClasses);
@@ -433,6 +434,7 @@
       loader.checkMixins(myClasses);
       loader.buildOutlineExpressions(
           loader.coreTypes, synthesizedFunctionNodes);
+      loader.computeMacroApplications();
       loader.checkTypes();
       loader.checkRedirectingFactories(myClasses);
       loader.checkMainMethods();
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro.dart
new file mode 100644
index 0000000..63dff78
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2021, 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:kernel/ast.dart';
+
+bool enableMacros = false;
+
+final Uri macroLibraryUri = Uri.parse('package:macro_builder/src/macro.dart');
+const String macroClassName = 'Macro';
+
+class MacroDeclarationData {
+  Class? macroClass;
+  Map<Library, List<Class>> macroDeclarations = {};
+  Set<Class> macroClasses = {};
+}
+
+class MacroApplicationData {
+  Map<Library, LibraryMacroApplicationData> libraryData = {};
+}
+
+class MacroApplications {
+  final List<Class> macros;
+
+  MacroApplications(this.macros);
+}
+
+class LibraryMacroApplicationData {
+  MacroApplications? libraryApplications;
+  Map<Class, ClassMacroApplicationData> classData = {};
+  Map<Typedef, MacroApplications> typedefApplications = {};
+  Map<Member, MacroApplications> memberApplications = {};
+}
+
+class ClassMacroApplicationData {
+  MacroApplications? classApplications;
+  Map<Member, MacroApplications> memberApplications = {};
+}
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 29c7861..d9a23a6 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -64,6 +64,7 @@
 import '../kernel/kernel_helper.dart'
     show SynthesizedFunctionNode, TypeDependency;
 import '../kernel/kernel_target.dart' show KernelTarget;
+import '../kernel/macro.dart';
 import '../kernel/transform_collections.dart' show CollectionTransformer;
 import '../kernel/transform_set_literals.dart' show SetLiteralTransformer;
 import '../kernel/type_builder_computer.dart' show TypeBuilderComputer;
@@ -199,6 +200,8 @@
 
   Uri? currentUriForCrashReporting;
 
+  Class? _macroClass;
+
   SourceLoader(this.fileSystem, this.includeComments, this.target)
       : dataForTesting =
             retainDataForTesting ? new SourceLoaderDataForTesting() : null;
@@ -828,7 +831,7 @@
     _typeInferenceEngine!.typeDependencies[member] = typeDependency;
   }
 
-  Future<Null> buildOutlines() async {
+  Future<void> buildOutlines() async {
     _ensureCoreLibrary();
     while (_unparsedLibraries.isNotEmpty) {
       LibraryBuilder library = _unparsedLibraries.removeFirst();
@@ -1168,6 +1171,128 @@
     ticker.logMs("Resolved $typeCount types");
   }
 
+  void computeMacroDeclarations(List<SourceClassBuilder> classes) {
+    if (!enableMacros) return;
+    LibraryBuilder? macroLibraryBuilder = lookupLibraryBuilder(macroLibraryUri);
+    if (macroLibraryBuilder == null) return;
+    Builder? macroClassBuilder =
+        macroLibraryBuilder.lookupLocalMember(macroClassName);
+    if (macroClassBuilder is! ClassBuilder) {
+      // TODO(johnniwinther): Report this when the actual macro builder package
+      // exists. It should at least be a warning.
+      return;
+    }
+
+    Class macroClass = _macroClass = macroClassBuilder.cls;
+    if (retainDataForTesting) {
+      dataForTesting!.macroDeclarationData.macroClass = macroClass;
+    }
+    for (SourceClassBuilder classBuilder in classes) {
+      Class cls = classBuilder.cls;
+      if (hierarchy.isSubtypeOf(cls, macroClass)) {
+        if (retainDataForTesting) {
+          (dataForTesting!.macroDeclarationData
+                  .macroDeclarations[cls.enclosingLibrary] ??= [])
+              .add(cls);
+        }
+      }
+    }
+  }
+
+  void computeMacroApplications() {
+    if (!enableMacros || _macroClass == null) return;
+    Class macroClass = _macroClass!;
+
+    Set<Class> macroClasses = {};
+    for (Library library in hierarchy.knownLibraries) {
+      for (Class cls in library.classes) {
+        // TODO(johnniwinther): Avoid calling `isSubtypeOf` for all classes. We
+        // should only check classes used in annotations to avoid marking too
+        // many classes as used.
+        if (hierarchy.isSubtypeOf(cls, macroClass)) {
+          macroClasses.add(cls);
+          if (retainDataForTesting) {
+            dataForTesting!.macroDeclarationData.macroClasses.add(cls);
+          }
+        }
+      }
+    }
+
+    Class? computeApplication(Expression expression) {
+      if (expression is ConstructorInvocation) {
+        Class cls = expression.target.enclosingClass;
+        if (macroClasses.contains(cls)) {
+          return cls;
+        }
+      }
+      return null;
+    }
+
+    MacroApplications? computeApplications(List<Expression> annotations) {
+      List<Class> macros = [];
+      for (Expression annotation in annotations) {
+        Class? cls = computeApplication(annotation);
+        if (cls != null) {
+          macros.add(cls);
+        }
+      }
+      return macros.isNotEmpty ? new MacroApplications(macros) : null;
+    }
+
+    for (LibraryBuilder libraryBuilder in libraryBuilders) {
+      if (libraryBuilder.loader != this) continue;
+      LibraryMacroApplicationData libraryMacroApplicationData =
+          new LibraryMacroApplicationData();
+      Library library = libraryBuilder.library;
+      libraryMacroApplicationData.libraryApplications =
+          computeApplications(library.annotations);
+      for (Class cls in library.classes) {
+        ClassMacroApplicationData classMacroApplicationData =
+            new ClassMacroApplicationData();
+        classMacroApplicationData.classApplications =
+            computeApplications(cls.annotations);
+        for (Member member in cls.members) {
+          MacroApplications? macroApplications =
+              computeApplications(member.annotations);
+          if (macroApplications != null) {
+            classMacroApplicationData.memberApplications[member] =
+                macroApplications;
+          }
+        }
+        if (classMacroApplicationData.classApplications != null ||
+            classMacroApplicationData.memberApplications.isNotEmpty) {
+          libraryMacroApplicationData.classData[cls] =
+              classMacroApplicationData;
+        }
+      }
+      for (Member member in library.members) {
+        MacroApplications? macroApplications =
+            computeApplications(member.annotations);
+        if (macroApplications != null) {
+          libraryMacroApplicationData.memberApplications[member] =
+              macroApplications;
+        }
+      }
+      for (Typedef typedef in library.typedefs) {
+        MacroApplications? macroApplications =
+            computeApplications(typedef.annotations);
+        if (macroApplications != null) {
+          libraryMacroApplicationData.typedefApplications[typedef] =
+              macroApplications;
+        }
+      }
+      if (libraryMacroApplicationData.libraryApplications != null ||
+          libraryMacroApplicationData.classData.isNotEmpty ||
+          libraryMacroApplicationData.typedefApplications.isNotEmpty ||
+          libraryMacroApplicationData.memberApplications.isNotEmpty) {
+        if (retainDataForTesting) {
+          dataForTesting!.macroApplicationData.libraryData[library] =
+              libraryMacroApplicationData;
+        }
+      }
+    }
+  }
+
   void finishDeferredLoadTearoffs() {
     int count = 0;
     for (LibraryBuilder library in libraryBuilders) {
@@ -2269,4 +2394,8 @@
   TreeNode toOriginal(TreeNode alias) {
     return _aliasMap[alias] ?? alias;
   }
+
+  final MacroDeclarationData macroDeclarationData = new MacroDeclarationData();
+
+  final MacroApplicationData macroApplicationData = new MacroApplicationData();
 }
diff --git a/pkg/front_end/test/macros/macro_test.dart b/pkg/front_end/test/macros/macro_test.dart
index 98f0000..bcc7294 100644
--- a/pkg/front_end/test/macros/macro_test.dart
+++ b/pkg/front_end/test/macros/macro_test.dart
@@ -8,12 +8,13 @@
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 
 import 'package:_fe_analyzer_shared/src/testing/features.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/class_hierarchy.dart';
-import 'package:kernel/core_types.dart';
 
 Future<void> main(List<String> args) async {
+  enableMacros = true;
+
   Directory dataDir =
       new Directory.fromUri(Platform.script.resolve('data/tests'));
   await runTests<Features>(dataDir,
@@ -27,129 +28,6 @@
       ]));
 }
 
-final Uri macroLibraryUri = Uri.parse('package:macro_builder/src/macro.dart');
-const String macroClassName = 'Macro';
-
-class MacroDeclarationData {
-  Class? macroClass;
-  Map<Library, List<Class>> macroDeclarations = {};
-  Set<Class> macroClasses = {};
-}
-
-MacroDeclarationData computeMacroDeclarationData(
-    Component component, ClassHierarchy classHierarchy) {
-  MacroDeclarationData data = new MacroDeclarationData();
-  Class? macroClass;
-  outer:
-  for (Library library in component.libraries) {
-    if (library.importUri == macroLibraryUri) {
-      for (Class cls in library.classes) {
-        if (cls.name == macroClassName) {
-          macroClass = cls;
-          break outer;
-        }
-      }
-    }
-  }
-  if (macroClass != null) {
-    data.macroClass = macroClass;
-    for (Library library in component.libraries) {
-      for (Class cls in library.classes) {
-        if (classHierarchy.isSubtypeOf(cls, macroClass)) {
-          (data.macroDeclarations[library] ??= []).add(cls);
-          data.macroClasses.add(cls);
-        }
-      }
-    }
-  }
-  return data;
-}
-
-class MacroApplications {
-  List<Class> macros = [];
-}
-
-class LibraryMacroApplicationData {
-  MacroApplications? libraryApplications;
-  Map<Class, ClassMacroApplicationData> classData = {};
-  Map<Typedef, MacroApplications> typedefApplications = {};
-  Map<Member, MacroApplications> memberApplications = {};
-}
-
-class ClassMacroApplicationData {
-  MacroApplications? classApplications;
-  Map<Member, MacroApplications> memberApplications = {};
-}
-
-MacroApplications? computeMacroApplications(
-    List<Expression> annotations, MacroDeclarationData macroDeclarationData) {
-  MacroApplications applications = new MacroApplications();
-  bool hasApplications = false;
-  for (Expression annotation in annotations) {
-    if (annotation is ConstantExpression) {
-      Constant constant = annotation.constant;
-      if (constant is InstanceConstant) {
-        if (macroDeclarationData.macroClasses.contains(constant.classNode)) {
-          applications.macros.add(constant.classNode);
-          hasApplications = true;
-        }
-      }
-    }
-  }
-  return hasApplications ? applications : null;
-}
-
-ClassMacroApplicationData? computeClassMacroApplicationData(
-    Class cls, MacroDeclarationData macroDeclarationData) {
-  ClassMacroApplicationData data = new ClassMacroApplicationData();
-  data.classApplications =
-      computeMacroApplications(cls.annotations, macroDeclarationData);
-  for (Member member in cls.members) {
-    MacroApplications? macroApplications =
-        computeMacroApplications(member.annotations, macroDeclarationData);
-    if (macroApplications != null) {
-      data.memberApplications[member] = macroApplications;
-    }
-  }
-  return data.classApplications != null || data.memberApplications.isNotEmpty
-      ? data
-      : null;
-}
-
-LibraryMacroApplicationData? computeLibraryMacroApplicationData(
-    Library library, MacroDeclarationData macroDeclarationData) {
-  LibraryMacroApplicationData data = new LibraryMacroApplicationData();
-  data.libraryApplications =
-      computeMacroApplications(library.annotations, macroDeclarationData);
-  for (Typedef typedef in library.typedefs) {
-    MacroApplications? macroApplications =
-        computeMacroApplications(typedef.annotations, macroDeclarationData);
-    if (macroApplications != null) {
-      data.typedefApplications[typedef] = macroApplications;
-    }
-  }
-  for (Member member in library.members) {
-    MacroApplications? macroApplications =
-        computeMacroApplications(member.annotations, macroDeclarationData);
-    if (macroApplications != null) {
-      data.memberApplications[member] = macroApplications;
-    }
-  }
-  for (Class cls in library.classes) {
-    ClassMacroApplicationData? classMacroApplicationData =
-        computeClassMacroApplicationData(cls, macroDeclarationData);
-    if (classMacroApplicationData != null) {
-      data.classData[cls] = classMacroApplicationData;
-    }
-  }
-  return data.libraryApplications != null ||
-          data.classData.isNotEmpty ||
-          data.memberApplications.isNotEmpty ||
-          data.typedefApplications.isNotEmpty
-      ? data
-      : null;
-}
-
 class MacroDataComputer extends DataComputer<Features> {
   const MacroDataComputer();
 
@@ -197,22 +75,20 @@
 }
 
 class MacroDataExtractor extends CfeDataExtractor<Features> {
-  late final ClassHierarchy classHierarchy;
   late final MacroDeclarationData macroDeclarationData;
+  late final MacroApplicationData macroApplicationData;
 
   MacroDataExtractor(InternalCompilerResult compilerResult,
       Map<Id, ActualData<Features>> actualMap)
       : super(compilerResult, actualMap) {
-    // TODO(johnniwinther): Why isn't `_UserTag` available in the
-    // [ClassHierarchy] provided by the [compilerResult]?
-    classHierarchy = new ClassHierarchy(
-        compilerResult.component!, new CoreTypes(compilerResult.component!));
-    macroDeclarationData =
-        computeMacroDeclarationData(compilerResult.component!, classHierarchy);
+    macroDeclarationData = compilerResult
+        .kernelTargetForTesting!.loader.dataForTesting!.macroDeclarationData;
+    macroApplicationData = compilerResult
+        .kernelTargetForTesting!.loader.dataForTesting!.macroApplicationData;
   }
 
   LibraryMacroApplicationData? getLibraryMacroApplicationData(Library library) {
-    return computeLibraryMacroApplicationData(library, macroDeclarationData);
+    return macroApplicationData.libraryData[library];
   }
 
   MacroApplications? getLibraryMacroApplications(Library library) {
@@ -221,8 +97,7 @@
 
   ClassMacroApplicationData? getClassMacroApplicationData(Class cls) {
     LibraryMacroApplicationData? applicationData =
-        computeLibraryMacroApplicationData(
-            cls.enclosingLibrary, macroDeclarationData);
+        getLibraryMacroApplicationData(cls.enclosingLibrary);
     if (applicationData != null) {
       return applicationData.classData[cls];
     }
diff --git a/tools/VERSION b/tools/VERSION
index fdf498a..fb38f54 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 36
+PRERELEASE 37
 PRERELEASE_PATCH 0
\ No newline at end of file