[cfe] Add MacroAnnotationParser to support early recognition

This CL adds a parser listener that supports (the initial) part of
the syntax needed to support detection of macro application early in
the pipeline. The listener is deliberately implementing (as opposed to
extending) the listener interface to ensure that all case handled in
the listener itself. The listener keeps track of whether unsupported
constructs have been seen to ensure that only valid syntax results
in a macro application.

Change-Id: I6742a0daa39c80f09759b41b9abdd7e693da4cc0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/225723
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
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 9a1166d..4cf5f7e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -395,6 +395,7 @@
       List<SourceClassBuilder> sourceClassBuilders =
           loader.checkSemantics(objectClassBuilder);
       loader.computeMacroDeclarations(sourceClassBuilders);
+      loader.computeMacroApplications();
       loader.finishTypeVariables(objectClassBuilder, dynamicType);
       loader.createTypeInferenceEngine();
       loader.buildComponent();
@@ -416,7 +417,6 @@
       loader.checkMixins(sourceClassBuilders);
       loader.buildOutlineExpressions(
           loader.coreTypes, synthesizedFunctionNodes);
-      loader.computeMacroApplications();
       loader.checkTypes();
       loader.checkRedirectingFactories(sourceClassBuilders);
       loader.checkMainMethods();
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro.dart
index dd6dfb1..65a8279 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -21,11 +21,19 @@
 }
 
 class MacroApplications {
-  final List<Class> macros;
+  final List<MacroApplication> macros;
 
   MacroApplications(this.macros);
 }
 
+class MacroApplication {
+  final Class cls;
+  final String constructorName;
+  // TODO(johnniwinther): Add support for arguments.
+
+  MacroApplication(this.cls, this.constructorName);
+}
+
 class LibraryMacroApplicationData {
   Map<Class, ClassMacroApplicationData> classData = {};
   Map<Member, MacroApplications> memberApplications = {};
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro_annotation_parser.dart b/pkg/front_end/lib/src/fasta/kernel/macro_annotation_parser.dart
new file mode 100644
index 0000000..118e001
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/macro_annotation_parser.dart
@@ -0,0 +1,1927 @@
+// 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:_fe_analyzer_shared/src/messages/codes.dart';
+import 'package:_fe_analyzer_shared/src/parser/parser.dart';
+import 'package:_fe_analyzer_shared/src/scanner/error_token.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+
+import '../builder/builder.dart';
+import '../builder/class_builder.dart';
+import '../builder/member_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/prefix_builder.dart';
+import '../scope.dart';
+import '../source/diet_parser.dart';
+import '../source/source_library_builder.dart';
+
+import 'macro.dart';
+
+List<MacroApplication>? prebuildAnnotations(
+    {required SourceLibraryBuilder enclosingLibrary,
+    required List<MetadataBuilder>? metadataBuilders,
+    required Uri fileUri,
+    required Scope scope}) {
+  if (metadataBuilders == null) return null;
+  List<MacroApplication>? result;
+  for (MetadataBuilder metadataBuilder in metadataBuilders) {
+    _MacroListener listener =
+        new _MacroListener(enclosingLibrary, fileUri, scope);
+    Parser parser = new Parser(listener,
+        useImplicitCreationExpression: useImplicitCreationExpressionInCfe);
+    parser.parseMetadata(
+        parser.syntheticPreviousToken(metadataBuilder.beginToken));
+    MacroApplication? application = listener.popMacroApplication();
+    if (application != null) {
+      result ??= [];
+      result.add(application);
+    }
+  }
+  return result;
+}
+
+class _Node {}
+
+class _UnrecognizedNode implements _Node {
+  const _UnrecognizedNode();
+}
+
+class _MacroClassNode implements _Node {
+  final Token token;
+  final ClassBuilder classBuilder;
+
+  _MacroClassNode(this.token, this.classBuilder);
+}
+
+class _MacroConstructorNode implements _Node {
+  final ClassBuilder classBuilder;
+  final String constructorName;
+
+  _MacroConstructorNode(this.classBuilder, this.constructorName);
+}
+
+class _PrefixNode implements _Node {
+  final PrefixBuilder prefixBuilder;
+
+  _PrefixNode(this.prefixBuilder);
+}
+
+class _MacroApplicationNode implements _Node {
+  final MacroApplication application;
+
+  _MacroApplicationNode(this.application);
+}
+
+class _NoArgumentsNode implements _Node {
+  const _NoArgumentsNode();
+}
+
+class _ArgumentsNode implements _Node {
+  _ArgumentsNode();
+}
+
+class _MacroListener implements Listener {
+  final SourceLibraryBuilder currentLibrary;
+
+  @override
+  final Uri uri;
+
+  final Scope scope;
+
+  final List<_Node> _stack = [];
+
+  Object? _unrecognized;
+
+  bool get unrecognized => _unrecognized != null;
+
+  void set unrecognized(bool value) {
+    if (value) {
+      // TODO(johnniwinther): Remove this when implementation is more mature.
+      _unrecognized = StackTrace.current;
+    } else {
+      _unrecognized = null;
+    }
+  }
+
+  _MacroListener(this.currentLibrary, this.uri, this.scope);
+
+  void pushUnsupported() {
+    push(const _UnrecognizedNode());
+    _unsupported();
+  }
+
+  void push(_Node node) {
+    _stack.add(node);
+  }
+
+  _Node pop() => _stack.removeLast();
+
+  MacroApplication? popMacroApplication() {
+    if (unrecognized) return null;
+    if (_stack.length != 1) return null;
+    _Node node = pop();
+    if (node is _MacroApplicationNode) {
+      return node.application;
+    }
+    return null;
+  }
+
+  @override
+  void beginMetadata(Token token) {
+    // Do nothing.
+  }
+
+  @override
+  void endMetadata(Token beginToken, Token? periodBeforeName, Token endToken) {
+    _Node argumentsNode = pop();
+    _Node referenceNode = pop();
+    if (!unrecognized) {
+      ClassBuilder? macroClass;
+      String? constructorName;
+      if (referenceNode is _MacroClassNode) {
+        macroClass = referenceNode.classBuilder;
+        MemberBuilder? member = referenceNode.classBuilder
+            .findConstructorOrFactory(
+                '', referenceNode.token.charOffset, uri, currentLibrary);
+        if (member != null) {
+          constructorName = '';
+        }
+      } else if (referenceNode is _MacroConstructorNode) {
+        macroClass = referenceNode.classBuilder;
+        constructorName = referenceNode.constructorName;
+      }
+      if (macroClass != null &&
+          constructorName != null &&
+          argumentsNode is _ArgumentsNode) {
+        push(new _MacroApplicationNode(
+            new MacroApplication(macroClass.cls, constructorName)));
+        return;
+      }
+    }
+    pushUnsupported();
+  }
+
+  @override
+  void handleIdentifier(Token token, IdentifierContext context) {
+    switch (context) {
+      case IdentifierContext.metadataReference:
+        Builder? builder = scope.lookup(token.lexeme, token.charOffset, uri);
+        if (builder is ClassBuilder && builder.isMacro) {
+          push(new _MacroClassNode(token, builder));
+        } else if (builder is PrefixBuilder) {
+          push(new _PrefixNode(builder));
+        } else {
+          pushUnsupported();
+        }
+        break;
+      case IdentifierContext.metadataContinuation:
+        _Node node = pop();
+        if (node is _PrefixNode) {
+          Builder? builder =
+              node.prefixBuilder.lookup(token.lexeme, token.charOffset, uri);
+          if (builder is ClassBuilder && builder.isMacro) {
+            push(new _MacroClassNode(token, builder));
+          } else {
+            pushUnsupported();
+          }
+        } else if (node is _MacroClassNode) {
+          MemberBuilder? member = node.classBuilder.findConstructorOrFactory(
+              token.lexeme, token.charOffset, uri, currentLibrary);
+          if (member != null) {
+            push(new _MacroConstructorNode(node.classBuilder, token.lexeme));
+          } else {
+            pushUnsupported();
+          }
+        } else {
+          pushUnsupported();
+        }
+        break;
+      case IdentifierContext.metadataContinuationAfterTypeArguments:
+        _Node node = pop();
+        if (node is _MacroClassNode) {
+          MemberBuilder? member = node.classBuilder.findConstructorOrFactory(
+              token.lexeme, token.charOffset, uri, currentLibrary);
+          if (member != null) {
+            push(new _MacroConstructorNode(node.classBuilder, token.lexeme));
+          } else {
+            pushUnsupported();
+          }
+        } else {
+          pushUnsupported();
+        }
+        break;
+      default:
+        pushUnsupported();
+        break;
+    }
+  }
+
+  @override
+  void beginArguments(Token token) {
+    // Do nothing.
+  }
+
+  @override
+  void endArguments(int count, Token beginToken, Token endToken) {
+    if (count == 0) {
+      push(new _ArgumentsNode());
+    } else {
+      // TODO(johnniwinther): Handle arguments.
+      pushUnsupported();
+    }
+  }
+
+  @override
+  void handleNoArguments(Token token) {
+    push(const _NoArgumentsNode());
+  }
+
+  @override
+  void handleNoTypeArguments(Token token) {
+    // TODO(johnniwinther): Handle type arguments. Ignore for now.
+  }
+
+  @override
+  void handleQualified(Token period) {
+    // Do nothing. Supported qualified names are handled through the identifier
+    // context.
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  // Stub implementation
+  //////////////////////////////////////////////////////////////////////////////
+
+  /// Called for listener events that are expected but not supported.
+  void _unsupported() {
+    unrecognized = true;
+  }
+
+  /// Called for listener events that are unexpected.
+  void _unexpected() {
+    unrecognized = true;
+  }
+
+  /// Called for listener events that are supported but not handled yet.
+  void _unhandled() {
+    unrecognized = true;
+  }
+
+  /// Called for listener events whose use in unknown.
+  void _unknown() {
+    unrecognized = true;
+  }
+
+  /// Called for listener events that are ignored.
+  void _ignored() {}
+
+  @override
+  void beginAsOperatorType(Token operator) {
+    _unsupported();
+  }
+
+  @override
+  void beginAssert(Token assertKeyword, Assert kind) {
+    _unsupported();
+  }
+
+  @override
+  void beginAwaitExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginBinaryExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginBlock(Token token, BlockKind blockKind) {
+    _unsupported();
+  }
+
+  @override
+  void beginBlockFunctionBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginCascade(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginCaseExpression(Token caseKeyword) {
+    _unsupported();
+  }
+
+  @override
+  void beginCatchClause(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginClassDeclaration(
+      Token begin, Token? abstractToken, Token? macroToken, Token name) {
+    _unexpected();
+  }
+
+  @override
+  void beginClassOrMixinOrExtensionBody(DeclarationKind kind, Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginClassOrMixinOrNamedMixinApplicationPrelude(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginCombinators(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginCompilationUnit(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginConditionalExpression(Token question) {
+    _unsupported();
+  }
+
+  @override
+  void beginConditionalUri(Token ifKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void beginConditionalUris(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginConstExpression(Token constKeyword) {
+    _unhandled();
+  }
+
+  @override
+  void beginConstLiteral(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void beginConstructorReference(Token start) {
+    _unknown();
+  }
+
+  @override
+  void beginDoWhileStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginDoWhileStatementBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginElseStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginEnum(Token enumKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void beginExport(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginExtensionDeclaration(Token extensionKeyword, Token? name) {
+    _unexpected();
+  }
+
+  @override
+  void beginExtensionDeclarationPrelude(Token extensionKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void beginFactoryMethod(DeclarationKind declarationKind, Token lastConsumed,
+      Token? externalToken, Token? constToken) {
+    _unexpected();
+  }
+
+  @override
+  void beginFieldInitializer(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginFields(
+      DeclarationKind declarationKind,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
+      Token lastConsumed) {
+    _unexpected();
+  }
+
+  @override
+  void beginForControlFlow(Token? awaitToken, Token forToken) {
+    _unsupported();
+  }
+
+  @override
+  void beginForInBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginForInExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginForStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginForStatementBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginFormalParameter(Token token, MemberKind kind, Token? requiredToken,
+      Token? covariantToken, Token? varFinalOrConst) {
+    _unsupported();
+  }
+
+  @override
+  void beginFormalParameterDefaultValueExpression() {
+    _unsupported();
+  }
+
+  @override
+  void beginFormalParameters(Token token, MemberKind kind) {
+    _unsupported();
+  }
+
+  @override
+  void beginFunctionExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginFunctionName(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginFunctionType(Token beginToken) {
+    _unhandled();
+  }
+
+  @override
+  void beginFunctionTypedFormalParameter(Token token) {
+    _unknown();
+  }
+
+  @override
+  void beginHide(Token hideKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void beginIfControlFlow(Token ifToken) {
+    _unsupported();
+  }
+
+  @override
+  void beginIfStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginImplicitCreationExpression(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void beginImport(Token importKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void beginInitializedIdentifier(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginInitializer(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginInitializers(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginIsOperatorType(Token operator) {
+    _unhandled();
+  }
+
+  @override
+  void beginLabeledStatement(Token token, int labelCount) {
+    _unsupported();
+  }
+
+  @override
+  void beginLibraryName(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginLiteralString(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void beginLiteralSymbol(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void beginLocalFunctionDeclaration(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginMember() {
+    _unexpected();
+  }
+
+  @override
+  void beginMetadataStar(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginMethod(
+      DeclarationKind declarationKind,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? varFinalOrConst,
+      Token? getOrSet,
+      Token name) {
+    _unexpected();
+  }
+
+  @override
+  void beginMixinDeclaration(Token mixinKeyword, Token name) {
+    _unexpected();
+  }
+
+  @override
+  void beginNamedFunctionExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginNamedMixinApplication(
+      Token begin, Token? abstractToken, Token? macroToken, Token name) {
+    _unexpected();
+  }
+
+  @override
+  void beginNewExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginOptionalFormalParameters(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginPart(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginPartOf(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginRedirectingFactoryBody(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginRethrowStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginReturnStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginShow(Token showKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void beginSwitchBlock(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginSwitchCase(int labelCount, int expressionCount, Token firstToken) {
+    _unsupported();
+  }
+
+  @override
+  void beginSwitchStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginThenStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginTopLevelMember(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginTopLevelMethod(Token lastConsumed, Token? externalToken) {
+    _unexpected();
+  }
+
+  @override
+  void beginTryStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginTypeArguments(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void beginTypeList(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginTypeVariable(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginTypeVariables(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginTypedef(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginUncategorizedTopLevelDeclaration(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginVariableInitializer(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginVariablesDeclaration(
+      Token token, Token? lateToken, Token? varFinalOrConst) {
+    _unsupported();
+  }
+
+  @override
+  void beginWhileStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginWhileStatementBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginYieldStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endAsOperatorType(Token operator) {
+    _unhandled();
+  }
+
+  @override
+  void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
+      Token? commaToken, Token semicolonToken) {
+    _unsupported();
+  }
+
+  @override
+  void endAwaitExpression(Token beginToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endBinaryExpression(Token token) {
+    _unknown();
+  }
+
+  @override
+  void endBlock(
+      int count, Token beginToken, Token endToken, BlockKind blockKind) {
+    _unsupported();
+  }
+
+  @override
+  void endBlockFunctionBody(int count, Token beginToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endCascade() {
+    _unsupported();
+  }
+
+  @override
+  void endCaseExpression(Token colon) {
+    _unsupported();
+  }
+
+  @override
+  void endCatchClause(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endClassConstructor(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endClassDeclaration(Token beginToken, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endClassFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endClassFields(
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endClassMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endClassOrMixinOrExtensionBody(
+      DeclarationKind kind, int memberCount, Token beginToken, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endCombinators(int count) {
+    _unexpected();
+  }
+
+  @override
+  void endCompilationUnit(int count, Token token) {
+    _unexpected();
+  }
+
+  @override
+  void endConditionalExpression(Token question, Token colon) {
+    _unhandled();
+  }
+
+  @override
+  void endConditionalUri(Token ifKeyword, Token leftParen, Token? equalSign) {
+    _unexpected();
+  }
+
+  @override
+  void endConditionalUris(int count) {
+    _unexpected();
+  }
+
+  @override
+  void endConstExpression(Token token) {
+    _unknown();
+  }
+
+  @override
+  void endConstLiteral(Token token) {
+    _unknown();
+  }
+
+  @override
+  void endConstructorReference(Token start, Token? periodBeforeName,
+      Token endToken, ConstructorReferenceContext constructorReferenceContext) {
+    _unknown();
+  }
+
+  @override
+  void endDoWhileStatement(
+      Token doKeyword, Token whileKeyword, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endDoWhileStatementBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endElseStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endEnum(Token enumKeyword, Token leftBrace, int memberCount) {
+    _unexpected();
+  }
+
+  @override
+  void endEnumConstructor(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endEnumFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endEnumFields(
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endEnumMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endExport(Token exportKeyword, Token semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void endExtensionConstructor(Token? getOrSet, Token beginToken,
+      Token beginParam, Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endExtensionDeclaration(Token extensionKeyword, Token? typeKeyword,
+      Token onKeyword, Token? showKeyword, Token? hideKeyword, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endExtensionFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endExtensionFields(
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endExtensionMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endFieldInitializer(Token assignment, Token token) {
+    _unexpected();
+  }
+
+  @override
+  void endForControlFlow(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endForIn(Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endForInBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endForInControlFlow(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endForInExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endForStatement(Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endForStatementBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endFormalParameter(
+      Token? thisKeyword,
+      Token? superKeyword,
+      Token? periodAfterThisOrSuper,
+      Token nameToken,
+      Token? initializerStart,
+      Token? initializerEnd,
+      FormalParameterKind kind,
+      MemberKind memberKind) {
+    _unsupported();
+  }
+
+  @override
+  void endFormalParameterDefaultValueExpression() {
+    _unsupported();
+  }
+
+  @override
+  void endFormalParameters(
+      int count, Token beginToken, Token endToken, MemberKind kind) {
+    _unsupported();
+  }
+
+  @override
+  void endFunctionExpression(Token beginToken, Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endFunctionName(Token beginToken, Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endFunctionType(Token functionToken, Token? questionMark) {
+    _unhandled();
+  }
+
+  @override
+  void endFunctionTypedFormalParameter(Token nameToken, Token? question) {
+    _unknown();
+  }
+
+  @override
+  void endHide(Token hideKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void endIfControlFlow(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endIfElseControlFlow(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endIfStatement(Token ifToken, Token? elseToken) {
+    _unsupported();
+  }
+
+  @override
+  void endImplicitCreationExpression(Token token, Token openAngleBracket) {
+    _unhandled();
+  }
+
+  @override
+  void endImport(Token importKeyword, Token? semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void endInitializedIdentifier(Token nameToken) {
+    _unsupported();
+  }
+
+  @override
+  void endInitializer(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void endInitializers(int count, Token beginToken, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endInvalidAwaitExpression(
+      Token beginToken, Token endToken, MessageCode errorCode) {
+    _unsupported();
+  }
+
+  @override
+  void endInvalidYieldStatement(Token beginToken, Token? starToken,
+      Token endToken, MessageCode errorCode) {
+    _unsupported();
+  }
+
+  @override
+  void endIsOperatorType(Token operator) {
+    _unhandled();
+  }
+
+  @override
+  void endLabeledStatement(int labelCount) {
+    _unsupported();
+  }
+
+  @override
+  void endLibraryName(Token libraryKeyword, Token semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void endLiteralString(int interpolationCount, Token endToken) {
+    _unhandled();
+  }
+
+  @override
+  void endLiteralSymbol(Token hashToken, int identifierCount) {
+    _unhandled();
+  }
+
+  @override
+  void endLocalFunctionDeclaration(Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endMember() {
+    _unexpected();
+  }
+
+  @override
+  void endMetadataStar(int count) {
+    _unsupported();
+  }
+
+  @override
+  void endMixinConstructor(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endMixinDeclaration(Token mixinKeyword, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endMixinFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endMixinFields(
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endMixinMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endNamedFunctionExpression(Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endNamedMixinApplication(Token begin, Token classKeyword, Token equals,
+      Token? implementsKeyword, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endNewExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endOptionalFormalParameters(
+      int count, Token beginToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endPart(Token partKeyword, Token semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void endPartOf(
+      Token partKeyword, Token ofKeyword, Token semicolon, bool hasName) {
+    _unexpected();
+  }
+
+  @override
+  void endRedirectingFactoryBody(Token beginToken, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endRethrowStatement(Token rethrowToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endReturnStatement(
+      bool hasExpression, Token beginToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endShow(Token showKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endSwitchCase(
+      int labelCount,
+      int expressionCount,
+      Token? defaultKeyword,
+      Token? colonAfterDefault,
+      int statementCount,
+      Token firstToken,
+      Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endSwitchStatement(Token switchKeyword, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endThenStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endTopLevelDeclaration(Token nextToken) {
+    _unexpected();
+  }
+
+  @override
+  void endTopLevelFields(
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endTopLevelMethod(Token beginToken, Token? getOrSet, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endTryStatement(
+      int catchCount, Token tryKeyword, Token? finallyKeyword) {
+    _unsupported();
+  }
+
+  @override
+  void endTypeArguments(int count, Token beginToken, Token endToken) {
+    _unhandled();
+  }
+
+  @override
+  void endTypeList(int count) {
+    _unexpected();
+  }
+
+  @override
+  void endTypeVariable(
+      Token token, int index, Token? extendsOrSuper, Token? variance) {
+    _unsupported();
+  }
+
+  @override
+  void endTypeVariables(Token beginToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endTypedef(Token typedefKeyword, Token? equals, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endVariableInitializer(Token assignmentOperator) {
+    _unsupported();
+  }
+
+  @override
+  void endVariablesDeclaration(int count, Token? endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endWhileStatement(Token whileKeyword, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endWhileStatementBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endYieldStatement(Token yieldToken, Token? starToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleAsOperator(Token operator) {
+    _unhandled();
+  }
+
+  @override
+  void handleAssignmentExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleAsyncModifier(Token? asyncToken, Token? starToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleBreakStatement(
+      bool hasTarget, Token breakKeyword, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleCaseMatch(Token caseKeyword, Token colon) {
+    _unsupported();
+  }
+
+  @override
+  void handleCatchBlock(Token? onKeyword, Token? catchKeyword, Token? comma) {
+    _unsupported();
+  }
+
+  @override
+  void handleClassExtends(Token? extendsKeyword, int typeCount) {
+    _unexpected();
+  }
+
+  @override
+  void handleClassHeader(Token begin, Token classKeyword, Token? nativeToken) {
+    _unexpected();
+  }
+
+  @override
+  void handleClassNoWithClause() {
+    _unexpected();
+  }
+
+  @override
+  void handleClassWithClause(Token withKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void handleCommentReference(
+      Token? newKeyword,
+      Token? firstToken,
+      Token? firstPeriod,
+      Token? secondToken,
+      Token? secondPeriod,
+      Token thirdToken) {
+    _ignored();
+  }
+
+  @override
+  void handleCommentReferenceText(String referenceSource, int referenceOffset) {
+    _ignored();
+  }
+
+  @override
+  void handleConditionalExpressionColon() {
+    _unhandled();
+  }
+
+  @override
+  void handleConstFactory(Token constKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void handleContinueStatement(
+      bool hasTarget, Token continueKeyword, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleDirectivesOnly() {
+    _unknown();
+  }
+
+  @override
+  void handleDottedName(int count, Token firstIdentifier) {
+    _unknown();
+  }
+
+  @override
+  void handleElseControlFlow(Token elseToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleEmptyFunctionBody(Token semicolon) {
+    _unsupported();
+  }
+
+  @override
+  void handleEmptyStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleEndingBinaryExpression(Token token) {
+    _unknown();
+  }
+
+  @override
+  void handleEnumElement(Token beginToken) {
+    _unexpected();
+  }
+
+  @override
+  void handleEnumElements(Token elementsEndToken, int elementsCount) {
+    _unexpected();
+  }
+
+  @override
+  void handleEnumHeader(Token enumKeyword, Token leftBrace) {
+    _unexpected();
+  }
+
+  @override
+  void handleEnumNoWithClause() {
+    _unexpected();
+  }
+
+  @override
+  void handleEnumWithClause(Token withKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void handleErrorToken(ErrorToken token) {
+    _unsupported();
+  }
+
+  @override
+  void handleExpressionFunctionBody(Token arrowToken, Token? endToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleExpressionStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleExtensionShowHide(Token? showKeyword, int showElementCount,
+      Token? hideKeyword, int hideElementCount) {
+    _unexpected();
+  }
+
+  @override
+  void handleExtraneousExpression(Token token, Message message) {
+    _unknown();
+  }
+
+  @override
+  void handleFinallyBlock(Token finallyKeyword) {
+    _unsupported();
+  }
+
+  @override
+  void handleForInLoopParts(Token? awaitToken, Token forToken,
+      Token leftParenthesis, Token inKeyword) {
+    _unsupported();
+  }
+
+  @override
+  void handleForInitializerEmptyStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleForInitializerExpressionStatement(Token token, bool forIn) {
+    _unsupported();
+  }
+
+  @override
+  void handleForInitializerLocalVariableDeclaration(Token token, bool forIn) {
+    _unsupported();
+  }
+
+  @override
+  void handleForLoopParts(Token forKeyword, Token leftParen,
+      Token leftSeparator, int updateExpressionCount) {
+    _unsupported();
+  }
+
+  @override
+  void handleFormalParameterWithoutValue(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleFunctionBodySkipped(Token token, bool isExpressionBody) {
+    _unsupported();
+  }
+
+  @override
+  void handleIdentifierList(int count) {
+    _unknown();
+  }
+
+  @override
+  void handleImplements(Token? implementsKeyword, int interfacesCount) {
+    _unexpected();
+  }
+
+  @override
+  void handleImportPrefix(Token? deferredKeyword, Token? asKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void handleIndexedExpression(
+      Token? question, Token openSquareBracket, Token closeSquareBracket) {
+    _unsupported();
+  }
+
+  @override
+  void handleInterpolationExpression(Token leftBracket, Token? rightBracket) {
+    _unhandled();
+  }
+
+  @override
+  void handleInvalidExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleInvalidFunctionBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleInvalidMember(Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void handleInvalidOperatorName(Token operatorKeyword, Token token) {
+    _unexpected();
+  }
+
+  @override
+  void handleInvalidStatement(Token token, Message message) {
+    _unsupported();
+  }
+
+  @override
+  void handleInvalidTopLevelBlock(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void handleInvalidTopLevelDeclaration(Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void handleInvalidTypeArguments(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleInvalidTypeReference(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleIsOperator(Token isOperator, Token? not) {
+    _unhandled();
+  }
+
+  @override
+  void handleLabel(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleLiteralBool(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleLiteralDouble(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleLiteralInt(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleLiteralList(
+      int count, Token leftBracket, Token? constKeyword, Token rightBracket) {
+    _unhandled();
+  }
+
+  @override
+  void handleLiteralMapEntry(Token colon, Token endToken) {
+    _unhandled();
+  }
+
+  @override
+  void handleLiteralNull(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleLiteralSetOrMap(int count, Token leftBrace, Token? constKeyword,
+      Token rightBrace, bool hasSetEntry) {
+    _unhandled();
+  }
+
+  @override
+  void handleMixinHeader(Token mixinKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void handleMixinOn(Token? onKeyword, int typeCount) {
+    _unexpected();
+  }
+
+  @override
+  void handleNamedArgument(Token colon) {
+    _unhandled();
+  }
+
+  @override
+  void handleNamedMixinApplicationWithClause(Token withKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void handleNativeClause(Token nativeToken, bool hasName) {
+    _unexpected();
+  }
+
+  @override
+  void handleNativeFunctionBody(Token nativeToken, Token semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void handleNativeFunctionBodyIgnored(Token nativeToken, Token semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void handleNativeFunctionBodySkipped(Token nativeToken, Token semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void handleNewAsIdentifier(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleNoCommentReference() {
+    _ignored();
+  }
+
+  @override
+  void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
+    _unknown();
+  }
+
+  @override
+  void handleNoFieldInitializer(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void handleNoFormalParameters(Token token, MemberKind kind) {
+    _unsupported();
+  }
+
+  @override
+  void handleNoFunctionBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleNoInitializers() {
+    _unexpected();
+  }
+
+  @override
+  void handleNoName(Token token) {
+    _unknown();
+  }
+
+  @override
+  void handleNoType(Token lastConsumed) {
+    _unknown();
+  }
+
+  @override
+  void handleNoTypeNameInConstructorReference(Token token) {
+    _unknown();
+  }
+
+  @override
+  void handleNoTypeVariables(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleNoVariableInitializer(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleNonNullAssertExpression(Token bang) {
+    _unsupported();
+  }
+
+  @override
+  void handleOperator(Token token) {
+    _unknown();
+  }
+
+  @override
+  void handleOperatorName(Token operatorKeyword, Token token) {
+    _unexpected();
+  }
+
+  @override
+  void handleParenthesizedCondition(Token token) {
+    _unknown();
+  }
+
+  @override
+  void handleParenthesizedExpression(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleRecoverClassHeader() {
+    _unexpected();
+  }
+
+  @override
+  void handleRecoverImport(Token? semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void handleRecoverMixinHeader() {
+    _unexpected();
+  }
+
+  @override
+  void handleRecoverableError(
+      Message message, Token startToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleScript(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void handleSend(Token beginToken, Token endToken) {
+    _unhandled();
+  }
+
+  @override
+  void handleShowHideIdentifier(Token? modifier, Token identifier) {
+    _unexpected();
+  }
+
+  @override
+  void handleSpreadExpression(Token spreadToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleStringJuxtaposition(Token startToken, int literalCount) {
+    _unhandled();
+  }
+
+  @override
+  void handleStringPart(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleSuperExpression(Token token, IdentifierContext context) {
+    _unsupported();
+  }
+
+  @override
+  void handleSymbolVoid(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleThenControlFlow(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleThisExpression(Token token, IdentifierContext context) {
+    _unsupported();
+  }
+
+  @override
+  void handleThrowExpression(Token throwToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleType(Token beginToken, Token? questionMark) {
+    _unknown();
+  }
+
+  @override
+  void handleTypeArgumentApplication(Token openAngleBracket) {
+    _unhandled();
+  }
+
+  @override
+  void handleTypeVariablesDefined(Token token, int count) {
+    _unsupported();
+  }
+
+  @override
+  void handleUnaryPostfixAssignmentExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleUnaryPrefixAssignmentExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleUnaryPrefixExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleUnescapeError(
+      Message message, covariant Token location, int stringOffset, int length) {
+    _unsupported();
+  }
+
+  @override
+  void handleValuedFormalParameter(Token equals, Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleVoidKeyword(Token token) {
+    _unknown();
+  }
+
+  @override
+  void handleVoidKeywordWithTypeArguments(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void logEvent(String name) {}
+
+  @override
+  void reportVarianceModifierNotEnabled(Token? variance) {
+    _unsupported();
+  }
+}
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 47cb5bd..6c12705 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -35,6 +35,7 @@
 import '../../base/common.dart';
 import '../../base/instrumentation.dart' show Instrumentation;
 import '../../base/nnbd_mode.dart';
+import '../builder/metadata_builder.dart';
 import '../dill/dill_library_builder.dart';
 import '../builder_graph.dart';
 import '../builder/builder.dart';
@@ -67,6 +68,7 @@
     show SynthesizedFunctionNode, TypeDependency;
 import '../kernel/kernel_target.dart' show KernelTarget;
 import '../kernel/macro.dart';
+import '../kernel/macro_annotation_parser.dart';
 import '../kernel/transform_collections.dart' show CollectionTransformer;
 import '../kernel/transform_set_literals.dart' show SetLiteralTransformer;
 import '../kernel/type_builder_computer.dart' show TypeBuilderComputer;
@@ -1381,65 +1383,108 @@
 
   void computeMacroApplications() {
     if (!enableMacros || _macroClassBuilder == null) return;
-    Class macroClass = _macroClassBuilder!.cls;
 
-    Class? computeApplication(Expression expression) {
-      if (expression is ConstructorInvocation) {
-        Class cls = expression.target.enclosingClass;
-        if (hierarchy.isSubtypeOf(cls, macroClass)) {
-          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;
+    MacroApplications? computeApplications(
+        SourceLibraryBuilder enclosingLibrary,
+        Scope scope,
+        Uri fileUri,
+        List<MetadataBuilder>? annotations) {
+      List<MacroApplication>? result = prebuildAnnotations(
+          enclosingLibrary: enclosingLibrary,
+          metadataBuilders: annotations,
+          fileUri: fileUri,
+          scope: scope);
+      return result != null ? new MacroApplications(result) : null;
     }
 
     for (SourceLibraryBuilder libraryBuilder in sourceLibraryBuilders) {
       // TODO(johnniwinther): Handle patch libraries.
       LibraryMacroApplicationData libraryMacroApplicationData =
           new LibraryMacroApplicationData();
-      Library library = libraryBuilder.library;
-      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);
+      Iterator<Builder> iterator = libraryBuilder.iterator;
+      while (iterator.moveNext()) {
+        Builder builder = iterator.current;
+        if (builder is SourceClassBuilder) {
+          SourceClassBuilder classBuilder = builder;
+          ClassMacroApplicationData classMacroApplicationData =
+              new ClassMacroApplicationData();
+          classMacroApplicationData.classApplications = computeApplications(
+              libraryBuilder,
+              classBuilder.scope,
+              classBuilder.fileUri,
+              classBuilder.metadata);
+          builder.forEach((String name, Builder memberBuilder) {
+            if (memberBuilder is SourceProcedureBuilder) {
+              MacroApplications? macroApplications = computeApplications(
+                  libraryBuilder,
+                  classBuilder.scope,
+                  memberBuilder.fileUri,
+                  memberBuilder.metadata);
+              if (macroApplications != null) {
+                classMacroApplicationData
+                        .memberApplications[memberBuilder.procedure] =
+                    macroApplications;
+              }
+            } else if (memberBuilder is SourceFieldBuilder) {
+              MacroApplications? macroApplications = computeApplications(
+                  libraryBuilder,
+                  classBuilder.scope,
+                  memberBuilder.fileUri,
+                  memberBuilder.metadata);
+              if (macroApplications != null) {
+                classMacroApplicationData
+                        .memberApplications[memberBuilder.field] =
+                    macroApplications;
+              }
+            }
+          });
+          classBuilder.forEachConstructor((String name, Builder memberBuilder) {
+            if (memberBuilder is SourceConstructorBuilder) {
+              MacroApplications? macroApplications = computeApplications(
+                  libraryBuilder,
+                  classBuilder.scope,
+                  memberBuilder.fileUri,
+                  memberBuilder.metadata);
+              if (macroApplications != null) {
+                classMacroApplicationData
+                        .memberApplications[memberBuilder.constructor] =
+                    macroApplications;
+              }
+            }
+          });
+
+          if (classMacroApplicationData.classApplications != null ||
+              classMacroApplicationData.memberApplications.isNotEmpty) {
+            libraryMacroApplicationData.classData[builder.cls] =
+                classMacroApplicationData;
+          }
+        } else if (builder is SourceProcedureBuilder) {
+          MacroApplications? macroApplications = computeApplications(
+              libraryBuilder,
+              libraryBuilder.scope,
+              builder.fileUri,
+              builder.metadata);
           if (macroApplications != null) {
-            classMacroApplicationData.memberApplications[member] =
+            libraryMacroApplicationData.memberApplications[builder.procedure] =
                 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;
+        } else if (builder is SourceFieldBuilder) {
+          MacroApplications? macroApplications = computeApplications(
+              libraryBuilder,
+              libraryBuilder.scope,
+              builder.fileUri,
+              builder.metadata);
+          if (macroApplications != null) {
+            libraryMacroApplicationData.memberApplications[builder.field] =
+                macroApplications;
+          }
         }
       }
       if (libraryMacroApplicationData.classData.isNotEmpty ||
           libraryMacroApplicationData.memberApplications.isNotEmpty) {
         if (retainDataForTesting) {
-          dataForTesting!.macroApplicationData.libraryData[library] =
+          dataForTesting!
+                  .macroApplicationData.libraryData[libraryBuilder.library] =
               libraryMacroApplicationData;
         }
       }
diff --git a/pkg/front_end/test/macros/data/pkgs/macro/lib/macro.dart b/pkg/front_end/test/macros/data/pkgs/macro/lib/macro.dart
index d7bf92d..c7fc7d5 100644
--- a/pkg/front_end/test/macros/data/pkgs/macro/lib/macro.dart
+++ b/pkg/front_end/test/macros/data/pkgs/macro/lib/macro.dart
@@ -6,14 +6,20 @@
 
 macro class Macro1 implements Macro {
   const Macro1();
+
+  const Macro1.named();
 }
 
 macro class Macro2 implements Macro {
   const Macro2();
+
+  const Macro2.named();
 }
 
-macro class Macro3 implements Macro {
+macro class Macro3<T> implements Macro {
   const Macro3();
+
+  const Macro3.named();
 }
 
 class NonMacro {
diff --git a/pkg/front_end/test/macros/data/tests/applications.dart b/pkg/front_end/test/macros/data/tests/applications.dart
new file mode 100644
index 0000000..804253c
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/applications.dart
@@ -0,0 +1,58 @@
+// 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:_fe_analyzer_shared/src/macros/api.dart,
+  package:macro/macro.dart,
+  main.dart],
+ macrosAreApplied,
+ macrosAreAvailable
+*/
+
+import 'package:macro/macro.dart';
+import 'package:macro/macro.dart' as prefix;
+
+/*class: Class:
+ appliedMacros=[
+  Macro1.new,
+  Macro2.named,
+  Macro2.new,
+  Macro3.named],
+ macrosAreApplied
+*/
+@Macro2.named()
+@prefix.Macro2()
+@prefix.Macro3.named()
+@Macro1()
+class Class {
+  /*member: Class.:appliedMacros=[
+    Macro1.named,
+    Macro1.new,
+    Macro2.named,
+    Macro3.new]*/
+  @Macro1.named()
+  @prefix.Macro1()
+  @prefix.Macro2.named()
+  @Macro3()
+  Class();
+
+  /*member: Class.method:appliedMacros=[Macro3.named]*/
+  @Macro3.named()
+  void method() {}
+
+  /*member: Class.field:appliedMacros=[Macro3.new]*/
+  @prefix.Macro3()
+  var field;
+}
+
+/*member: method:appliedMacros=[Macro2.named]*/
+@Macro2.named()
+void method() {}
+
+@Macro3()
+/*member: field:appliedMacros=[Macro3.new]*/
+var field;
+
+main() {}
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
index f4e6484..fc6ae56 100644
--- 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
@@ -10,9 +10,9 @@
 import 'macro_lib.dart';
 import 'apply_lib_dep.dart';
 
-@Macro1()
 /*class: Class:
- appliedMacros=[Macro1],
+ appliedMacros=[Macro1.new],
  macrosAreApplied
 */
+@Macro1()
 class Class extends Super {}
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
index 1c2e947..3aa757c 100644
--- 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
@@ -11,11 +11,11 @@
 import 'package:_fe_analyzer_shared/src/macros/api.dart';
 import 'macro_lib2a.dart';
 
-@Macro2a()
 /*class: Macro2b:
- appliedMacros=[Macro2a],
+ appliedMacros=[Macro2a.new],
  macrosAreApplied
 */
+@Macro2a()
 macro 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
index 9a3839e..455b1b1 100644
--- a/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
@@ -16,11 +16,11 @@
 import 'macro_lib2a.dart';
 import 'macro_lib2b.dart';
 
+/*member: main:appliedMacros=[
+  Macro1.new,
+  Macro2a.new,
+  Macro2b.new]*/
 @Macro1()
 @Macro2a()
 @Macro2b()
-/*member: main:appliedMacros=[
-  Macro1,
-  Macro2a,
-  Macro2b]*/
 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 a830bb3..241eda8 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
@@ -14,25 +14,25 @@
 
 import 'package:macro/macro.dart';
 
+/*member: main:appliedMacros=[Macro1.new]*/
 @Macro1()
-/*member: main:appliedMacros=[Macro1]*/
 void main() {}
 
-@Macro2()
 /*class: Class1:
- appliedMacros=[Macro2],
+ appliedMacros=[Macro2.new],
  macrosAreApplied
 */
+@Macro2()
 class Class1 {
+  /*member: Class1.:appliedMacros=[Macro3.new]*/
   @Macro3()
-  /*member: Class1.:appliedMacros=[Macro3]*/
   Class1();
 
+  /*member: Class1.method:appliedMacros=[
+    Macro1.new,
+    Macro2.new]*/
   @Macro1()
   @Macro2()
-  /*member: Class1.method:appliedMacros=[
-    Macro1,
-    Macro2]*/
   void method() {}
 }
 
@@ -41,8 +41,8 @@
 
 /*class: Class3:macrosAreApplied*/
 class Class3 {
+  /*member: Class3.field:appliedMacros=[Macro3.new]*/
   @Macro3()
-  /*member: Class3.field:appliedMacros=[Macro3]*/
   var field;
 }
 
@@ -51,20 +51,20 @@
   var field;
 }
 
+/*member: field:appliedMacros=[Macro1.new]*/
 @Macro1()
-/*member: field:appliedMacros=[Macro1]*/
 var field;
 
 extension Extension on int {
+  /*member: Extension|field:*/
   @Macro1()
-  /*member: Extension|field:appliedMacros=[Macro1]*/
   static var field;
 
+  /*member: Extension|method:*/
   @Macro2()
-  /*member: Extension|method:appliedMacros=[Macro2]*/
   void method() {}
 
+  /*member: Extension|staticMethod:*/
   @Macro3()
-  /*member: Extension|staticMethod:appliedMacros=[Macro3]*/
   static void staticMethod() {}
 }
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 7c78a01..026aeb3 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
@@ -13,21 +13,21 @@
 
 import 'macro_lib.dart';
 
+/*member: main:appliedMacros=[Macro1.new]*/
 @Macro1()
-/*member: main:appliedMacros=[Macro1]*/
 void main() {}
 
-@Macro2()
 /*class: Class1:
- appliedMacros=[Macro2],
+ appliedMacros=[Macro2.new],
  macrosAreApplied
 */
+@Macro2()
 class Class1 {
+  /*member: Class1.method:appliedMacros=[
+    Macro1.new,
+    Macro2.new]*/
   @Macro1()
   @Macro2()
-  /*member: Class1.method:appliedMacros=[
-    Macro1,
-    Macro2]*/
   void method() {}
 }
 
@@ -36,8 +36,8 @@
 
 /*class: Class3:macrosAreApplied*/
 class Class3 {
+  /*member: Class3.field:appliedMacros=[Macro1.new]*/
   @Macro1()
-  /*member: Class3.field:appliedMacros=[Macro1]*/
   var field;
 }
 
diff --git a/pkg/front_end/test/macros/macro_test.dart b/pkg/front_end/test/macros/macro_test.dart
index 6042432..ee92293 100644
--- a/pkg/front_end/test/macros/macro_test.dart
+++ b/pkg/front_end/test/macros/macro_test.dart
@@ -139,8 +139,13 @@
   void registerMacroApplications(
       Features features, MacroApplications? macroApplications) {
     if (macroApplications != null) {
-      for (Class cls in macroApplications.macros) {
-        features.addElement(Tags.appliedMacros, cls.name);
+      for (MacroApplication application in macroApplications.macros) {
+        String className = application.cls.name;
+        String constructorName = application.constructorName == ''
+            ? 'new'
+            : application.constructorName;
+        features.addElement(
+            Tags.appliedMacros, '${className}.${constructorName}');
       }
     }
   }
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 81e6368..dd3fd3e 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -766,6 +766,7 @@
 masking
 masks
 master
+mature
 mb
 mc
 md
@@ -964,6 +965,7 @@
 pow
 pragma
 pre
+prebuild
 prebuilt
 preexisted
 preexisting