// Copyright (c) 2022, 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: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;
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/summary2/library_builder.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/macro.dart';
import 'package:analyzer/src/summary2/macro_application_error.dart';
import 'package:analyzer/src/summary2/macro_declarations.dart';
import 'package:analyzer/src/summary2/macro_injected_impl.dart' as injected;
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer/src/utilities/extensions/collection.dart';
import 'package:analyzer/src/utilities/extensions/object.dart';
import 'package:collection/collection.dart';
import 'package:macros/macros.dart' as macro;
import 'package:macros/src/executor.dart' as macro;
import 'package:macros/src/executor/exception_impls.dart' as macro;
import 'package:macros/src/executor/introspection_impls.dart' as macro;
import 'package:macros/src/executor/multi_executor.dart';
import 'package:macros/src/executor/remote_instance.dart' as macro;
import 'package:meta/meta.dart';

/// The full list of [macro.ArgumentKind]s for this dart type, with type
/// arguments for [InterfaceType]s, if [includeTop] is `true` also including
/// the [InterfaceType] itself, with [macro.ArgumentKind.nullable] preceding
/// nullable types, depth first.
List<macro.ArgumentKind> _argumentKindsOfType(
  DartType type, {
  bool includeTop = true,
}) {
  return [
    if (type.nullabilitySuffix == NullabilitySuffix.question)
      macro.ArgumentKind.nullable,
    if (includeTop)
      switch (type) {
        DartType(isDartCoreBool: true) => macro.ArgumentKind.bool,
        DartType(isDartCoreDouble: true) => macro.ArgumentKind.double,
        DartType(isDartCoreInt: true) => macro.ArgumentKind.int,
        DartType(isDartCoreNum: true) => macro.ArgumentKind.num,
        DartType(isDartCoreNull: true) => macro.ArgumentKind.nil,
        DartType(isDartCoreObject: true) => macro.ArgumentKind.object,
        DartType(isDartCoreString: true) => macro.ArgumentKind.string,
        DartType(isDartCoreList: true) => macro.ArgumentKind.list,
        DartType(isDartCoreMap: true) => macro.ArgumentKind.map,
        DartType(isDartCoreSet: true) => macro.ArgumentKind.set,
        DynamicType() => macro.ArgumentKind.dynamic,
        // TODO(jakemac): Support type annotations and code objects
        _ => throw UnsupportedError('Unsupported macro type argument $type'),
      },
    if (type is InterfaceType) ...[
      for (var typeArgument in type.typeArguments)
        ..._argumentKindsOfType(typeArgument),
    ]
  ];
}

class ApplicationResult {
  final _MacroApplication application;
  final List<macro.MacroExecutionResult> results;

  ApplicationResult(this.application, this.results);

  MacroTargetElement get targetElement {
    return application.target.element;
  }
}

// TODO(scheglov): The name is deceptive, this is not for a single library.
class LibraryMacroApplier {
  @visibleForTesting
  static bool testThrowExceptionTypes = false;

  @visibleForTesting
  static bool testThrowExceptionDeclarations = false;

  @visibleForTesting
  static bool testThrowExceptionDefinitions = false;

  @visibleForTesting
  static bool testThrowExceptionIntrospection = false;

  final LinkedElementFactory elementFactory;
  final MultiMacroExecutor macroExecutor;
  final bool Function(Uri) isLibraryBeingLinked;
  final DeclarationBuilder declarationBuilder;

  /// The callback to run declarations phase if the type.
  /// We do it out-of-order when the type is introspected.
  final Future<void> Function({
    required ElementImpl? targetElement,
    required OperationPerformanceImpl performance,
  }) runDeclarationsPhase;

  /// The applications that currently run.
  ///
  /// There can be more than one, because during the declarations phase we
  /// can start introspecting another declaration, which runs the declarations
  /// phase for that another declaration.
  final List<_MacroApplication> _runningApplications = [];

  /// The map from a declaration that has declarations phase introspection
  /// cycle, to the cycle exception.
  final Map<MacroTargetElement, _MacroIntrospectionCycleException>
      _elementToIntrospectionCycleException = {};

  late final macro.TypePhaseIntrospector _typesPhaseIntrospector =
      _TypePhaseIntrospector(
    this,
    elementFactory,
    declarationBuilder,
    OperationPerformanceImpl('<typesPhaseIntrospector>'),
  );

  LibraryMacroApplier({
    required this.elementFactory,
    required this.macroExecutor,
    required this.isLibraryBeingLinked,
    required this.declarationBuilder,
    required this.runDeclarationsPhase,
  });

  /// The currently running macro application.
  _MacroApplication? get currentApplication {
    return _runningApplications.lastOrNull;
  }

  Future<void> add({
    required LibraryBuilder libraryBuilder,
    required CompilationUnitElementImpl container,
    required ast.CompilationUnitImpl unit,
  }) async {
    for (var directive in unit.directives.reversed) {
      switch (directive) {
        case ast.LibraryDirectiveImpl():
          await _addAnnotations(
            libraryBuilder: libraryBuilder,
            container: container,
            targetNode: directive,
            targetNodeElement: libraryBuilder.element,
            targetDeclarationKind: macro.DeclarationKind.library,
            annotations: directive.metadata,
          );
        default:
          break;
      }
    }

    for (var declaration in unit.declarations.reversed) {
      switch (declaration) {
        case ast.ClassDeclarationImpl():
          var element = declaration.declaredElement!;
          var declarationElement = element.augmented.firstFragment;
          await _addClassLike(
            libraryBuilder: libraryBuilder,
            container: container,
            targetElement: declarationElement,
            classNode: declaration,
            classDeclarationKind: macro.DeclarationKind.classType,
            classAnnotations: declaration.metadata,
            members: declaration.members,
          );
        case ast.ClassTypeAliasImpl():
          var element = declaration.declaredElement!;
          var declarationElement = element.augmented.firstFragment;
          await _addClassLike(
            libraryBuilder: libraryBuilder,
            container: container,
            targetElement: declarationElement,
            classNode: declaration,
            classDeclarationKind: macro.DeclarationKind.classType,
            classAnnotations: declaration.metadata,
            members: const [],
          );
        case ast.EnumDeclarationImpl():
          var element = declaration.declaredElement!;
          var declarationElement = element.augmented.firstFragment;
          await _addClassLike(
            libraryBuilder: libraryBuilder,
            container: container,
            targetElement: declarationElement,
            classNode: declaration,
            classDeclarationKind: macro.DeclarationKind.enumType,
            classAnnotations: declaration.metadata,
            members: declaration.members,
          );
          for (var constant in declaration.constants.reversed) {
            await _addAnnotations(
              libraryBuilder: libraryBuilder,
              container: container,
              targetNode: constant,
              targetNodeElement: constant.declaredElement,
              targetDeclarationKind: macro.DeclarationKind.enumValue,
              annotations: constant.metadata,
            );
          }
        case ast.ExtensionDeclarationImpl():
          var element = declaration.declaredElement!;
          var declarationElement = element.augmented.firstFragment;
          await _addClassLike(
            libraryBuilder: libraryBuilder,
            container: container,
            targetElement: declarationElement,
            classNode: declaration,
            classDeclarationKind: macro.DeclarationKind.extension,
            classAnnotations: declaration.metadata,
            members: declaration.members,
          );
        case ast.ExtensionTypeDeclarationImpl():
          var element = declaration.declaredElement!;
          var declarationElement = element.augmented.firstFragment;
          await _addClassLike(
            libraryBuilder: libraryBuilder,
            container: container,
            targetElement: declarationElement,
            classNode: declaration,
            classDeclarationKind: macro.DeclarationKind.extensionType,
            classAnnotations: declaration.metadata,
            members: declaration.members,
          );
        case ast.FunctionDeclarationImpl():
          await _addAnnotations(
            libraryBuilder: libraryBuilder,
            container: container,
            targetNode: declaration,
            targetNodeElement: declaration.declaredElement,
            targetDeclarationKind: macro.DeclarationKind.function,
            annotations: declaration.metadata,
          );
        case ast.FunctionTypeAliasImpl():
          // TODO(scheglov): implement it
          break;
        case ast.GenericTypeAliasImpl():
          await _addAnnotations(
            libraryBuilder: libraryBuilder,
            container: container,
            targetNode: declaration,
            targetNodeElement: declaration.declaredElement,
            targetDeclarationKind: macro.DeclarationKind.typeAlias,
            annotations: declaration.metadata,
          );
        case ast.MixinDeclarationImpl():
          var element = declaration.declaredElement!;
          var declarationElement = element.augmented.firstFragment;
          await _addClassLike(
            libraryBuilder: libraryBuilder,
            container: container,
            targetElement: declarationElement,
            classNode: declaration,
            classDeclarationKind: macro.DeclarationKind.mixinType,
            classAnnotations: declaration.metadata,
            members: declaration.members,
          );
        case ast.TopLevelVariableDeclarationImpl():
          var variables = declaration.variables.variables;
          for (var variable in variables.reversed) {
            await _addAnnotations(
              libraryBuilder: libraryBuilder,
              container: container,
              targetNode: variable,
              targetNodeElement: variable.declaredElement,
              targetDeclarationKind: macro.DeclarationKind.variable,
              annotations: declaration.metadata,
            );
          }
      }
    }
  }

  /// Builds the augmentation library code for [results].
  String? buildAugmentationLibraryCode(
    Uri augmentedLibraryUri,
    List<macro.MacroExecutionResult> results,
  ) {
    if (results.isEmpty) {
      return null;
    }

    return macroExecutor.buildAugmentationLibrary(
      augmentedLibraryUri,
      results,
      declarationBuilder.typeDeclarationOf,
      declarationBuilder.resolveIdentifier,
      declarationBuilder.inferOmittedType,
    );
  }

  void disposeMacroApplications({
    required LibraryBuilder libraryBuilder,
  }) {
    for (var application in libraryBuilder._applications) {
      var instance = application.instance;
      if (instance is macro.MacroInstanceIdentifier) {
        macroExecutor.disposeMacro(instance);
      }
    }
  }

  Future<ApplicationResult?> executeDeclarationsPhase({
    required LibraryBuilder libraryBuilder,
    required ElementImpl? targetElement,
    required OperationPerformanceImpl performance,
  }) async {
    if (targetElement != null) {
      for (var i = 0; i < _runningApplications.length; i++) {
        var running = _runningApplications[i];
        if (running.target.element == targetElement) {
          var applications = _runningApplications.sublist(i);
          var exception = _MacroIntrospectionCycleException(
            'Declarations phase introspection cycle.',
            applications: applications,
          );

          // Mark all applications as having introspection cycle.
          // So, every introspection of these elements will throw.
          for (var application in applications) {
            var element = application.target.element;
            _elementToIntrospectionCycleException[element] = exception;
          }

          throw exception;
        }
      }
    }

    var application = _nextForDeclarationsPhase(
      libraryBuilder: libraryBuilder,
      targetElement: targetElement,
    );
    if (application == null) {
      return null;
    }

    _runningApplications.add(application);
    var results = <macro.MacroExecutionResult>[];

    await _runWithCatchingExceptions(
      () async {
        var target = _buildTarget(application.target.node);

        var introspector = _DeclarationPhaseIntrospector(
          this,
          elementFactory,
          declarationBuilder,
          performance,
          libraryBuilder.element.typeSystem,
        );

        var instance = application.instance;
        macro.MacroExecutionResult result;
        if (instance is macro.MacroInstanceIdentifier) {
          result = await macroExecutor.executeDeclarationsPhase(
            instance,
            target,
            introspector,
          );
        } else if (instance is injected.RunningMacro) {
          result = await instance.executeDeclarationsPhase(
            target,
            introspector,
          );
        } else {
          throw UnimplementedError('$instance');
        }

        _addDiagnostics(application, result);
        if (result.isNotEmpty) {
          results.add(result);
        }

        if (testThrowExceptionDeclarations) {
          throw 'Intentional exception';
        }
      },
      targetElement: application.target.element,
      annotationIndex: application.annotationIndex,
    );

    _runningApplications.removeLast();
    return ApplicationResult(application, results);
  }

  Future<ApplicationResult?> executeDefinitionsPhase({
    required LibraryBuilder libraryBuilder,
    required OperationPerformanceImpl performance,
  }) async {
    var application = _nextForDefinitionsPhase(
      libraryBuilder: libraryBuilder,
    );
    if (application == null) {
      return null;
    }

    _runningApplications.add(application);
    var results = <macro.MacroExecutionResult>[];

    await _runWithCatchingExceptions(
      () async {
        var target = _buildTarget(application.target.node);

        var introspector = _DefinitionPhaseIntrospector(
          this,
          elementFactory,
          declarationBuilder,
          performance,
          application.target.library.element.typeSystem,
        );

        macro.MacroExecutionResult result;
        var instance = application.instance;
        if (instance is macro.MacroInstanceIdentifier) {
          result = await macroExecutor.executeDefinitionsPhase(
            instance,
            target,
            introspector,
          );
        } else if (instance is injected.RunningMacro) {
          result = await instance.executeDefinitionsPhase(
            target,
            introspector,
          );
        } else {
          throw UnimplementedError('$instance');
        }

        _addDiagnostics(application, result);
        if (result.isNotEmpty) {
          results.add(result);
        }

        if (testThrowExceptionDefinitions) {
          throw 'Intentional exception';
        }
      },
      targetElement: application.target.element,
      annotationIndex: application.annotationIndex,
    );

    _runningApplications.removeLast();
    return ApplicationResult(application, results);
  }

  Future<ApplicationResult?> executeTypesPhase({
    required LibraryBuilder libraryBuilder,
  }) async {
    var application = _nextForTypesPhase(
      libraryBuilder: libraryBuilder,
    );
    if (application == null) {
      return null;
    }

    _runningApplications.add(application);
    var results = <macro.MacroExecutionResult>[];

    await _runWithCatchingExceptions(
      () async {
        var target = _buildTarget(application.target.node);

        macro.MacroExecutionResult result;
        var instance = application.instance;

        if (instance is macro.MacroInstanceIdentifier) {
          result = await macroExecutor.executeTypesPhase(
            instance,
            target,
            _typesPhaseIntrospector,
          );
        } else if (instance is injected.RunningMacro) {
          result = await instance.executeTypesPhase(
            target,
            _typesPhaseIntrospector,
          );
        } else {
          throw UnimplementedError('$instance');
        }

        _addDiagnostics(application, result);
        if (result.isNotEmpty) {
          results.add(result);
        }

        if (testThrowExceptionTypes) {
          throw 'Intentional exception';
        }
      },
      targetElement: application.target.element,
      annotationIndex: application.annotationIndex,
    );

    _runningApplications.removeLast();
    return ApplicationResult(application, results);
  }

  Future<void> _addAnnotations({
    required LibraryBuilder libraryBuilder,
    required CompilationUnitElementImpl container,
    required ast.AstNode targetNode,
    required Element? targetNodeElement,
    required macro.DeclarationKind targetDeclarationKind,
    required List<ast.Annotation> annotations,
  }) async {
    if (targetNode is ast.FieldDeclaration) {
      for (var field in targetNode.fields.variables) {
        await _addAnnotations(
          libraryBuilder: libraryBuilder,
          container: container,
          targetNode: field,
          targetNodeElement: field.declaredElement,
          targetDeclarationKind: macro.DeclarationKind.field,
          annotations: annotations,
        );
      }
      return;
    }

    var targetElement = targetNodeElement.ifTypeOrNull<MacroTargetElement>();
    if (targetElement == null) {
      return;
    }

    var macroTarget = _MacroTarget(
      library: libraryBuilder,
      node: targetNode,
      element: targetElement,
    );

    if (injected.macroImplementation == null) {
      await _addAnnotationsDefault(
        libraryBuilder: libraryBuilder,
        container: container,
        annotations: annotations,
        macroTarget: macroTarget,
        targetDeclarationKind: targetDeclarationKind,
      );
    } else {
      await _addAnnotationsInjected(
        libraryBuilder: libraryBuilder,
        container: container,
        annotations: annotations,
        macroTarget: macroTarget,
        targetDeclarationKind: targetDeclarationKind,
      );
    }
  }

  Future<void> _addAnnotationsDefault({
    required LibraryBuilder libraryBuilder,
    required CompilationUnitElementImpl container,
    required List<ast.Annotation> annotations,
    required _MacroTarget macroTarget,
    required macro.DeclarationKind targetDeclarationKind,
  }) async {
    for (var (annotationIndex, annotation) in annotations.indexed) {
      var importedMacro = _importedMacro(
        container: container,
        annotation: annotation,
      );
      if (importedMacro == null) {
        continue;
      }

      var constructorElement = importedMacro.constructorElement;
      if (constructorElement == null) {
        continue;
      }

      var instance = await _runWithCatchingExceptions(
        () async {
          var arguments = _buildArguments(
            annotationIndex: annotationIndex,
            constructor: constructorElement,
            node: importedMacro.arguments,
          );

          return await importedMacro.bundleExecutor.instantiate(
            libraryUri: importedMacro.macroLibrary.source.uri,
            className: importedMacro.macroClass.name,
            constructorName: importedMacro.constructorName ?? '',
            arguments: arguments,
          );
        },
        targetElement: macroTarget.element,
        annotationIndex: annotationIndex,
      );
      if (instance == null) {
        continue;
      }

      var phasesToExecute = macro.Phase.values.where((phase) {
        return instance.shouldExecute(targetDeclarationKind, phase);
      }).toSet();

      if (!instance.supportsDeclarationKind(targetDeclarationKind)) {
        macroTarget.element.addMacroDiagnostic(
          InvalidMacroTargetDiagnostic(
            annotationIndex: annotationIndex,
            supportedKinds: macro.DeclarationKind.values
                .where(instance.supportsDeclarationKind)
                .map((e) => e.name)
                .toList(),
          ),
        );
        return;
      }

      var application = _MacroApplication(
        target: macroTarget,
        annotationIndex: annotationIndex,
        annotationNode: annotation,
        instance: instance,
        phasesToExecute: phasesToExecute,
      );

      libraryBuilder._applications.add(application);
    }
  }

  Future<void> _addAnnotationsInjected({
    required LibraryBuilder libraryBuilder,
    required CompilationUnitElementImpl container,
    required List<ast.Annotation> annotations,
    required _MacroTarget macroTarget,
    required macro.DeclarationKind targetDeclarationKind,
  }) async {
    var macroPackageConfigs = injected.macroImplementation!.packageConfigs;
    for (var (annotationIndex, annotation) in annotations.indexed) {
      var macroClassAndConstructorName = _lookupMacroClassAndConstructorName(
        container: container,
        annotation: annotation,
      );
      if (macroClassAndConstructorName == null) continue;
      var macroUri = macroClassAndConstructorName.$1.librarySource.uri;
      var macroName = annotation.name.name;
      if (!macroPackageConfigs.isMacro(
          macroClassAndConstructorName.$1.librarySource.uri,
          annotation.name.name)) {
        continue;
      }

      var instance =
          injected.macroImplementation!.runner.run(macroUri, macroName);
      var application = _MacroApplication(
        target: macroTarget,
        annotationIndex: annotationIndex,
        annotationNode: annotation,
        instance: instance,
        phasesToExecute: {
          macro.Phase.types,
          macro.Phase.declarations,
          macro.Phase.definitions
        },
      );

      libraryBuilder._applications.add(application);
    }
  }

  Future<void> _addClassLike({
    required LibraryBuilder libraryBuilder,
    required CompilationUnitElementImpl container,
    required MacroTargetElement targetElement,
    required ast.Declaration classNode,
    required macro.DeclarationKind classDeclarationKind,
    required List<ast.Annotation> classAnnotations,
    required List<ast.ClassMember> members,
  }) async {
    await _addAnnotations(
      libraryBuilder: libraryBuilder,
      container: container,
      targetNode: classNode,
      targetNodeElement: classNode.declaredElement,
      targetDeclarationKind: classDeclarationKind,
      annotations: classAnnotations,
    );

    for (var member in members.reversed) {
      var memberDeclarationKind = switch (member) {
        ast.ConstructorDeclaration() => macro.DeclarationKind.constructor,
        ast.FieldDeclaration() => macro.DeclarationKind.field,
        ast.MethodDeclaration() => macro.DeclarationKind.method,
      };
      await _addAnnotations(
        libraryBuilder: libraryBuilder,
        container: container,
        targetNode: member,
        targetNodeElement: member.declaredElement,
        targetDeclarationKind: memberDeclarationKind,
        annotations: member.metadata,
      );
    }
  }

  void _addDiagnostics(
    _MacroApplication application,
    macro.MacroExecutionResult result,
  ) {
    MacroDiagnosticMessage convertMessage(
      macro.DiagnosticMessage message,
    ) {
      MacroDiagnosticTarget target;
      switch (message.target) {
        case macro.DeclarationDiagnosticTarget macroTarget:
          var element = (macroTarget.declaration as HasElement).element;
          target = ElementMacroDiagnosticTarget(element: element);
        case macro.TypeAnnotationDiagnosticTarget macroTarget:
          target = _typeAnnotationTarget(application, macroTarget);
        case macro.MetadataAnnotationDiagnosticTarget macroTarget:
          var annotation =
              macroTarget.metadataAnnotation as MetadataAnnotationImpl;
          target = ElementAnnotationMacroDiagnosticTarget(
            element: annotation.element,
            annotationIndex: annotation.annotationIndex,
          );
        case null:
          target = ApplicationMacroDiagnosticTarget(
            annotationIndex: application.annotationIndex,
          );
      }

      return MacroDiagnosticMessage(
        target: target,
        message: message.message,
      );
    }

    for (var diagnostic in result.diagnostics) {
      application.target.element.addMacroDiagnostic(
        MacroDiagnostic(
          severity: diagnostic.severity,
          message: convertMessage(diagnostic.message),
          contextMessages:
              diagnostic.contextMessages.map(convertMessage).toList(),
          correctionMessage: diagnostic.correctionMessage,
        ),
      );
    }

    bool addIntrospectionCycle(macro.MacroException? exception) {
      if (exception is! _MacroIntrospectionCycleException) {
        return false;
      }

      var introspectedElement = application.lastIntrospectedElement;
      if (introspectedElement == null) {
        return false;
      }

      var applications = exception.applications;
      var components = applications.map((application) {
        return DeclarationsIntrospectionCycleComponent(
          element: application.target.element,
          annotationIndex: application.annotationIndex,
          introspectedElement: application.lastIntrospectedElement!,
        );
      }).toList();

      // Report only for this application.
      // Introspections of every cycle component will report it too.
      // Macro implementations can catch and ignore introspection exceptions.
      application.target.element.addMacroDiagnostic(
        DeclarationsIntrospectionCycleDiagnostic(
          annotationIndex: application.annotationIndex,
          introspectedElement: introspectedElement,
          components: components,
        ),
      );
      return true;
    }

    if (result.exception case var exception?) {
      var reported = addIntrospectionCycle(exception);
      if (!reported) {
        application.target.element.addMacroDiagnostic(
          ExceptionMacroDiagnostic(
            annotationIndex: application.annotationIndex,
            message: exception.message,
            stackTrace: exception.stackTrace ?? '<null>',
          ),
        );
      }
    }
  }

  macro.MacroTarget _buildTarget(ast.AstNode node) {
    return declarationBuilder.buildTarget(node);
  }

  /// If [annotation] references a macro, invokes the right callback.
  _AnnotationMacro? _importedMacro({
    required CompilationUnitElementImpl container,
    required ast.Annotation annotation,
  }) {
    var arguments = annotation.arguments;
    if (arguments == null) {
      return null;
    }

    var macroClassAndConstructorName = _lookupMacroClassAndConstructorName(
      container: container,
      annotation: annotation,
    );
    if (macroClassAndConstructorName == null) return null;
    var macroClass = macroClassAndConstructorName.$1;
    var macroLibrary = macroClass.library;
    var bundleExecutor = macroLibrary.bundleMacroExecutor;
    if (bundleExecutor == null) {
      return null;
    }

    if (!macroClass.isMacro) return null;

    return _AnnotationMacro(
      macroLibrary: macroLibrary,
      bundleExecutor: bundleExecutor,
      macroClass: macroClass,
      constructorName: macroClassAndConstructorName.$2,
      arguments: arguments,
    );
  }

  (ClassElementImpl, String?)? _lookupMacroClassAndConstructorName({
    required CompilationUnitElementImpl container,
    required ast.Annotation annotation,
  }) {
    String? prefix;
    String name;
    String? constructorName;
    var nameNode = annotation.name;
    if (nameNode is ast.SimpleIdentifier) {
      prefix = null;
      name = nameNode.name;
      constructorName = annotation.constructorName?.name;
    } else if (nameNode is ast.PrefixedIdentifier) {
      var importPrefixCandidate = nameNode.prefix.name;
      var hasImportPrefix = container.libraryImports.any(
          (import) => import.prefix?.element.name == importPrefixCandidate);
      if (hasImportPrefix) {
        prefix = importPrefixCandidate;
        name = nameNode.identifier.name;
        constructorName = annotation.constructorName?.name;
      } else {
        prefix = null;
        name = nameNode.prefix.name;
        constructorName = nameNode.identifier.name;
      }
    } else {
      throw StateError('${nameNode.runtimeType} $nameNode');
    }

    for (var import in container.libraryImports) {
      if (import.prefix?.element.name != prefix) {
        continue;
      }

      var importedLibrary = import.importedLibrary;
      if (importedLibrary == null) {
        continue;
      }

      // Skip if a library that is being linked.
      var importedUri = importedLibrary.source.uri;
      if (isLibraryBeingLinked(importedUri)) {
        continue;
      }

      var macroClass = importedLibrary.exportNamespace.get(name);
      if (macroClass is ClassElementImpl) {
        return (macroClass, constructorName);
      }
    }
    return null;
  }

  _MacroApplication<Object>? _nextForDeclarationsPhase({
    required LibraryBuilder libraryBuilder,
    required Element? targetElement,
  }) {
    var applications = libraryBuilder._applications;
    for (var i = applications.length - 1; i >= 0; i--) {
      var application = applications[i];
      if (targetElement != null) {
        var applicationElement = application.target.element;
        if (!identical(applicationElement, targetElement) &&
            !identical(applicationElement.enclosingElement3, targetElement)) {
          continue;
        }
      }
      if (application.phasesToExecute.remove(macro.Phase.declarations)) {
        return application;
      }
    }

    return null;
  }

  _MacroApplication<Object>? _nextForDefinitionsPhase({
    required LibraryBuilder libraryBuilder,
  }) {
    var applications = libraryBuilder._applications;
    for (var i = applications.length - 1; i >= 0; i--) {
      var application = applications[i];
      if (application.phasesToExecute.remove(macro.Phase.definitions)) {
        return application;
      }
    }
    return null;
  }

  _MacroApplication<Object>? _nextForTypesPhase({
    required LibraryBuilder libraryBuilder,
  }) {
    var applications = libraryBuilder._applications;
    for (var i = applications.length - 1; i >= 0; i--) {
      var application = applications[i];
      if (application.phasesToExecute.remove(macro.Phase.types)) {
        return application;
      }
    }
    return null;
  }

  MacroDiagnosticTarget _typeAnnotationTarget(
    _MacroApplication application,
    macro.TypeAnnotationDiagnosticTarget macroTarget,
  ) {
    switch (macroTarget.typeAnnotation) {
      case TypeAnnotationWithLocation typeAnnotation:
        return TypeAnnotationMacroDiagnosticTarget(
          location: typeAnnotation.location,
        );
    }

    // We don't know anything better.
    return ApplicationMacroDiagnosticTarget(
      annotationIndex: application.annotationIndex,
    );
  }

  static macro.Arguments _buildArguments({
    required int annotationIndex,
    required ConstructorElement constructor,
    required ast.ArgumentList node,
  }) {
    var allParameters = constructor.parameters;
    var namedParameters = allParameters
        .where((e) => e.isNamed)
        .map((e) => MapEntry(e.name, e))
        .mapFromEntries;
    var positionalParameters =
        allParameters.where((e) => e.isPositional).toList();
    var positionalParameterIndex = 0;

    var positional = <macro.Argument>[];
    var named = <String, macro.Argument>{};
    for (var i = 0; i < node.arguments.length; ++i) {
      ParameterElement? parameter;
      String? namedArgumentName;
      ast.Expression expressionToEvaluate;
      var argument = node.arguments[i];
      if (argument is ast.NamedExpression) {
        namedArgumentName = argument.name.label.name;
        expressionToEvaluate = argument.expression;
        parameter = namedParameters.remove(namedArgumentName);
      } else {
        expressionToEvaluate = argument;
        parameter = positionalParameters.elementAtOrNull(
          positionalParameterIndex++,
        );
      }

      var contextType = parameter?.type ?? DynamicTypeImpl.instance;
      var evaluation = _ArgumentEvaluation(
        annotationIndex: annotationIndex,
        argumentIndex: i,
      );
      var value = evaluation.evaluate(contextType, expressionToEvaluate);

      if (namedArgumentName != null) {
        named[namedArgumentName] = value;
      } else {
        positional.add(value);
      }
    }
    return macro.Arguments(positional, named);
  }

  /// Run the [body], report [AnalyzerMacroDiagnostic]s to [onDiagnostic].
  static Future<T?> _runWithCatchingExceptions<T>(
    Future<T> Function() body, {
    required MacroTargetElement targetElement,
    required int annotationIndex,
  }) async {
    try {
      return await body();
    } on AnalyzerMacroDiagnostic catch (e) {
      targetElement.addMacroDiagnostic(e);
    } on macro.MacroException catch (e) {
      targetElement.addMacroDiagnostic(
        ExceptionMacroDiagnostic(
          annotationIndex: annotationIndex,
          message: e.message,
          stackTrace: e.stackTrace ?? '<null>',
        ),
      );
    } catch (e, stackTrace) {
      targetElement.addMacroDiagnostic(
        ExceptionMacroDiagnostic(
          annotationIndex: annotationIndex,
          message: '$e',
          stackTrace: '$stackTrace',
        ),
      );
    }
    return null;
  }
}

/// This mixin is added to [LibraryBuilder] to make it a container with
/// macro applications, but at the same time don't expose internals of
/// [_MacroApplication].
mixin MacroApplicationsContainer {
  /// 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<Object>> _applications = [];
}

/// Facts about applying macros in a library.
class MacroProcessing {
  bool hasAnyIntrospection = false;
}

class _AnnotationMacro {
  final LibraryElementImpl macroLibrary;
  final BundleMacroExecutor bundleExecutor;
  final ClassElementImpl macroClass;
  final String? constructorName;
  final ast.ArgumentList arguments;

  _AnnotationMacro({
    required this.macroLibrary,
    required this.bundleExecutor,
    required this.macroClass,
    required this.constructorName,
    required this.arguments,
  });

  ConstructorElement? get constructorElement {
    return macroClass.getNamedConstructor(constructorName ?? '');
  }
}

/// Helper class for evaluating arguments for a single constructor based
/// macro application.
class _ArgumentEvaluation {
  final int annotationIndex;
  final int argumentIndex;

  _ArgumentEvaluation({
    required this.annotationIndex,
    required this.argumentIndex,
  });

  macro.Argument evaluate(DartType contextType, ast.Expression node) {
    if (node is ast.AdjacentStrings) {
      return macro.StringArgument(node.strings
          .map((e) => evaluate(contextType, e))
          .map((arg) => arg.value)
          .join());
    } else if (node is ast.BooleanLiteral) {
      return macro.BoolArgument(node.value);
    } else if (node is ast.DoubleLiteral) {
      return macro.DoubleArgument(node.value);
    } else if (node is ast.IntegerLiteral) {
      return macro.IntArgument(node.value!);
    } else if (node is ast.ListLiteral) {
      return _listLiteral(contextType, node);
    } else if (node is ast.NullLiteral) {
      return macro.NullArgument();
    } else if (node is ast.PrefixExpression &&
        node.operator.type == TokenType.MINUS) {
      var operandValue = evaluate(contextType, node.operand);
      if (operandValue is macro.DoubleArgument) {
        return macro.DoubleArgument(-operandValue.value);
      } else if (operandValue is macro.IntArgument) {
        return macro.IntArgument(-operandValue.value);
      }
    } else if (node is ast.SetOrMapLiteral) {
      return _setOrMapLiteral(contextType, node);
    } else if (node is ast.SimpleStringLiteral) {
      return macro.StringArgument(node.value);
    }
    _throwError(node, 'Not supported: ${node.runtimeType}');
  }

  macro.ListArgument _listLiteral(
    DartType contextType,
    ast.ListLiteral node,
  ) {
    DartType elementType;
    switch (contextType) {
      case InterfaceType(isDartCoreList: true):
        elementType = contextType.typeArguments[0];
      default:
        _throwError(node, 'Expected context type List');
    }

    var typeArguments = _argumentKindsOfType(
      contextType,
      includeTop: false,
    );

    return macro.ListArgument(
      node.elements
          .cast<ast.Expression>()
          .map((e) => evaluate(elementType, e))
          .toList(),
      typeArguments,
    );
  }

  macro.Argument _setOrMapLiteral(
    DartType contextType,
    ast.SetOrMapLiteral node,
  ) {
    var typeArguments = _argumentKindsOfType(
      contextType,
      includeTop: false,
    );

    switch (contextType) {
      case InterfaceType(isDartCoreMap: true):
        var keyType = contextType.typeArguments[0];
        var valueType = contextType.typeArguments[1];
        var result = <macro.Argument, macro.Argument>{};
        for (var element in node.elements) {
          if (element is! ast.MapLiteralEntry) {
            _throwError(element, 'MapLiteralEntry expected');
          }
          var key = evaluate(keyType, element.key);
          var value = evaluate(valueType, element.value);
          result[key] = value;
        }
        return macro.MapArgument(result, typeArguments);
      case InterfaceType(isDartCoreSet: true):
        var elementType = contextType.typeArguments[0];
        var result = <macro.Argument>[];
        for (var element in node.elements) {
          if (element is! ast.Expression) {
            _throwError(element, 'Expression expected');
          }
          var value = evaluate(elementType, element);
          result.add(value);
        }
        return macro.SetArgument(result, typeArguments);
      default:
        _throwError(node, 'Expected context type Map or Set');
    }
  }

  Never _throwError(ast.AstNode node, String message) {
    throw ArgumentMacroDiagnostic(
      annotationIndex: annotationIndex,
      argumentIndex: argumentIndex,
      message: message,
    );
  }
}

class _DeclarationPhaseIntrospector extends _TypePhaseIntrospector
    implements macro.DeclarationPhaseIntrospector {
  final TypeSystemImpl typeSystem;

  _DeclarationPhaseIntrospector(
    super.applier,
    super.elementFactory,
    super.declarationBuilder,
    super.performance,
    this.typeSystem,
  );

  @override
  Future<List<macro.ConstructorDeclaration>> constructorsOf(
    covariant macro.TypeDeclaration type,
  ) async {
    performance.getDataInt('constructorsOf').increment();

    var element = (type as HasElement).element;
    await _runDeclarationsPhase(element);

    macroProcessing?.hasAnyIntrospection = true;
    if (element case InterfaceElement(:var augmented)) {
      return augmented.constructors
          .map((e) => e.declaration as ConstructorElementImpl)
          .map(declarationBuilder.declarationOfElement)
          .whereType<macro.ConstructorDeclaration>()
          .toList();
    }
    return [];
  }

  @override
  Future<List<macro.FieldDeclaration>> fieldsOf(
    macro.TypeDeclaration type,
  ) async {
    if (LibraryMacroApplier.testThrowExceptionIntrospection) {
      throw 'Intentional exception';
    }

    var element = (type as HasElement).element;
    await _runDeclarationsPhase(element);

    macroProcessing?.hasAnyIntrospection = true;
    if (element case InstanceElement(:var augmented)) {
      return augmented.fields
          .whereNot((e) => e.isSynthetic)
          .map((e) => e.declaration as FieldElementImpl)
          .map(declarationBuilder.declarationOfElement)
          .whereType<macro.FieldDeclaration>()
          .toList();
    }
    // TODO(scheglov): can we test this?
    throw StateError('Unexpected: ${type.runtimeType}');
  }

  @override
  Future<List<macro.MethodDeclaration>> methodsOf(
    macro.TypeDeclaration type,
  ) async {
    performance.getDataInt('methodsOf').increment();

    var element = (type as HasElement).element;
    await _runDeclarationsPhase(element);

    macroProcessing?.hasAnyIntrospection = true;
    if (element case InstanceElement(:var augmented)) {
      return [
        ...augmented.accessors.whereNot((e) => e.isSynthetic),
        ...augmented.methods,
      ]
          .map((e) => e.declaration as ExecutableElementImpl)
          .map(declarationBuilder.declarationOfElement)
          .whereType<macro.MethodDeclaration>()
          .toList();
    }
    // TODO(scheglov): can we test this?
    throw StateError('Unexpected: ${type.runtimeType}');
  }

  @override
  Future<macro.StaticType> resolve(macro.TypeAnnotationCode typeCode) async {
    performance.getDataInt('resolve').increment();
    macroProcessing?.hasAnyIntrospection = true;
    var type = declarationBuilder.resolveType(typeCode);
    return _dartTypeToStaticType(type);
  }

  @override
  Future<macro.TypeDeclaration> typeDeclarationOf(
    macro.Identifier identifier,
  ) async {
    performance.getDataInt('typeDeclarationOf').increment();
    macroProcessing?.hasAnyIntrospection = true;
    return declarationBuilder.typeDeclarationOf(identifier);
  }

  @override
  Future<List<macro.TypeDeclaration>> typesOf(
    covariant LibraryImplFromElement library,
  ) async {
    macroProcessing?.hasAnyIntrospection = true;
    return library.element.topLevelElements
        .map((e) => declarationBuilder.declarationOfElement(e))
        .whereType<macro.TypeDeclaration>()
        .toList();
  }

  @override
  Future<List<macro.EnumValueDeclaration>> valuesOf(
    covariant macro.EnumDeclaration type,
  ) async {
    var element = (type as HasElement).element;
    await _runDeclarationsPhase(element);

    element as EnumElementImpl;
    macroProcessing?.hasAnyIntrospection = true;

    // TODO(scheglov): use augmented
    return element.constants
        .map(declarationBuilder.declarationOfElement)
        .whereType<macro.EnumValueDeclaration>()
        .toList();
  }

  macro.StaticTypeImpl _dartTypeToStaticType(DartType type) {
    if (type is InterfaceType) {
      var element = type.element;
      var declaration = declarationBuilder.declarationOfElement(element);

      return _InterfaceTypeImpl(
        macro.RemoteInstance.uniqueId,
        typeSystem: typeSystem,
        introspector: this,
        type: type,
        declaration: declaration as macro.ParameterizedTypeDeclarationImpl,
        typeArguments: [
          for (final type in type.typeArguments) _dartTypeToStaticType(type),
        ],
      );
    } else {
      return _StaticTypeImpl(
        macro.RemoteInstance.uniqueId,
        typeSystem: typeSystem,
        introspector: this,
        type: type,
      );
    }
  }

  Future<void> _runDeclarationsPhase(ElementImpl element) async {
    // Don't run for the current element.
    var current = applier._runningApplications.lastOrNull;
    if (current?.target.element == element) {
      return;
    }

    current?.lastIntrospectedElement = element;
    await applier.runDeclarationsPhase(
      targetElement: element,
      performance: performance,
    );

    // We might have detected a cycle for this target element.
    // Either just now, or before.
    var exception = applier._elementToIntrospectionCycleException[element];
    if (exception != null) {
      throw exception;
    }
  }
}

class _DefinitionPhaseIntrospector extends _DeclarationPhaseIntrospector
    implements macro.DefinitionPhaseIntrospector {
  _DefinitionPhaseIntrospector(
    super.applier,
    super.elementFactory,
    super.declarationBuilder,
    super.performance,
    super.typeSystem,
  );

  @override
  Future<macro.Declaration> declarationOf(
    covariant macro.Identifier identifier,
  ) async {
    return declarationBuilder.declarationOf(identifier);
  }

  @override
  Future<macro.TypeAnnotation> inferType(
    covariant macro.OmittedTypeAnnotation omittedType,
  ) async {
    return declarationBuilder.inferOmittedType(omittedType);
  }

  @override
  Future<List<macro.Declaration>> topLevelDeclarationsOf(
    covariant LibraryImplFromElement library,
  ) async {
    macroProcessing?.hasAnyIntrospection = true;
    return library.element.topLevelElements
        .whereNot((e) => e.isSynthetic)
        .map((e) => declarationBuilder.declarationOfElement(e))
        .whereType<macro.Declaration>()
        .toList();
  }
}

class _InterfaceTypeImpl extends _StaticTypeImpl
    implements macro.NamedStaticTypeImpl {
  @override
  final macro.ParameterizedTypeDeclarationImpl declaration;

  @override
  final List<macro.StaticTypeImpl> typeArguments;

  _InterfaceTypeImpl(
    super.id, {
    required super.typeSystem,
    required super.introspector,
    required InterfaceType super.type,
    required this.declaration,
    required this.typeArguments,
  });
}

class _MacroApplication<I> {
  final _MacroTarget target;
  final int annotationIndex;
  final ast.Annotation annotationNode;
  final I instance;
  final Set<macro.Phase> phasesToExecute;
  ElementImpl? lastIntrospectedElement;

  _MacroApplication({
    required this.target,
    required this.annotationIndex,
    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);
  }
}

final class _MacroIntrospectionCycleException
    extends macro.MacroIntrospectionCycleExceptionImpl {
  final List<_MacroApplication> applications;

  _MacroIntrospectionCycleException(
    super.message, {
    required this.applications,
  });
}

class _MacroTarget {
  final LibraryBuilder library;
  final ast.AstNode node;
  final MacroTargetElement element;

  _MacroTarget({
    required this.library,
    required this.node,
    required this.element,
  });
}

class _StaticTypeImpl extends macro.StaticTypeImpl {
  final TypeSystemImpl typeSystem;
  final _DeclarationPhaseIntrospector introspector;
  final DartType type;

  _StaticTypeImpl(
    super.id, {
    required this.typeSystem,
    required this.introspector,
    required this.type,
  });

  @override
  Future<macro.NamedStaticType?> asInstanceOf(
      macro.TypeDeclaration declaration) {
    InterfaceType? result;

    if (declaration case HasElement(:var element)) {
      if (element is InterfaceElementImpl) {
        result = type.asInstanceOf(element);
      }
    }

    return Future.value(switch (result) {
      var type? =>
        introspector._dartTypeToStaticType(type) as _InterfaceTypeImpl,
      _ => null,
    });
  }

  @override
  Future<bool> isExactly(_StaticTypeImpl other) {
    var result = type == other.type;
    return Future.value(result);
  }

  @override
  Future<bool> isSubtypeOf(_StaticTypeImpl other) {
    var result = typeSystem.isSubtypeOf(type, other.type);
    return Future.value(result);
  }
}

class _TypePhaseIntrospector implements macro.TypePhaseIntrospector {
  final LibraryMacroApplier applier;
  final LinkedElementFactory elementFactory;
  final DeclarationBuilder declarationBuilder;
  final OperationPerformanceImpl performance;

  _TypePhaseIntrospector(
    this.applier,
    this.elementFactory,
    this.declarationBuilder,
    this.performance,
  );

  MacroProcessing? get macroProcessing {
    return applier.currentApplication?.target.library.macroProcessing;
  }

  @override
  Future<macro.Identifier> resolveIdentifier(Uri library, String name) async {
    var libraryElement = elementFactory.libraryOfUri2(library);
    macroProcessing?.hasAnyIntrospection = true;

    var element = libraryElement.exportNamespace.get(name);
    if (element is PropertyAccessorElement && element.isSynthetic) {
      element = element.variable2;
    }

    if (element == null) {
      throw macro.MacroImplementationExceptionImpl(
        [
          'Unresolved identifier.',
          'library: $library',
          'name: $name',
        ].join('\n'),
        stackTrace: StackTrace.current.toString(),
      );
    }

    return declarationBuilder.fromElement.identifier(element);
  }
}

extension on macro.MacroExecutionResult {
  bool get isNotEmpty =>
      enumValueAugmentations.isNotEmpty ||
      extendsTypeAugmentations.isNotEmpty ||
      interfaceAugmentations.isNotEmpty ||
      libraryAugmentations.isNotEmpty ||
      mixinAugmentations.isNotEmpty ||
      typeAugmentations.isNotEmpty;
}
