// 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: await instance.phasesToExecute,
      );

      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;
}
