Version 2.16.0-41.0.dev

Merge commit '02cd6a9a94cd10849cb44951afaae444ea4c3f13' into 'dev'
diff --git a/DEPS b/DEPS
index 9dab5da..a2c3532 100644
--- a/DEPS
+++ b/DEPS
@@ -44,9 +44,9 @@
   # co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
   # hashes. It requires access to the dart-build-access group, which EngProd
   # has.
-  "co19_rev": "39c5bbc03bf5c5c0a3f9341abe811871eababfaf",
+  "co19_rev": "4ef349830b971c22d8ddb2970c4ba9002806fd85",
   # This line prevents conflicts when both packages are rolled simultaneously.
-  "co19_2_rev": "86f01ade433fbb4eec3a7f93f5e1e4fed9a84fb3",
+  "co19_2_rev": "995745937abffe9fc3a6441f9f0db27b2d706e4c",
 
   # The internal benchmarks to use. See go/dart-benchmarks-internal
   "benchmarks_internal_rev": "076df10d9b77af337f2d8029725787155eb1cd52",
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index 0bfffd5..930f1b0 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -400,7 +400,7 @@
         // from ClassHierarchyBuilder.
         TypeDeclarationBuilder? unaliasedDeclaration = this.declaration;
         // The following code assumes that the declaration is a TypeAliasBuilder
-        // that through a chain of other TypeAliasBuilders (possibly, the chian
+        // that through a chain of other TypeAliasBuilders (possibly, the chain
         // length is 0) references a ClassBuilder of the Null class.  Otherwise,
         // it won't produce the NullType on the output.
         while (unaliasedDeclaration is TypeAliasBuilder) {
@@ -421,7 +421,7 @@
         // class from ClassHierarchyBuilder.
         TypeDeclarationBuilder? unaliasedDeclaration = this.declaration;
         // The following code assumes that the declaration is a TypeAliasBuilder
-        // that through a chain of other TypeAliasBuilders (possibly, the chian
+        // that through a chain of other TypeAliasBuilders (possibly, the chain
         // length is 0) references a ClassBuilder of the FutureOr class.
         // Otherwise, it won't produce the FutureOrType on the output.
         while (unaliasedDeclaration is TypeAliasBuilder) {
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 61bdb2e..23f2625 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -9,18 +9,6 @@
 import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
     show ScannerConfiguration;
 
-import 'package:front_end/src/api_prototype/experimental_flags.dart';
-
-import 'package:front_end/src/api_prototype/lowering_predicates.dart'
-    show isExtensionThisName;
-
-import 'package:front_end/src/base/nnbd_mode.dart';
-
-import 'package:front_end/src/fasta/builder/member_builder.dart'
-    show MemberBuilder;
-
-import 'package:front_end/src/fasta/fasta_codes.dart';
-import 'package:front_end/src/fasta/source/source_loader.dart';
 import 'package:kernel/binary/ast_from_binary.dart'
     show
         BinaryBuilderWithMetadata,
@@ -69,13 +57,19 @@
 
 import 'package:package_config/package_config.dart' show Package, PackageConfig;
 
+import '../api_prototype/experimental_flags.dart';
+
 import '../api_prototype/file_system.dart' show FileSystem, FileSystemEntity;
 
 import '../api_prototype/incremental_kernel_generator.dart'
     show IncrementalKernelGenerator, isLegalIdentifier;
 
+import '../api_prototype/lowering_predicates.dart' show isExtensionThisName;
+
 import '../api_prototype/memory_file_system.dart' show MemoryFileSystem;
 
+import '../base/nnbd_mode.dart';
+
 import 'builder/builder.dart' show Builder;
 
 import 'builder/class_builder.dart' show ClassBuilder;
@@ -86,6 +80,8 @@
 
 import 'builder/library_builder.dart' show LibraryBuilder;
 
+import 'builder/member_builder.dart' show MemberBuilder;
+
 import 'builder/name_iterator.dart' show NameIterator;
 
 import 'builder/type_builder.dart' show TypeBuilder;
@@ -107,6 +103,8 @@
 
 import 'export.dart' show Export;
 
+import 'fasta_codes.dart';
+
 import 'import.dart' show Import;
 
 import 'incremental_serializer.dart' show IncrementalSerializer;
@@ -134,6 +132,8 @@
 import 'source/source_library_builder.dart'
     show ImplicitLanguageVersion, SourceLibraryBuilder;
 
+import 'source/source_loader.dart';
+
 import 'ticker.dart' show Ticker;
 
 import 'uri_translator.dart' show UriTranslator;
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 40a1882..2950121 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -402,7 +402,6 @@
     if (loader.first == null) return null;
     return withCrashReporting<Component?>(() async {
       await loader.buildOutlines();
-      loader.createTypeInferenceEngine();
       loader.coreLibrary.becomeCoreLibrary();
       loader.resolveParts();
       loader.computeLibraryScopes();
@@ -411,32 +410,33 @@
       loader.computeVariances();
       loader.computeDefaultTypes(
           dynamicType, nullType, bottomType, objectClassBuilder);
-      List<SourceClassBuilder> myClasses =
+      List<SourceClassBuilder> sourceClassBuilders =
           loader.checkSemantics(objectClassBuilder);
+      loader.computeMacroDeclarations(sourceClassBuilders);
       loader.finishTypeVariables(objectClassBuilder, dynamicType);
+      loader.createTypeInferenceEngine();
       loader.buildComponent();
       installDefaultSupertypes();
-      installSyntheticConstructors(myClasses);
+      installSyntheticConstructors(sourceClassBuilders);
       loader.resolveConstructors();
       component =
           link(new List<Library>.from(loader.libraries), nameRoot: nameRoot);
       computeCoreTypes();
-      loader.buildClassHierarchy(myClasses, objectClassBuilder);
+      loader.buildClassHierarchy(sourceClassBuilders, objectClassBuilder);
       loader.computeHierarchy();
-      loader.computeMacroDeclarations(myClasses);
       loader.computeShowHideElements();
       loader.installTypedefTearOffs();
-      loader.performTopLevelInference(myClasses);
-      loader.checkSupertypes(myClasses);
-      loader.checkOverrides(myClasses);
-      loader.checkAbstractMembers(myClasses);
-      loader.addNoSuchMethodForwarders(myClasses);
-      loader.checkMixins(myClasses);
+      loader.performTopLevelInference(sourceClassBuilders);
+      loader.checkSupertypes(sourceClassBuilders);
+      loader.checkOverrides(sourceClassBuilders);
+      loader.checkAbstractMembers(sourceClassBuilders);
+      loader.addNoSuchMethodForwarders(sourceClassBuilders);
+      loader.checkMixins(sourceClassBuilders);
       loader.buildOutlineExpressions(
           loader.coreTypes, synthesizedFunctionNodes);
       loader.computeMacroApplications();
       loader.checkTypes();
-      loader.checkRedirectingFactories(myClasses);
+      loader.checkRedirectingFactories(sourceClassBuilders);
       loader.checkMainMethods();
       installAllComponentProblems(loader.allComponentProblems);
       loader.allComponentProblems.clear();
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro.dart
index 63dff78..afa9dca 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -10,9 +10,9 @@
 const String macroClassName = 'Macro';
 
 class MacroDeclarationData {
-  Class? macroClass;
-  Map<Library, List<Class>> macroDeclarations = {};
-  Set<Class> macroClasses = {};
+  bool macrosAreAvailable = false;
+  Map<Uri, List<String>> macroDeclarations = {};
+  List<List<Uri>>? compilationSequence;
 }
 
 class MacroApplicationData {
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 d9a23a6..aa989c5 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -27,6 +27,7 @@
 import 'package:kernel/core_types.dart' show CoreTypes;
 import 'package:kernel/reference_from_index.dart' show ReferenceFromIndex;
 import 'package:kernel/type_environment.dart';
+import 'package:kernel/util/graph.dart';
 import 'package:package_config/package_config.dart' as package_config;
 
 import '../../api_prototype/experimental_flags.dart';
@@ -34,7 +35,9 @@
 import '../../base/common.dart';
 import '../../base/instrumentation.dart' show Instrumentation;
 import '../../base/nnbd_mode.dart';
+import '../dill/dill_class_builder.dart';
 import '../dill/dill_library_builder.dart';
+import '../builder_graph.dart';
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
 import '../builder/constructor_builder.dart';
@@ -200,7 +203,7 @@
 
   Uri? currentUriForCrashReporting;
 
-  Class? _macroClass;
+  ClassBuilder? _macroClassBuilder;
 
   SourceLoader(this.fileSystem, this.includeComments, this.target)
       : dataForTesting =
@@ -1171,10 +1174,12 @@
     ticker.logMs("Resolved $typeCount types");
   }
 
-  void computeMacroDeclarations(List<SourceClassBuilder> classes) {
+  void computeMacroDeclarations(List<SourceClassBuilder> sourceClassBuilders) {
     if (!enableMacros) return;
+
     LibraryBuilder? macroLibraryBuilder = lookupLibraryBuilder(macroLibraryUri);
     if (macroLibraryBuilder == null) return;
+
     Builder? macroClassBuilder =
         macroLibraryBuilder.lookupLocalMember(macroClassName);
     if (macroClassBuilder is! ClassBuilder) {
@@ -1183,45 +1188,106 @@
       return;
     }
 
-    Class macroClass = _macroClass = macroClassBuilder.cls;
+    _macroClassBuilder = macroClassBuilder;
     if (retainDataForTesting) {
-      dataForTesting!.macroDeclarationData.macroClass = macroClass;
+      dataForTesting!.macroDeclarationData.macrosAreAvailable = true;
     }
-    for (SourceClassBuilder classBuilder in classes) {
-      Class cls = classBuilder.cls;
-      if (hierarchy.isSubtypeOf(cls, macroClass)) {
-        if (retainDataForTesting) {
-          (dataForTesting!.macroDeclarationData
-                  .macroDeclarations[cls.enclosingLibrary] ??= [])
-              .add(cls);
+
+    Set<ClassBuilder> macroClasses = {macroClassBuilder};
+    Set<Uri> macroLibraries = {macroLibraryBuilder.importUri};
+
+    bool isMacroClass(TypeDeclarationBuilder? typeDeclarationBuilder) {
+      if (typeDeclarationBuilder == null) return false;
+      while (typeDeclarationBuilder is TypeAliasBuilder) {
+        typeDeclarationBuilder =
+            typeDeclarationBuilder.unaliasDeclaration(null);
+      }
+      if (typeDeclarationBuilder is ClassBuilder) {
+        if (macroClasses.contains(typeDeclarationBuilder)) return true;
+        if (typeDeclarationBuilder is DillClassBuilder) {
+          // TODO(johnniwinther): Recognize macro classes from dill.
         }
       }
+      return false;
+    }
+
+    for (SourceClassBuilder sourceClassBuilder in sourceClassBuilders) {
+      bool isMacro =
+          isMacroClass(sourceClassBuilder.supertypeBuilder?.declaration);
+      if (!isMacro && sourceClassBuilder.interfaceBuilders != null) {
+        for (TypeBuilder interfaceBuilder
+            in sourceClassBuilder.interfaceBuilders!) {
+          if (isMacroClass(interfaceBuilder.declaration)) {
+            isMacro = true;
+            break;
+          }
+        }
+      }
+      isMacro = isMacro ||
+          isMacroClass(sourceClassBuilder.mixedInTypeBuilder?.declaration);
+      if (isMacro) {
+        macroClasses.add(sourceClassBuilder);
+        macroLibraries.add(sourceClassBuilder.library.importUri);
+        if (retainDataForTesting) {
+          (dataForTesting!.macroDeclarationData.macroDeclarations[
+                  sourceClassBuilder.library.importUri] ??= [])
+              .add(sourceClassBuilder.name);
+        }
+      }
+    }
+
+    bool isDillLibrary(Uri uri) => _builders[uri]?.loader != this;
+
+    List<List<Uri>> computeCompilationSequence(Graph<Uri> libraryGraph,
+        {required bool Function(Uri) filter}) {
+      List<List<Uri>> stronglyConnectedComponents =
+          computeStrongComponents(libraryGraph);
+
+      Graph<List<Uri>> strongGraph =
+          new StrongComponentGraph(libraryGraph, stronglyConnectedComponents);
+      List<List<List<Uri>>> componentLayers = [];
+      topologicalSort(strongGraph, layers: componentLayers);
+      List<List<Uri>> layeredComponents = [];
+      List<Uri> currentLayer = [];
+      for (List<List<Uri>> layer in componentLayers) {
+        bool declaresMacro = false;
+        for (List<Uri> component in layer) {
+          for (Uri uri in component) {
+            if (filter(uri)) continue;
+            if (macroLibraries.contains(uri)) {
+              declaresMacro = true;
+            }
+            currentLayer.add(uri);
+          }
+        }
+        if (declaresMacro) {
+          layeredComponents.add(currentLayer);
+          currentLayer = [];
+        }
+      }
+      if (currentLayer.isNotEmpty) {
+        layeredComponents.add(currentLayer);
+      }
+      return layeredComponents;
+    }
+
+    List<List<Uri>> compilationSteps = computeCompilationSequence(
+        new BuilderGraph(_builders),
+        filter: isDillLibrary);
+    if (retainDataForTesting) {
+      dataForTesting!.macroDeclarationData.compilationSequence =
+          compilationSteps;
     }
   }
 
   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);
-          }
-        }
-      }
-    }
+    if (!enableMacros || _macroClassBuilder == null) return;
+    Class macroClass = _macroClassBuilder!.cls;
 
     Class? computeApplication(Expression expression) {
       if (expression is ConstructorInvocation) {
         Class cls = expression.target.enclosingClass;
-        if (macroClasses.contains(cls)) {
+        if (hierarchy.isSubtypeOf(cls, macroClass)) {
           return cls;
         }
       }
diff --git a/pkg/front_end/test/macros/data/tests/declare_macro.dart b/pkg/front_end/test/macros/data/tests/declare_macro.dart
index 58edc63..5d396f7 100644
--- a/pkg/front_end/test/macros/data/tests/declare_macro.dart
+++ b/pkg/front_end/test/macros/data/tests/declare_macro.dart
@@ -3,6 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*library: 
+ compilationSequence=[
+  package:macro_builder/src/macro.dart,
+  main.dart|package:macro_builder/macro_builder.dart],
  declaredMacros=[MyMacro],
  macrosAreAvailable
 */
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib.dart
new file mode 100644
index 0000000..f4e6484
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib.dart
@@ -0,0 +1,18 @@
+// 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.
+
+/*library: 
+ macrosAreApplied,
+ macrosAreAvailable
+*/
+
+import 'macro_lib.dart';
+import 'apply_lib_dep.dart';
+
+@Macro1()
+/*class: Class:
+ appliedMacros=[Macro1],
+ macrosAreApplied
+*/
+class Class extends Super {}
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib_dep.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib_dep.dart
new file mode 100644
index 0000000..018b909
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib_dep.dart
@@ -0,0 +1,7 @@
+// 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.
+
+/*library: macrosAreAvailable*/
+
+class Super {}
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib.dart
new file mode 100644
index 0000000..149d512
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib.dart
@@ -0,0 +1,15 @@
+// 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.
+
+/*library: 
+ declaredMacros=[Macro1],
+ macrosAreAvailable
+*/
+
+import 'package:macro_builder/macro_builder.dart';
+import 'macro_lib_dep.dart';
+
+class Macro1 extends MacroBase implements Macro {
+  const Macro1();
+}
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib_dep.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib_dep.dart
new file mode 100644
index 0000000..13c27f8
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib_dep.dart
@@ -0,0 +1,9 @@
+// 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.
+
+/*library: macrosAreAvailable*/
+
+class MacroBase {
+  const MacroBase();
+}
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
new file mode 100644
index 0000000..868f08d
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart
@@ -0,0 +1,19 @@
+// 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.
+
+/*library: 
+ compilationSequence=[
+  apply_lib_dep.dart|macro_lib_dep.dart|main_lib_dep.dart|package:macro_builder/src/macro.dart,
+  macro_lib.dart|package:macro_builder/macro_builder.dart,
+  apply_lib.dart|main.dart],
+ macrosAreAvailable
+*/
+
+import 'apply_lib.dart';
+import 'main_lib_dep.dart';
+
+void main() {
+  new Class();
+  method();
+}
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/main_lib_dep.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/main_lib_dep.dart
new file mode 100644
index 0000000..684c9d7
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/main_lib_dep.dart
@@ -0,0 +1,7 @@
+// 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.
+
+/*library: macrosAreAvailable*/
+
+void method() {}
diff --git a/pkg/front_end/test/macros/data/tests/direct_import.dart b/pkg/front_end/test/macros/data/tests/direct_import.dart
index b2f6177..f3484cd 100644
--- a/pkg/front_end/test/macros/data/tests/direct_import.dart
+++ b/pkg/front_end/test/macros/data/tests/direct_import.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.
 
-/*library: macrosAreAvailable*/
+/*library: 
+ compilationSequence=[
+  package:macro_builder/src/macro.dart,
+  main.dart],
+ macrosAreAvailable
+*/
 
 // ignore: unused_import
 import 'package:macro_builder/src/macro.dart';
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_builder.dart b/pkg/front_end/test/macros/data/tests/import_macro_builder.dart
index 14e5966c..dca3012 100644
--- a/pkg/front_end/test/macros/data/tests/import_macro_builder.dart
+++ b/pkg/front_end/test/macros/data/tests/import_macro_builder.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.
 
-/*library: macrosAreAvailable*/
+/*library: 
+ compilationSequence=[
+  package:macro_builder/src/macro.dart,
+  main.dart|package:macro_builder/macro_builder.dart],
+ macrosAreAvailable
+*/
 
 // ignore: unused_import
 import 'package:macro_builder/macro_builder.dart';
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_package.dart b/pkg/front_end/test/macros/data/tests/import_macro_package.dart
index 5e69df3..1fabb48 100644
--- a/pkg/front_end/test/macros/data/tests/import_macro_package.dart
+++ b/pkg/front_end/test/macros/data/tests/import_macro_package.dart
@@ -2,7 +2,13 @@
 // 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.
 
-/*library: macrosAreAvailable*/
+/*library: 
+ compilationSequence=[
+  package:macro_builder/src/macro.dart,
+  package:macro/macro.dart|package:macro_builder/macro_builder.dart,
+  main.dart],
+ macrosAreAvailable
+*/
 
 // ignore: unused_import
 import 'package:macro/macro.dart';
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart b/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart
index 625315b..5b109f4 100644
--- a/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart
+++ b/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart
@@ -2,7 +2,13 @@
 // 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.
 
-/*library: macrosAreAvailable*/
+/*library: 
+ compilationSequence=[
+  package:macro_builder/src/macro.dart,
+  macro_lib.dart|package:macro_builder/macro_builder.dart,
+  main.dart],
+ macrosAreAvailable
+*/
 
 // ignore: unused_import
 import 'macro_lib.dart';
diff --git a/pkg/front_end/test/macros/data/tests/macro_declarations.dart b/pkg/front_end/test/macros/data/tests/macro_declarations.dart
new file mode 100644
index 0000000..872dad84
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/macro_declarations.dart
@@ -0,0 +1,37 @@
+// 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.
+
+/*library: 
+ compilationSequence=[
+  package:macro_builder/src/macro.dart,
+  main.dart|package:macro_builder/macro_builder.dart],
+ declaredMacros=[
+  Extends,
+  ExtendsAlias,
+  Implements,
+  ImplementsAlias,
+  Mixin,
+  MixinAlias,
+  _Mixin&Object&Macro,
+  _MixinAlias&Object&Alias],
+ macrosAreAvailable
+*/
+
+import 'package:macro_builder/macro_builder.dart';
+
+class Extends extends Macro {}
+
+class Implements implements Macro {}
+
+class Mixin with Macro {}
+
+typedef Alias = Macro;
+
+class ExtendsAlias extends Alias {}
+
+class ImplementsAlias implements Alias {}
+
+class MixinAlias with Alias {}
+
+void main() {}
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib1.dart b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib1.dart
new file mode 100644
index 0000000..a05f387
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib1.dart
@@ -0,0 +1,14 @@
+// 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.
+
+/*library: 
+ declaredMacros=[Macro1],
+ macrosAreAvailable
+*/
+
+import 'package:macro_builder/macro_builder.dart';
+
+class Macro1 implements Macro {
+  const Macro1();
+}
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2a.dart b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2a.dart
new file mode 100644
index 0000000..967801f
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2a.dart
@@ -0,0 +1,14 @@
+// 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.
+
+/*library: 
+ declaredMacros=[Macro2a],
+ macrosAreAvailable
+*/
+
+import 'package:macro_builder/macro_builder.dart';
+
+class Macro2a implements Macro {
+  const Macro2a();
+}
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2b.dart b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2b.dart
new file mode 100644
index 0000000..b9bc7d2
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2b.dart
@@ -0,0 +1,21 @@
+// 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.
+
+/*library: 
+ declaredMacros=[Macro2b],
+ macrosAreApplied,
+ macrosAreAvailable
+*/
+
+import 'package:macro_builder/macro_builder.dart';
+import 'macro_lib2a.dart';
+
+@Macro2a()
+/*class: Macro2b:
+ appliedMacros=[Macro2a],
+ macrosAreApplied
+*/
+class Macro2b implements Macro {
+  const Macro2b();
+}
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
new file mode 100644
index 0000000..9dee592
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
@@ -0,0 +1,26 @@
+// 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.
+
+/*library: 
+ compilationSequence=[
+  package:macro_builder/src/macro.dart,
+  macro_lib1.dart|macro_lib2a.dart|package:macro_builder/macro_builder.dart,
+  macro_lib2b.dart,
+  main.dart],
+ macrosAreApplied,
+ macrosAreAvailable
+*/
+
+import 'macro_lib1.dart';
+import 'macro_lib2a.dart';
+import 'macro_lib2b.dart';
+
+@Macro1()
+@Macro2a()
+@Macro2b()
+/*member: main:appliedMacros=[
+  Macro1,
+  Macro2a,
+  Macro2b]*/
+void main() {}
diff --git a/pkg/front_end/test/macros/data/tests/no_import.dart b/pkg/front_end/test/macros/data/tests/no_import.dart
index e5c2fad..80fd055 100644
--- a/pkg/front_end/test/macros/data/tests/no_import.dart
+++ b/pkg/front_end/test/macros/data/tests/no_import.dart
@@ -2,4 +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.
 
+/*library: */
+
 void main() {}
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 09c2b3b..74f18ff 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
@@ -4,6 +4,10 @@
 
 /*library: 
  appliedMacros=[Macro3],
+ compilationSequence=[
+  package:macro_builder/src/macro.dart,
+  package:macro/macro.dart|package:macro_builder/macro_builder.dart,
+  main.dart],
  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 f5a3e60..930eb5c 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
@@ -3,6 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*library: 
+ compilationSequence=[
+  package:macro_builder/src/macro.dart,
+  macro_lib.dart|package:macro_builder/macro_builder.dart,
+  main.dart],
  macrosAreApplied,
  macrosAreAvailable
 */
diff --git a/pkg/front_end/test/macros/macro_test.dart b/pkg/front_end/test/macros/macro_test.dart
index bcc7294..82fe62d 100644
--- a/pkg/front_end/test/macros/macro_test.dart
+++ b/pkg/front_end/test/macros/macro_test.dart
@@ -70,10 +70,29 @@
 class Tags {
   static const String macrosAreAvailable = 'macrosAreAvailable';
   static const String macrosAreApplied = 'macrosAreApplied';
+  static const String compilationSequence = 'compilationSequence';
   static const String declaredMacros = 'declaredMacros';
   static const String appliedMacros = 'appliedMacros';
 }
 
+String importUriToString(Uri importUri) {
+  if (importUri.scheme == 'package') {
+    return importUri.toString();
+  } else if (importUri.scheme == 'dart') {
+    return importUri.toString();
+  } else {
+    return importUri.pathSegments.last;
+  }
+}
+
+String libraryToString(Library library) => importUriToString(library.importUri);
+
+String strongComponentToString(Iterable<Uri> uris) {
+  List<String> list = uris.map(importUriToString).toList();
+  list.sort();
+  return list.join('|');
+}
+
 class MacroDataExtractor extends CfeDataExtractor<Features> {
   late final MacroDeclarationData macroDeclarationData;
   late final MacroApplicationData macroApplicationData;
@@ -129,25 +148,6 @@
   }
 
   @override
-  Features computeLibraryValue(Id id, Library node) {
-    Features features = new Features();
-    if (macroDeclarationData.macroClass != null) {
-      features.add(Tags.macrosAreAvailable);
-    }
-    List<Class>? macroClasses = macroDeclarationData.macroDeclarations[node];
-    if (macroClasses != null) {
-      for (Class cls in macroClasses) {
-        features.addElement(Tags.declaredMacros, cls.name);
-      }
-    }
-    if (getLibraryMacroApplicationData(node) != null) {
-      features.add(Tags.macrosAreApplied);
-    }
-    registerMacroApplications(features, getLibraryMacroApplications(node));
-    return features;
-  }
-
-  @override
   Features computeClassValue(Id id, Class node) {
     Features features = new Features();
     if (getClassMacroApplicationData(node) != null) {
@@ -158,6 +158,35 @@
   }
 
   @override
+  Features computeLibraryValue(Id id, Library node) {
+    Features features = new Features();
+    if (macroDeclarationData.macrosAreAvailable) {
+      features.add(Tags.macrosAreAvailable);
+    }
+    if (node == compilerResult.component!.mainMethod!.enclosingLibrary) {
+      if (macroDeclarationData.compilationSequence != null) {
+        features.markAsUnsorted(Tags.compilationSequence);
+        for (List<Uri> component in macroDeclarationData.compilationSequence!) {
+          features.addElement(
+              Tags.compilationSequence, strongComponentToString(component));
+        }
+      }
+    }
+    List<String>? macroClasses =
+        macroDeclarationData.macroDeclarations[node.importUri];
+    if (macroClasses != null) {
+      for (String clsName in macroClasses) {
+        features.addElement(Tags.declaredMacros, clsName);
+      }
+    }
+    if (getLibraryMacroApplicationData(node) != null) {
+      features.add(Tags.macrosAreApplied);
+    }
+    registerMacroApplications(features, getLibraryMacroApplications(node));
+    return features;
+  }
+
+  @override
   Features computeMemberValue(Id id, Member node) {
     Features features = new Features();
     registerMacroApplications(features, getMemberMacroApplications(node));
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index fcf3a64..0f0d0b8 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -679,6 +679,8 @@
 launched
 launcher
 layer
+layered
+layers
 layout
 lc
 ld
@@ -1215,6 +1217,7 @@
 subexpression
 subexpression's
 subexpressions
+subgraph
 subnode
 subnodes
 subscription
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index cad9efd..4a5faff 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -436,7 +436,6 @@
 checking
 checkpoints
 checks
-chian
 child
 children
 choice
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 86bfe96..bb52fe8 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -598,10 +598,13 @@
 la
 launch
 launching
+layered
 layers
 le
 legs
 lengths
+lib2a
+lib2b
 lightly
 likewise
 lily
@@ -644,6 +647,8 @@
 loopback
 mac
 macro
+macro2a
+macro2b
 macros
 maker
 matters
diff --git a/pkg/kernel/lib/util/graph.dart b/pkg/kernel/lib/util/graph.dart
index 4119f1b..aedbf14 100644
--- a/pkg/kernel/lib/util/graph.dart
+++ b/pkg/kernel/lib/util/graph.dart
@@ -4,12 +4,42 @@
 
 library fasta.graph;
 
+import 'dart:math';
+
+import '../ast.dart';
+
 abstract class Graph<T> {
   Iterable<T> get vertices;
 
   Iterable<T> neighborsOf(T vertex);
 }
 
+/// [Graph] implementation using a collection of [Library] nodes as the graph
+/// vertices and using library dependencies to compute neighbors.
+///
+/// If [coreLibrary] is provided, it will be included in the neighbor of all
+/// vertices. Otherwise, `dart:core` will only be neighboring libraries that
+/// explicitly dependent on it.
+class LibraryGraph implements Graph<Library> {
+  final Iterable<Library> libraries;
+  final Library? coreLibrary;
+
+  LibraryGraph(this.libraries, {this.coreLibrary});
+
+  @override
+  Iterable<Library> get vertices => libraries;
+
+  @override
+  Iterable<Library> neighborsOf(Library library) sync* {
+    if (coreLibrary != null && library != coreLibrary) {
+      yield coreLibrary!;
+    }
+    for (LibraryDependency dependency in library.dependencies) {
+      yield dependency.targetLibrary;
+    }
+  }
+}
+
 /// Computes the strongly connected components of [graph].
 ///
 /// This implementation is based on [Dijkstra's path-based strong component
@@ -77,3 +107,93 @@
 
   return result;
 }
+
+/// A [Graph] using strongly connected components, as computed by
+/// [computeStrongComponents], as vertices. Neighbors are computed using the
+/// neighbors of the provided [subgraph] which was used to compute the strongly
+/// connected components.
+class StrongComponentGraph<T> implements Graph<List<T>> {
+  final Graph<T> subgraph;
+  final List<List<T>> components;
+  final Map<T, List<T>> _elementToComponentMap = {};
+  final Map<List<T>, Set<List<T>>> _neighborsMap = {};
+
+  StrongComponentGraph(this.subgraph, this.components) {
+    for (List<T> component in components) {
+      for (T element in component) {
+        _elementToComponentMap[element] = component;
+      }
+    }
+  }
+
+  Set<List<T>> _computeNeighborsOf(List<T> component) {
+    Set<List<T>> neighbors = {};
+    for (T element in component) {
+      for (T neighborElement in subgraph.neighborsOf(element)) {
+        List<T> neighborComponent = _elementToComponentMap[neighborElement]!;
+        if (component != neighborComponent) {
+          neighbors.add(neighborComponent);
+        }
+      }
+    }
+    return neighbors;
+  }
+
+  @override
+  Iterable<List<T>> neighborsOf(List<T> vertex) {
+    return _neighborsMap[vertex] ??= _computeNeighborsOf(vertex);
+  }
+
+  @override
+  Iterable<List<T>> get vertices => components;
+}
+
+/// Returns the non-cyclic vertices of [graph] sorted in topological order.
+///
+/// If [indexMap] is provided, it is filled with "index" of each vertex.
+/// If [layers] is provided, it is filled with a list of the vertices for each
+/// "index".
+///
+/// Here, the "index" of a vertex is the length of the longest path through
+/// neighbors. For vertices with no neighbors, the index is 0. For any other
+/// vertex, it is 1 plus max of the index of its neighbors.
+List<T> topologicalSort<T>(Graph<T> graph,
+    {Map<T, int>? indexMap, List<List<T>>? layers}) {
+  List<T> workList = graph.vertices.toList();
+  indexMap ??= {};
+  List<T> topologicallySortedVertices = [];
+  List<T> previousWorkList;
+  do {
+    previousWorkList = workList;
+    workList = [];
+    for (int i = 0; i < previousWorkList.length; i++) {
+      T vertex = previousWorkList[i];
+      int index = 0;
+      bool allSupertypesProcessed = true;
+      for (T neighbor in graph.neighborsOf(vertex)) {
+        int? neighborIndex = indexMap[neighbor];
+        if (neighborIndex == null) {
+          allSupertypesProcessed = false;
+          break;
+        } else {
+          index = max(index, neighborIndex + 1);
+        }
+      }
+      if (allSupertypesProcessed) {
+        indexMap[vertex] = index;
+        topologicallySortedVertices.add(vertex);
+        if (layers != null) {
+          if (index >= layers.length) {
+            assert(index == layers.length);
+            layers.add([vertex]);
+          } else {
+            layers[index].add(vertex);
+          }
+        }
+      } else {
+        workList.add(vertex);
+      }
+    }
+  } while (previousWorkList.length != workList.length);
+  return topologicallySortedVertices;
+}
diff --git a/tools/VERSION b/tools/VERSION
index c982ee7..d12c805 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 40
+PRERELEASE 41
 PRERELEASE_PATCH 0
\ No newline at end of file