Macro. More ordering for declarations phase.

Change-Id: I01e528a0f077367929e9e631992644b198165d6b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/333581
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index 010ab14..4f78ea1 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -350,66 +350,71 @@
     _declaredReferences[name] = reference;
   }
 
-  Future<void> executeMacroDeclarationsPhase({
+  /// Completes with `true` if a macro application was run in this library.
+  ///
+  /// Completes with `false` if there are no macro applications to run, either
+  /// because we ran all, or those that we have not run yet have dependencies
+  /// of interfaces declared in other libraries that, and we have not run yet
+  /// declarations phase macro applications for them.
+  Future<bool> executeMacroDeclarationsPhase({
     required OperationPerformanceImpl performance,
   }) async {
     final macroApplier = linker.macroApplier;
     if (macroApplier == null) {
-      return;
+      return false;
     }
 
-    while (true) {
-      final results = await macroApplier.executeDeclarationsPhase(
-        typeSystem: element.typeSystem,
-      );
+    final results = await macroApplier.executeDeclarationsPhase(
+      library: element,
+    );
 
-      // No more applications to execute.
-      if (results == null) {
-        break;
-      }
-
-      // No results from the application.
-      if (results.isEmpty) {
-        continue;
-      }
-
-      _macroResults.add(results);
-
-      final augmentationCode = macroApplier.buildAugmentationLibraryCode(
-        results,
-      );
-      if (augmentationCode == null) {
-        continue;
-      }
-
-      final importState = kind.addMacroAugmentation(
-        augmentationCode,
-        addLibraryAugmentDirective: true,
-        partialIndex: _macroResults.length,
-      );
-
-      final augmentation = _addMacroAugmentation(importState);
-
-      final macroLinkingUnit = units.last;
-      ElementBuilder(
-        libraryBuilder: this,
-        container: macroLinkingUnit.container,
-        unitReference: macroLinkingUnit.reference,
-        unitElement: macroLinkingUnit.element,
-      ).buildDeclarationElements(macroLinkingUnit.node);
-
-      final nodesToBuildType = NodesToBuildType();
-      final resolver =
-          ReferenceResolver(linker, nodesToBuildType, augmentation);
-      macroLinkingUnit.node.accept(resolver);
-      TypesBuilder(linker).build(nodesToBuildType);
-
-      // Append applications from the partial augmentation.
-      await macroApplier.add(
-        container: augmentation,
-        unit: macroLinkingUnit.node,
-      );
+    // No more applications to execute.
+    if (results == null) {
+      return false;
     }
+
+    // No results from the application.
+    if (results.isEmpty) {
+      return true;
+    }
+
+    _macroResults.add(results);
+
+    final augmentationCode = macroApplier.buildAugmentationLibraryCode(
+      results,
+    );
+    if (augmentationCode == null) {
+      return true;
+    }
+
+    final importState = kind.addMacroAugmentation(
+      augmentationCode,
+      addLibraryAugmentDirective: true,
+      partialIndex: _macroResults.length,
+    );
+
+    final augmentation = _addMacroAugmentation(importState);
+
+    final macroLinkingUnit = units.last;
+    ElementBuilder(
+      libraryBuilder: this,
+      container: macroLinkingUnit.container,
+      unitReference: macroLinkingUnit.reference,
+      unitElement: macroLinkingUnit.element,
+    ).buildDeclarationElements(macroLinkingUnit.node);
+
+    final nodesToBuildType = NodesToBuildType();
+    final resolver = ReferenceResolver(linker, nodesToBuildType, augmentation);
+    macroLinkingUnit.node.accept(resolver);
+    TypesBuilder(linker).build(nodesToBuildType);
+
+    // Append applications from the partial augmentation.
+    await macroApplier.add(
+      libraryElement: element,
+      container: augmentation,
+      unit: macroLinkingUnit.node,
+    );
+    return true;
   }
 
   Future<void> executeMacroTypesPhase({
@@ -460,6 +465,7 @@
 
       // Append applications from the partial augmentation.
       await macroApplier.add(
+        libraryElement: element,
         container: augmentation,
         unit: macroLinkingUnit.node,
       );
@@ -470,6 +476,7 @@
   Future<void> fillMacroApplier(LibraryMacroApplier macroApplier) async {
     for (final linkingUnit in units) {
       await macroApplier.add(
+        libraryElement: element,
         container: element,
         unit: linkingUnit.node,
       );
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index 61edb9d..ed5fe4c 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -305,10 +305,16 @@
   Future<void> _executeMacroDeclarationsPhase({
     required OperationPerformanceImpl performance,
   }) async {
-    for (final library in builders.values) {
-      await library.executeMacroDeclarationsPhase(
-        performance: performance,
-      );
+    while (true) {
+      var hasProgress = false;
+      for (final library in builders.values) {
+        hasProgress |= await library.executeMacroDeclarationsPhase(
+          performance: performance,
+        );
+      }
+      if (!hasProgress) {
+        break;
+      }
     }
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/macro_application.dart b/pkg/analyzer/lib/src/summary2/macro_application.dart
index f3434af..c2cd358 100644
--- a/pkg/analyzer/lib/src/summary2/macro_application.dart
+++ b/pkg/analyzer/lib/src/summary2/macro_application.dart
@@ -8,6 +8,7 @@
 import 'package:_fe_analyzer_shared/src/macros/executor/protocol.dart' as macro;
 import 'package:analyzer/dart/ast/ast.dart' as ast;
 import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart' as ast;
@@ -18,6 +19,7 @@
 import 'package:analyzer/src/summary2/macro_application_error.dart';
 import 'package:analyzer/src/summary2/macro_declarations.dart';
 import 'package:analyzer/src/utilities/extensions/object.dart';
+import 'package:collection/collection.dart';
 
 /// The full list of [macro.ArgumentKind]s for this dart type (includes the type
 /// itself as well as type arguments, in source order with
@@ -71,8 +73,25 @@
   final MultiMacroExecutor macroExecutor;
   final bool Function(Uri) isLibraryBeingLinked;
   final DeclarationBuilder declarationBuilder;
+
+  /// The reversed queue of macro applications to apply.
+  ///
+  /// We add classes before methods, and methods in the reverse order,
+  /// classes in the reverse order, annotations in the direct order.
+  ///
+  /// We iterate from the end looking for the next application to apply.
+  /// This way we ensure two ordering rules:
+  /// 1. inner before outer
+  /// 2. right to left
+  /// 3. source order
   final List<_MacroApplication> _applications = [];
 
+  /// The map from [InstanceElement] to the applications associated with it.
+  /// This includes applications on the class itself, and on the methods of
+  /// the class.
+  final Map<InstanceElement, List<_MacroApplication>> _interfaceApplications =
+      {};
+
   late final macro.TypePhaseIntrospector _typesPhaseIntrospector =
       _TypePhaseIntrospector(elementFactory, declarationBuilder);
 
@@ -84,6 +103,7 @@
   });
 
   Future<void> add({
+    required LibraryElementImpl libraryElement,
     required LibraryOrAugmentationElementImpl container,
     required ast.CompilationUnit unit,
   }) async {
@@ -92,23 +112,31 @@
         case ast.ClassDeclaration():
           final element = declaration.declaredElement;
           element as ClassElementImpl;
+          final declarationElement = element.augmented?.declaration ?? element;
+          declarationElement as ClassElementImpl;
           await _addClassLike(
+            libraryElement: libraryElement,
             container: container,
-            targetElement: element.declarationElement,
+            targetElement: declarationElement,
             classNode: declaration,
             classDeclarationKind: macro.DeclarationKind.classType,
             classAnnotations: declaration.metadata,
+            declarationsPhaseInterface: declarationElement,
             members: declaration.members,
           );
         case ast.MixinDeclaration():
           final element = declaration.declaredElement;
           element as MixinElementImpl;
+          final declarationElement = element.augmented?.declaration ?? element;
+          declarationElement as MixinElementImpl;
           await _addClassLike(
+            libraryElement: libraryElement,
             container: container,
-            targetElement: element.declarationElement,
+            targetElement: declarationElement,
             classNode: declaration,
             classDeclarationKind: macro.DeclarationKind.mixinType,
             classAnnotations: declaration.metadata,
+            declarationsPhaseInterface: declarationElement,
             members: declaration.members,
           );
       }
@@ -134,9 +162,11 @@
   }
 
   Future<List<macro.MacroExecutionResult>?> executeDeclarationsPhase({
-    required TypeSystemImpl typeSystem,
+    required LibraryElementImpl library,
   }) async {
-    final application = _nextForDeclarationsPhase();
+    final application = _nextForDeclarationsPhase(
+      library: library,
+    );
     if (application == null) {
       return null;
     }
@@ -150,7 +180,7 @@
         final introspector = _DeclarationPhaseIntrospector(
           elementFactory,
           declarationBuilder,
-          typeSystem,
+          library.typeSystem,
         );
 
         final result = await macroExecutor.executeDeclarationsPhase(
@@ -204,7 +234,9 @@
   }
 
   Future<void> _addAnnotations({
+    required LibraryElementImpl libraryElement,
     required LibraryOrAugmentationElementImpl container,
+    required InstanceElement? declarationsPhaseElement,
     required ast.Declaration targetNode,
     required macro.DeclarationKind targetDeclarationKind,
     required List<ast.Annotation> annotations,
@@ -251,39 +283,54 @@
         return instance.shouldExecute(targetDeclarationKind, phase);
       }).toSet();
 
-      _applications.add(
-        _MacroApplication(
-          targetNode: targetNode,
-          targetElement: targetElement,
-          targetDeclarationKind: targetDeclarationKind,
-          instance: instance,
-          phasesToExecute: phasesToExecute,
-        ),
+      final application = _MacroApplication(
+        libraryElement: libraryElement,
+        declarationsPhaseElement: declarationsPhaseElement,
+        targetNode: targetNode,
+        targetElement: targetElement,
+        targetDeclarationKind: targetDeclarationKind,
+        annotationNode: annotation,
+        instance: instance,
+        phasesToExecute: phasesToExecute,
       );
+
+      _applications.add(application);
+
+      // Record mapping for declarations phase dependencies.
+      if (declarationsPhaseElement != null) {
+        (_interfaceApplications[declarationsPhaseElement] ??= [])
+            .add(application);
+      }
     }
   }
 
   Future<void> _addClassLike({
+    required LibraryElementImpl libraryElement,
     required LibraryOrAugmentationElementImpl container,
     required MacroTargetElement targetElement,
     required ast.Declaration classNode,
     required macro.DeclarationKind classDeclarationKind,
     required List<ast.Annotation> classAnnotations,
+    required InterfaceElement? declarationsPhaseInterface,
     required List<ast.ClassMember> members,
   }) async {
     await _addAnnotations(
+      libraryElement: libraryElement,
       container: container,
       targetNode: classNode,
       targetDeclarationKind: classDeclarationKind,
+      declarationsPhaseElement: declarationsPhaseInterface,
       annotations: classAnnotations,
     );
 
     for (final member in members.reversed) {
       await _addAnnotations(
+        libraryElement: libraryElement,
         container: container,
         targetNode: member,
         // TODO(scheglov) incomplete
         targetDeclarationKind: macro.DeclarationKind.method,
+        declarationsPhaseElement: declarationsPhaseInterface,
         annotations: member.metadata,
       );
     }
@@ -304,6 +351,28 @@
     }
   }
 
+  bool _hasInterfaceDependenciesSatisfied(_MacroApplication application) {
+    final dependencyElements = _interfaceDependencies(
+      application.declarationsPhaseElement,
+    );
+    if (dependencyElements == null) {
+      return true;
+    }
+
+    for (final dependencyElement in dependencyElements) {
+      final applications = _interfaceApplications[dependencyElement];
+      if (applications != null) {
+        for (final dependencyApplication in applications) {
+          if (dependencyApplication.hasDeclarationsPhase) {
+            return false;
+          }
+        }
+      }
+    }
+
+    return true;
+  }
+
   /// If [annotation] references a macro, invokes the right callback.
   _AnnotationMacro? _importedMacro({
     required LibraryOrAugmentationElementImpl container,
@@ -385,13 +454,58 @@
     throw UnimplementedError();
   }
 
-  /// TODO(scheglov) Should use dependencies.
-  _MacroApplication? _nextForDeclarationsPhase() {
-    for (final application in _applications.reversed) {
-      if (application.phasesToExecute.remove(macro.Phase.declarations)) {
-        return application;
-      }
+  Set<InstanceElement>? _interfaceDependencies(InstanceElement? element) {
+    // TODO(scheglov) other elements
+    switch (element) {
+      case ExtensionElement():
+        // TODO(scheglov) implement
+        throw UnimplementedError();
+      case MixinElement():
+        final augmented = element.augmented;
+        switch (augmented) {
+          case null:
+            return const {};
+          default:
+            return [
+              ...augmented.superclassConstraints.map((e) => e.element),
+              ...augmented.interfaces.map((e) => e.element),
+            ].whereNotNull().toSet();
+        }
+      case InterfaceElement():
+        final augmented = element.augmented;
+        switch (augmented) {
+          case null:
+            return const {};
+          default:
+            return [
+              element.supertype?.element,
+              ...augmented.mixins.map((e) => e.element),
+              ...augmented.interfaces.map((e) => e.element),
+            ].whereNotNull().toSet();
+        }
+      default:
+        return null;
     }
+  }
+
+  _MacroApplication? _nextForDeclarationsPhase({
+    required LibraryElementImpl library,
+  }) {
+    for (final application in _applications.reversed) {
+      if (!application.hasDeclarationsPhase) {
+        continue;
+      }
+      if (application.libraryElement != library) {
+        continue;
+      }
+      if (!_hasInterfaceDependenciesSatisfied(application)) {
+        continue;
+      }
+      // The application has no dependencies to run.
+      application.removeDeclarationsPhase();
+      return application;
+    }
+
     return null;
   }
 
@@ -610,14 +724,22 @@
             .map(declarationBuilder.fromElement.fieldElement)
             .toList();
     }
+    // TODO(scheglov) implement
     throw UnsupportedError('Only introspection on classes is supported');
   }
 
   @override
   Future<List<macro.MethodDeclaration>> methodsOf(
-      covariant macro.IntrospectableType clazz) {
-    // TODO: implement methodsOf
-    throw UnimplementedError();
+      covariant macro.IntrospectableType type) async {
+    switch (type) {
+      case IntrospectableClassDeclarationImpl():
+        return type.element.augmented!.methods
+            .where((e) => !e.isSynthetic)
+            .map(declarationBuilder.fromElement.methodElement)
+            .toList();
+    }
+    // TODO(scheglov) implement
+    throw UnsupportedError('Only introspection on classes is supported');
   }
 
   @override
@@ -675,19 +797,33 @@
 }
 
 class _MacroApplication {
+  final LibraryElementImpl libraryElement;
+  final InstanceElement? declarationsPhaseElement;
   final ast.AstNode targetNode;
   final MacroTargetElement targetElement;
   final macro.DeclarationKind targetDeclarationKind;
+  final ast.Annotation annotationNode;
   final macro.MacroInstanceIdentifier instance;
   final Set<macro.Phase> phasesToExecute;
 
   _MacroApplication({
+    required this.libraryElement,
+    required this.declarationsPhaseElement,
     required this.targetNode,
     required this.targetElement,
     required this.targetDeclarationKind,
+    required this.annotationNode,
     required this.instance,
     required this.phasesToExecute,
   });
+
+  bool get hasDeclarationsPhase {
+    return phasesToExecute.contains(macro.Phase.declarations);
+  }
+
+  void removeDeclarationsPhase() {
+    phasesToExecute.remove(macro.Phase.declarations);
+  }
 }
 
 class _StaticTypeImpl implements macro.StaticType {
@@ -736,14 +872,3 @@
       mixinAugmentations.isNotEmpty ||
       typeAugmentations.isNotEmpty;
 }
-
-extension<T extends InstanceElementImpl> on T {
-  T get declarationElement {
-    switch (augmented) {
-      case T(:final T declaration):
-        return declaration;
-      default:
-        return this;
-    }
-  }
-}
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index b453b2d..6de638c 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -55,6 +55,7 @@
   bool withPropertyLinking = false;
   bool withRedirectedConstructors = false;
   bool withReferences = false;
+  bool withReturnType = true;
   bool withSyntheticDartCoreImport = false;
 
   ElementTextConfiguration({
@@ -539,7 +540,7 @@
       _writeCodeRange(e);
       _writeTypeParameterElements(e.typeParameters);
       _writeParameterElements(e.parameters);
-      _writeType('returnType', e.returnType);
+      _writeReturnType(e.returnType);
       _writeAugmentationTarget(e);
       _writeAugmentation(e);
     });
@@ -710,10 +711,12 @@
 
     _writeElements('exports', e.libraryExports, _writeExportElement);
 
-    _sink.writelnWithIndent('definingUnit');
-    _sink.withIndent(() {
-      _writeUnitElement(e.definingCompilationUnit);
-    });
+    if (configuration.filter(e.definingCompilationUnit)) {
+      _sink.writelnWithIndent('definingUnit');
+      _sink.withIndent(() {
+        _writeUnitElement(e.definingCompilationUnit);
+      });
+    }
 
     if (e is LibraryElementImpl) {
       _writeLibraryAugmentations(e);
@@ -760,7 +763,7 @@
 
       _writeTypeParameterElements(e.typeParameters);
       _writeParameterElements(e.parameters);
-      _writeType('returnType', e.returnType);
+      _writeReturnType(e.returnType);
       _writeNonSyntheticElement(e);
 
       if (e.isAugmentation) {
@@ -967,7 +970,7 @@
 
       expect(e.typeParameters, isEmpty);
       _writeParameterElements(e.parameters);
-      _writeType('returnType', e.returnType);
+      _writeReturnType(e.returnType);
       _writeNonSyntheticElement(e);
       writeLinking();
       _writeAugmentationTarget(e);
@@ -1058,6 +1061,12 @@
     }
   }
 
+  void _writeReturnType(DartType type) {
+    if (configuration.withReturnType) {
+      _writeType('returnType', type);
+    }
+  }
+
   void _writeShouldUseTypeForInitializerInference(
     PropertyInducingElementImpl e,
   ) {
@@ -1129,7 +1138,7 @@
         _sink.withIndent(() {
           _writeTypeParameterElements(aliasedElement.typeParameters);
           _writeParameterElements(aliasedElement.parameters);
-          _writeType('returnType', aliasedElement.returnType);
+          _writeReturnType(aliasedElement.returnType);
         });
       }
     });
diff --git a/pkg/analyzer/test/src/summary/elements_base.dart b/pkg/analyzer/test/src/summary/elements_base.dart
index 9162cc0..b7d95fc 100644
--- a/pkg/analyzer/test/src/summary/elements_base.dart
+++ b/pkg/analyzer/test/src/summary/elements_base.dart
@@ -32,18 +32,14 @@
 
     final uriStr = 'package:test/test.dart';
     final libraryResult = await analysisSession.getLibraryByUri(uriStr);
-    libraryResult as LibraryElementResult;
 
     if (keepLinkingLibraries) {
-      return libraryResult.element as LibraryElementImpl;
+      return libraryResult.element;
     } else {
       analysisContext.changeFile(file.path);
       await analysisContext.applyPendingFileChanges();
       // Ask again, should be read from bytes.
-      final analysisSession = analysisContext.currentSession;
-      final libraryResult = await analysisSession.getLibraryByUri(uriStr);
-      libraryResult as LibraryElementResult;
-      return libraryResult.element as LibraryElementImpl;
+      return testContextLibrary(uriStr);
     }
   }
 
@@ -59,4 +55,17 @@
     }
     expect(actual, expected);
   }
+
+  Future<LibraryElementImpl> testContextLibrary(String uriStr) async {
+    final analysisContext = contextFor(testFile);
+    final analysisSession = analysisContext.currentSession;
+    final libraryResult = await analysisSession.getLibraryByUri(uriStr);
+    return libraryResult.element;
+  }
+}
+
+extension on SomeLibraryElementResult {
+  LibraryElementImpl get element {
+    return (this as LibraryElementResult).element as LibraryElementImpl;
+  }
 }
diff --git a/pkg/analyzer/test/src/summary/macro/order.dart b/pkg/analyzer/test/src/summary/macro/order.dart
index 971a597..34ed6f7 100644
--- a/pkg/analyzer/test/src/summary/macro/order.dart
+++ b/pkg/analyzer/test/src/summary/macro/order.dart
@@ -4,7 +4,8 @@
 
 import 'package:_fe_analyzer_shared/src/macros/api.dart';
 
-/*macro*/ class AddClass implements ClassTypesMacro, MethodTypesMacro {
+/*macro*/ class AddClass
+    implements ClassTypesMacro, MethodTypesMacro, MixinTypesMacro {
   final String name;
 
   const AddClass(this.name);
@@ -19,6 +20,11 @@
     _add(builder);
   }
 
+  @override
+  buildTypesForMixin(method, builder) {
+    _add(builder);
+  }
+
   void _add(TypeBuilder builder) {
     final code = 'class $name {}';
     builder.declareType(name, DeclarationCode.fromString(code));
@@ -26,7 +32,10 @@
 }
 
 /*macro*/ class AddFunction
-    implements ClassDeclarationsMacro, MethodDeclarationsMacro {
+    implements
+        ClassDeclarationsMacro,
+        MethodDeclarationsMacro,
+        MixinDeclarationsMacro {
   final String name;
 
   const AddFunction(this.name);
@@ -41,9 +50,42 @@
     _add(builder);
   }
 
+  @override
+  buildDeclarationsForMixin(method, builder) {
+    _add(builder);
+  }
+
   void _add(DeclarationBuilder builder) {
     final code = 'void $name() {}';
     final declaration = DeclarationCode.fromString(code);
     builder.declareInLibrary(declaration);
   }
 }
+
+/*macro*/ class AddHierarchyMethod implements ClassDeclarationsMacro {
+  final String name;
+
+  const AddHierarchyMethod(this.name);
+
+  @override
+  buildDeclarationsForClass(clazz, builder) async {
+    // builder.typeDeclarationOf(identifier);
+    final methods = (await Future.wait(
+      clazz.interfaces.map(
+        (interface) async {
+          final type = await builder.typeDeclarationOf(interface.identifier);
+          type as IntrospectableType;
+          return await builder.methodsOf(type);
+        },
+      ),
+    ))
+        .expand((element) => element)
+        .toList();
+    final methodsStr = methods.map((e) => e.identifier.name).join('_');
+
+    final compoundName = methodsStr.isEmpty ? name : '${methodsStr}_$name';
+    final code = '  void $compoundName() {}';
+    final declaration = DeclarationCode.fromString(code);
+    builder.declareInType(declaration);
+  }
+}
diff --git a/pkg/analyzer/test/src/summary/macro_test.dart b/pkg/analyzer/test/src/summary/macro_test.dart
index 934f9ff..47b4e06 100644
--- a/pkg/analyzer/test/src/summary/macro_test.dart
+++ b/pkg/analyzer/test/src/summary/macro_test.dart
@@ -23,6 +23,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/node_text_expectations.dart';
+import 'element_text.dart';
 import 'elements_base.dart';
 import 'macros_environment.dart';
 
@@ -45,12 +46,16 @@
     defineReflectiveTests(MacroDeclarationsTest_fromBytes);
     defineReflectiveTests(MacroElementsTest_keepLinking);
     defineReflectiveTests(MacroElementsTest_fromBytes);
-    defineReflectiveTests(MacroApplicationOrderTest_keepLinking);
+    defineReflectiveTests(MacroApplicationOrderTest);
     defineReflectiveTests(UpdateNodeTextExpectations);
   });
 }
 
-abstract class MacroApplicationOrderTest extends MacroElementsBaseTest {
+@reflectiveTest
+class MacroApplicationOrderTest extends MacroElementsBaseTest {
+  @override
+  bool get keepLinkingLibraries => true;
+
   String get _orderCode {
     var code = MacrosEnvironment.instance.packageAnalyzerFolder
         .getChildAssumingFile('test/src/summary/macro/order.dart')
@@ -58,34 +63,799 @@
     return code.replaceAll('/*macro*/', 'macro');
   }
 
-  test_phases_class_types_declarations() async {
-    newFile('$testPackageLibPath/a.dart', _orderCode);
+  test_declarations_class_interfaces_backward() async {
+    _newOrderMacrosFile();
 
     var library = await buildLibrary(r'''
-import 'a.dart';
+import 'order.dart';
+
+@AddFunction('f31')
+@AddFunction('f32')
+class X3 {}
+
+@AddFunction('f21')
+@AddFunction('f22')
+class X2 {}
+
+@AddFunction('f11')
+@AddFunction('f12')
+class X1 implements X2, X3 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f32() {}
+void f31() {}
+void f22() {}
+void f21() {}
+void f12() {}
+void f11() {}
+---
+''');
+  }
+
+  test_declarations_class_interfaces_forward() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f11')
+@AddFunction('f12')
+class X1 implements X2, X3 {}
+
+@AddFunction('f21')
+@AddFunction('f22')
+class X2 {}
+
+@AddFunction('f31')
+@AddFunction('f32')
+class X3 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f22() {}
+void f21() {}
+void f32() {}
+void f31() {}
+void f12() {}
+void f11() {}
+---
+''');
+  }
+
+  test_declarations_class_interfaces_forward2() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f11')
+@AddFunction('f12')
+class X1 implements X3, X4 {}
+
+@AddFunction('f21')
+@AddFunction('f22')
+class X2 implements X3, X4 {}
+
+@AddFunction('f31')
+@AddFunction('f32')
+class X3 {}
+
+@AddFunction('f41')
+@AddFunction('f42')
+class X4 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f32() {}
+void f31() {}
+void f42() {}
+void f41() {}
+void f12() {}
+void f11() {}
+void f22() {}
+void f21() {}
+---
+''');
+  }
+
+  test_declarations_class_interfaces_forward3() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f11')
+@AddFunction('f12')
+class X1 implements X2, X4 {}
+
+@AddFunction('f21')
+@AddFunction('f22')
+class X2 implements X3 {}
+
+@AddFunction('f31')
+@AddFunction('f32')
+class X3 {}
+
+@AddFunction('f41')
+@AddFunction('f42')
+class X4 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f32() {}
+void f31() {}
+void f22() {}
+void f21() {}
+void f42() {}
+void f41() {}
+void f12() {}
+void f11() {}
+---
+''');
+  }
+
+  test_declarations_class_mixins_backward() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f31')
+@AddFunction('f32')
+mixin X3 {}
+
+@AddFunction('f21')
+@AddFunction('f22')
+mixin X2 {}
+
+@AddFunction('f11')
+@AddFunction('f12')
+class X1 with X2, X3 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f32() {}
+void f31() {}
+void f22() {}
+void f21() {}
+void f12() {}
+void f11() {}
+---
+''');
+  }
+
+  test_declarations_class_mixins_forward() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f11')
+@AddFunction('f12')
+class X1 with X2, X3 {}
+
+@AddFunction('f21')
+@AddFunction('f22')
+mixin X2 {}
+
+@AddFunction('f31')
+@AddFunction('f32')
+mixin X3 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f22() {}
+void f21() {}
+void f32() {}
+void f31() {}
+void f12() {}
+void f11() {}
+---
+''');
+  }
+
+  test_declarations_class_superclass_backward() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f3')
+class X3 extends X2 {
+  @AddFunction('f31')
+  void foo() {}
+
+  @AddFunction('f32')
+  void bar() {}
+}
+
+@AddFunction('f2')
+class X2 extends X1 {
+  @AddFunction('f21')
+  void foo() {}
+
+  @AddFunction('f22')
+  void bar() {}
+}
+
+@AddFunction('f1')
+class X1 {
+  @AddFunction('f11')
+  void foo() {}
+
+  @AddFunction('f12')
+  void bar() {}
+}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f11() {}
+void f12() {}
+void f1() {}
+void f21() {}
+void f22() {}
+void f2() {}
+void f31() {}
+void f32() {}
+void f3() {}
+---
+''');
+  }
+
+  test_declarations_class_superclass_forward() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f1')
+class X1 {
+  @AddFunction('f11')
+  void foo() {}
+
+  @AddFunction('f12')
+  void bar() {}
+}
+
+@AddFunction('f2')
+class X2 extends X1 {
+  @AddFunction('f21')
+  void foo() {}
+
+  @AddFunction('f22')
+  void bar() {}
+}
+
+@AddFunction('f3')
+class X3 extends X2 {
+  @AddFunction('f31')
+  void foo() {}
+
+  @AddFunction('f32')
+  void bar() {}
+}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f11() {}
+void f12() {}
+void f1() {}
+void f21() {}
+void f22() {}
+void f2() {}
+void f31() {}
+void f32() {}
+void f3() {}
+---
+''');
+  }
+
+  test_declarations_class_superClass_mixins_interfaces_backward() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f41')
+@AddFunction('f42')
+class X4 {}
+
+@AddFunction('f31')
+@AddFunction('f32')
+mixin X3 {}
+
+@AddFunction('f21')
+@AddFunction('f22')
+class X2 {}
+
+@AddFunction('f11')
+@AddFunction('f12')
+class X1 extends X2 with X3 implements X4 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f42() {}
+void f41() {}
+void f32() {}
+void f31() {}
+void f22() {}
+void f21() {}
+void f12() {}
+void f11() {}
+---
+''');
+  }
+
+  test_declarations_class_superClass_mixins_interfaces_forward() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f11')
+@AddFunction('f12')
+class X1 extends X2 with X3 implements X4 {}
+
+@AddFunction('f21')
+@AddFunction('f22')
+class X2 {}
+
+@AddFunction('f31')
+@AddFunction('f32')
+mixin X3 {}
+
+@AddFunction('f41')
+@AddFunction('f42')
+class X4 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f22() {}
+void f21() {}
+void f32() {}
+void f31() {}
+void f42() {}
+void f41() {}
+void f12() {}
+void f11() {}
+---
+''');
+  }
+
+  test_declarations_libraryCycle_class_interfaces() async {
+    useEmptyByteStore();
+    _newOrderMacrosFile();
+
+    newFile('$testPackageLibPath/x2.dart', r'''
+import 'test.dart';
+import 'order.dart';
+
+@AddHierarchyMethod('f211')
+@AddHierarchyMethod('f212')
+class X21 {}
+
+@AddHierarchyMethod('f221')
+@AddHierarchyMethod('f222')
+class X22 {}
+''');
+
+    final testLibrary = await buildLibrary(r'''
+import 'order.dart';
+import 'x2.dart';
+
+@AddHierarchyMethod('f11')
+@AddHierarchyMethod('f12')
+class X1 implements X22 {}
+''');
+
+    // When we process `X1`, we see macro generated methods of `X22`.
+    // This shows that we processed `X22` before `X1`.
+    configuration.forOrder();
+    checkElementText(testLibrary, r'''
+library
+  imports
+    package:test/order.dart
+    package:test/x2.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+augment class X1 {
+  void f222_f221_f12() {}
+  void f222_f221_f11() {}
+}
+---
+''');
+
+    // There are no dependencies between `X21` and `X22`, so they are
+    // processed in the source order.
+    // We see `f212` before `f211`, this shows that we process annotations
+    // from right to left.
+    final x2Library = await testContextLibrary('package:test/x2.dart');
+    checkElementText(x2Library, r'''
+library
+  imports
+    package:test/test.dart
+    package:test/order.dart
+  augmentationImports
+    package:test/x2.macro.dart
+      macroGeneratedCode
+---
+library augment 'x2.dart';
+
+augment class X21 {
+  void f212() {}
+  void f211() {}
+}
+augment class X22 {
+  void f222() {}
+  void f221() {}
+}
+---
+''');
+  }
+
+  test_declarations_mixin_interfaces_backward() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f31')
+@AddFunction('f32')
+class X3 {}
+
+@AddFunction('f21')
+@AddFunction('f22')
+class X2 {}
+
+@AddFunction('f11')
+@AddFunction('f12')
+mixin X1 implements X2, X3 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f32() {}
+void f31() {}
+void f22() {}
+void f21() {}
+void f12() {}
+void f11() {}
+---
+''');
+  }
+
+  test_declarations_mixin_interfaces_forward() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f11')
+@AddFunction('f12')
+mixin X1 implements X2, X3 {}
+
+@AddFunction('f21')
+@AddFunction('f22')
+class X2 {}
+
+@AddFunction('f31')
+@AddFunction('f32')
+class X3 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f22() {}
+void f21() {}
+void f32() {}
+void f31() {}
+void f12() {}
+void f11() {}
+---
+''');
+  }
+
+  test_declarations_mixin_superclassConstraints_backward() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f31')
+@AddFunction('f32')
+class X3 {}
+
+@AddFunction('f21')
+@AddFunction('f22')
+class X2 {}
+
+@AddFunction('f11')
+@AddFunction('f12')
+mixin X1 on X2, X3 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f32() {}
+void f31() {}
+void f22() {}
+void f21() {}
+void f12() {}
+void f11() {}
+---
+''');
+  }
+
+  test_declarations_mixin_superclassConstraints_forward() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f11')
+@AddFunction('f12')
+mixin X1 on X2, X3 {}
+
+@AddFunction('f21')
+@AddFunction('f22')
+class X2 {}
+
+@AddFunction('f31')
+@AddFunction('f32')
+class X3 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f22() {}
+void f21() {}
+void f32() {}
+void f31() {}
+void f12() {}
+void f11() {}
+---
+''');
+  }
+
+  test_declarations_mixin_superclassConstraints_interfaces_backward() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f31')
+@AddFunction('f32')
+class X3 {}
+
+@AddFunction('f21')
+@AddFunction('f22')
+class X2 {}
+
+@AddFunction('f11')
+@AddFunction('f12')
+mixin X1 on X2 implements X3 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f32() {}
+void f31() {}
+void f22() {}
+void f21() {}
+void f12() {}
+void f11() {}
+---
+''');
+  }
+
+  test_declarations_mixin_superclassConstraints_interfaces_forward() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddFunction('f11')
+@AddFunction('f12')
+mixin X1 on X2 implements X3 {}
+
+@AddFunction('f21')
+@AddFunction('f22')
+class X2 {}
+
+@AddFunction('f31')
+@AddFunction('f32')
+class X3 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+void f22() {}
+void f21() {}
+void f32() {}
+void f31() {}
+void f12() {}
+void f11() {}
+---
+''');
+  }
+
+  test_phases_class_types_declarations() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
 
 @AddClass('A1')
 @AddFunction('f1')
 class X {}
 ''');
 
-    configuration
-      ..withConstructors = false
-      ..withMetadata = false
-      ..withReferences = true;
+    configuration.forOrder();
     checkElementText(library, r'''
 library
-  reference: self
   imports
-    package:test/a.dart
-  definingUnit
-    reference: self
-    classes
-      class X @59
-        reference: self::@class::X
+    package:test/order.dart
   augmentationImports
     package:test/test.macro.dart
-      reference: self::@augmentation::package:test/test.macro.dart
       macroGeneratedCode
 ---
 library augment 'test.dart';
@@ -93,23 +863,14 @@
 class A1 {}
 void f1() {}
 ---
-      definingUnit
-        reference: self::@augmentation::package:test/test.macro.dart
-        classes
-          class A1 @36
-            reference: self::@augmentation::package:test/test.macro.dart::@class::A1
-        functions
-          f1 @47
-            reference: self::@augmentation::package:test/test.macro.dart::@function::f1
-            returnType: void
 ''');
   }
 
   test_types_class_method_rightToLeft() async {
-    newFile('$testPackageLibPath/a.dart', _orderCode);
+    _newOrderMacrosFile();
 
     var library = await buildLibrary(r'''
-import 'a.dart';
+import 'order.dart';
 
 class X {
   @AddClass('A1')
@@ -118,27 +879,13 @@
 }
 ''');
 
-    configuration
-      ..withConstructors = false
-      ..withMetadata = false
-      ..withReferences = true;
+    configuration.forOrder();
     checkElementText(library, r'''
 library
-  reference: self
   imports
-    package:test/a.dart
-  definingUnit
-    reference: self
-    classes
-      class X @24
-        reference: self::@class::X
-        methods
-          foo @71
-            reference: self::@class::X::@method::foo
-            returnType: void
+    package:test/order.dart
   augmentationImports
     package:test/test.macro.dart
-      reference: self::@augmentation::package:test/test.macro.dart
       macroGeneratedCode
 ---
 library augment 'test.dart';
@@ -146,21 +893,14 @@
 class A2 {}
 class A1 {}
 ---
-      definingUnit
-        reference: self::@augmentation::package:test/test.macro.dart
-        classes
-          class A2 @36
-            reference: self::@augmentation::package:test/test.macro.dart::@class::A2
-          class A1 @48
-            reference: self::@augmentation::package:test/test.macro.dart::@class::A1
 ''');
   }
 
   test_types_class_method_sourceOrder() async {
-    newFile('$testPackageLibPath/a.dart', _orderCode);
+    _newOrderMacrosFile();
 
     var library = await buildLibrary(r'''
-import 'a.dart';
+import 'order.dart';
 
 class X {
   @AddClass('A1')
@@ -171,30 +911,13 @@
 }
 ''');
 
-    configuration
-      ..withConstructors = false
-      ..withMetadata = false
-      ..withReferences = true;
+    configuration.forOrder();
     checkElementText(library, r'''
 library
-  reference: self
   imports
-    package:test/a.dart
-  definingUnit
-    reference: self
-    classes
-      class X @24
-        reference: self::@class::X
-        methods
-          foo @53
-            reference: self::@class::X::@method::foo
-            returnType: void
-          bar @88
-            reference: self::@class::X::@method::bar
-            returnType: void
+    package:test/order.dart
   augmentationImports
     package:test/test.macro.dart
-      reference: self::@augmentation::package:test/test.macro.dart
       macroGeneratedCode
 ---
 library augment 'test.dart';
@@ -202,44 +925,27 @@
 class A1 {}
 class A2 {}
 ---
-      definingUnit
-        reference: self::@augmentation::package:test/test.macro.dart
-        classes
-          class A1 @36
-            reference: self::@augmentation::package:test/test.macro.dart::@class::A1
-          class A2 @48
-            reference: self::@augmentation::package:test/test.macro.dart::@class::A2
 ''');
   }
 
   test_types_class_rightToLeft() async {
-    newFile('$testPackageLibPath/a.dart', _orderCode);
+    _newOrderMacrosFile();
 
     var library = await buildLibrary(r'''
-import 'a.dart';
+import 'order.dart';
 
 @AddClass('A1')
 @AddClass('A2')
 class X {}
 ''');
 
-    configuration
-      ..withConstructors = false
-      ..withMetadata = false
-      ..withReferences = true;
+    configuration.forOrder();
     checkElementText(library, r'''
 library
-  reference: self
   imports
-    package:test/a.dart
-  definingUnit
-    reference: self
-    classes
-      class X @56
-        reference: self::@class::X
+    package:test/order.dart
   augmentationImports
     package:test/test.macro.dart
-      reference: self::@augmentation::package:test/test.macro.dart
       macroGeneratedCode
 ---
 library augment 'test.dart';
@@ -247,48 +953,29 @@
 class A2 {}
 class A1 {}
 ---
-      definingUnit
-        reference: self::@augmentation::package:test/test.macro.dart
-        classes
-          class A2 @36
-            reference: self::@augmentation::package:test/test.macro.dart::@class::A2
-          class A1 @48
-            reference: self::@augmentation::package:test/test.macro.dart::@class::A1
 ''');
   }
 
   test_types_class_sourceOrder() async {
-    newFile('$testPackageLibPath/a.dart', _orderCode);
+    _newOrderMacrosFile();
 
     var library = await buildLibrary(r'''
-import 'a.dart';
+import 'order.dart';
 
 @AddClass('A1')
-class X {}
+class X1 {}
 
 @AddClass('A2')
-class Y {}
+class X2 {}
 ''');
 
-    configuration
-      ..withConstructors = false
-      ..withMetadata = false
-      ..withReferences = true;
+    configuration.forOrder();
     checkElementText(library, r'''
 library
-  reference: self
   imports
-    package:test/a.dart
-  definingUnit
-    reference: self
-    classes
-      class X @40
-        reference: self::@class::X
-      class Y @68
-        reference: self::@class::Y
+    package:test/order.dart
   augmentationImports
     package:test/test.macro.dart
-      reference: self::@augmentation::package:test/test.macro.dart
       macroGeneratedCode
 ---
 library augment 'test.dart';
@@ -296,21 +983,14 @@
 class A1 {}
 class A2 {}
 ---
-      definingUnit
-        reference: self::@augmentation::package:test/test.macro.dart
-        classes
-          class A1 @36
-            reference: self::@augmentation::package:test/test.macro.dart::@class::A1
-          class A2 @48
-            reference: self::@augmentation::package:test/test.macro.dart::@class::A2
 ''');
   }
 
   test_types_innerBeforeOuter_class_method() async {
-    newFile('$testPackageLibPath/a.dart', _orderCode);
+    _newOrderMacrosFile();
 
     var library = await buildLibrary(r'''
-import 'a.dart';
+import 'order.dart';
 
 @AddClass('A1')
 class X {
@@ -319,27 +999,13 @@
 }
 ''');
 
-    configuration
-      ..withConstructors = false
-      ..withMetadata = false
-      ..withReferences = true;
+    configuration.forOrder();
     checkElementText(library, r'''
 library
-  reference: self
   imports
-    package:test/a.dart
-  definingUnit
-    reference: self
-    classes
-      class X @40
-        reference: self::@class::X
-        methods
-          foo @69
-            reference: self::@class::X::@method::foo
-            returnType: void
+    package:test/order.dart
   augmentationImports
     package:test/test.macro.dart
-      reference: self::@augmentation::package:test/test.macro.dart
       macroGeneratedCode
 ---
 library augment 'test.dart';
@@ -347,21 +1013,162 @@
 class A2 {}
 class A1 {}
 ---
-      definingUnit
-        reference: self::@augmentation::package:test/test.macro.dart
-        classes
-          class A2 @36
-            reference: self::@augmentation::package:test/test.macro.dart::@class::A2
-          class A1 @48
-            reference: self::@augmentation::package:test/test.macro.dart::@class::A1
 ''');
   }
-}
 
-@reflectiveTest
-class MacroApplicationOrderTest_keepLinking extends MacroApplicationOrderTest {
-  @override
-  bool get keepLinkingLibraries => true;
+  test_types_innerBeforeOuter_mixin_method() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddClass('A1')
+mixin X {
+  @AddClass('A2')
+  void foo() {}
+}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+class A2 {}
+class A1 {}
+---
+''');
+  }
+
+  test_types_mixin_method_rightToLeft() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+mixin X {
+  @AddClass('A1')
+  @AddClass('A2')
+  void foo() {}
+}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+class A2 {}
+class A1 {}
+---
+''');
+  }
+
+  test_types_mixin_method_sourceOrder() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+mixin X {
+  @AddClass('A1')
+  void foo() {}
+
+  @AddClass('A2')
+  void bar() {}
+}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+class A1 {}
+class A2 {}
+---
+''');
+  }
+
+  test_types_mixin_rightToLeft() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddClass('A1')
+@AddClass('A2')
+mixin X {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+class A2 {}
+class A1 {}
+---
+''');
+  }
+
+  test_types_mixin_sourceOrder() async {
+    _newOrderMacrosFile();
+
+    var library = await buildLibrary(r'''
+import 'order.dart';
+
+@AddClass('A1')
+mixin X1 {}
+
+@AddClass('A2')
+mixin X2 {}
+''');
+
+    configuration.forOrder();
+    checkElementText(library, r'''
+library
+  imports
+    package:test/order.dart
+  augmentationImports
+    package:test/test.macro.dart
+      macroGeneratedCode
+---
+library augment 'test.dart';
+
+class A1 {}
+class A2 {}
+---
+''');
+  }
+
+  void _newOrderMacrosFile() {
+    newFile('$testPackageLibPath/order.dart', _orderCode);
+  }
 }
 
 @reflectiveTest
@@ -3256,3 +4063,18 @@
     return file;
   }
 }
+
+extension on ElementTextConfiguration {
+  void forOrder() {
+    filter = (element) {
+      if (element is CompilationUnitElement) {
+        return false;
+        // return element.source.uri != Uri.parse('package:test/test.dart');
+      }
+      return true;
+    };
+    withConstructors = false;
+    withMetadata = false;
+    withReturnType = false;
+  }
+}