// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:_fe_analyzer_shared/src/macros/api.dart' as macro;
import 'package:_fe_analyzer_shared/src/macros/executor.dart' as macro;
import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart'
    as macro;
import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart'
    as macro;
import 'package:kernel/ast.dart' show DartType;
import 'package:kernel/src/types.dart';
import 'package:kernel/type_environment.dart' show SubtypeCheckMode;

import '../../base/common.dart';
import '../builder/builder.dart';
import '../builder/class_builder.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/library_builder.dart';
import '../builder/member_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/nullability_builder.dart';
import '../builder/type_alias_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_declaration_builder.dart';
import '../identifiers.dart';
import '../source/source_class_builder.dart';
import '../source/source_constructor_builder.dart';
import '../source/source_factory_builder.dart';
import '../source/source_field_builder.dart';
import '../source/source_library_builder.dart';
import '../source/source_loader.dart';
import '../source/source_procedure_builder.dart';
import 'hierarchy/hierarchy_builder.dart';
import 'hierarchy/hierarchy_node.dart';

bool enableMacros = false;

/// Enables macros whether the Macro class actually exists in the transitive
/// deps or not. This allows for easier experimentation.
///
/// TODO: Remove this once it is no longer necessary.
bool forceEnableMacros = false;

const String augmentationScheme = 'org-dartlang-augmentation';

final Uri macroLibraryUri =
    Uri.parse('package:_fe_analyzer_shared/src/macros/api.dart');
const String macroClassName = 'Macro';
final macro.IdentifierImpl dynamicIdentifier = new macro.IdentifierImpl(
    id: macro.RemoteInstance.uniqueId, name: 'dynamic');

class MacroDeclarationData {
  bool macrosAreAvailable = false;
  Map<Uri, List<String>> macroDeclarations = {};
  List<List<Uri>>? compilationSequence;
  List<Map<Uri, Map<String, List<String>>>> neededPrecompilations = [];
}

class MacroApplication {
  final ClassBuilder classBuilder;
  final String constructorName;

  // TODO(johnniwinther): Add support for arguments.

  MacroApplication(this.classBuilder, this.constructorName);

  late macro.MacroInstanceIdentifier instanceIdentifier;

  @override
  String toString() {
    return '${classBuilder.name}.'
        '${constructorName.isEmpty ? 'new' : constructorName}()';
  }
}

class MacroApplicationDataForTesting {
  Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData = {};
  Map<SourceLibraryBuilder, String> libraryTypesResult = {};
  Map<SourceLibraryBuilder, String> libraryDefinitionResult = {};
  Map<SourceClassBuilder, List<macro.MacroExecutionResult>> classTypesResults =
      {};
  Map<SourceClassBuilder, List<macro.MacroExecutionResult>>
      classDeclarationsResults = {};
  Map<SourceClassBuilder, List<macro.MacroExecutionResult>>
      classDefinitionsResults = {};
  Map<MemberBuilder, List<macro.MacroExecutionResult>> memberTypesResults = {};
  Map<MemberBuilder, List<macro.MacroExecutionResult>>
      memberDeclarationsResults = {};
  Map<MemberBuilder, List<macro.MacroExecutionResult>>
      memberDefinitionsResults = {};
}

class LibraryMacroApplicationData {
  Map<SourceClassBuilder, ClassMacroApplicationData> classData = {};
  Map<MemberBuilder, List<MacroApplication>> memberApplications = {};
}

class ClassMacroApplicationData {
  List<MacroApplication>? classApplications;
  Map<MemberBuilder, List<MacroApplication>> memberApplications = {};
}

/// Macro classes that need to be precompiled.
class NeededPrecompilations {
  /// Map from library uris to macro class names and the names of constructor
  /// their constructors is returned for macro classes that need to be
  /// precompiled.
  final Map<Uri, Map<String, List<String>>> macroDeclarations;

  NeededPrecompilations(this.macroDeclarations);
}

class MacroApplications {
  final macro.MacroExecutor _macroExecutor;
  final Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData;
  final MacroApplicationDataForTesting? dataForTesting;
  List<_ApplicationData>? _applicationDataCache;

  MacroApplications(
      this._macroExecutor, this.libraryData, this.dataForTesting) {
    dataForTesting?.libraryData.addAll(libraryData);
  }

  static Future<MacroApplications> loadMacroIds(
      macro.MacroExecutor macroExecutor,
      Map<Uri, Uri> precompiledMacroUris,
      Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData,
      MacroApplicationDataForTesting? dataForTesting) async {
    Map<ClassBuilder, macro.MacroClassIdentifier> classIdCache = {};

    Map<MacroApplication, macro.MacroInstanceIdentifier> instanceIdCache = {};

    Future<void> ensureMacroClassIds(
        List<MacroApplication>? applications) async {
      if (applications != null) {
        for (MacroApplication application in applications) {
          Uri libraryUri = application.classBuilder.library.importUri;
          String macroClassName = application.classBuilder.name;
          Uri? precompiledMacroUri = precompiledMacroUris[libraryUri];
          try {
            macro.MacroClassIdentifier macroClassIdentifier =
                classIdCache[application.classBuilder] ??=
                    await macroExecutor.loadMacro(libraryUri, macroClassName,
                        precompiledKernelUri: precompiledMacroUri);
            try {
              application.instanceIdentifier = instanceIdCache[application] ??=
                  await macroExecutor.instantiateMacro(
                      macroClassIdentifier,
                      application.constructorName,
                      // TODO(johnniwinther): Support macro arguments.
                      new macro.Arguments([], {}));
            } catch (e) {
              throw "Error instantiating macro `${application}`: $e";
            }
          } catch (e) {
            throw "Error loading macro class "
                "'${application.classBuilder.name}' from "
                "'${application.classBuilder.library.importUri}': $e";
          }
        }
      }
    }

    for (LibraryMacroApplicationData libraryData in libraryData.values) {
      for (ClassMacroApplicationData classData
          in libraryData.classData.values) {
        await ensureMacroClassIds(classData.classApplications);
        for (List<MacroApplication> applications
            in classData.memberApplications.values) {
          await ensureMacroClassIds(applications);
        }
      }
      for (List<MacroApplication> applications
          in libraryData.memberApplications.values) {
        await ensureMacroClassIds(applications);
      }
    }
    return new MacroApplications(macroExecutor, libraryData, dataForTesting);
  }

  Map<ClassBuilder, macro.ClassDeclaration> _classDeclarations = {};
  Map<macro.ClassDeclaration, ClassBuilder> _classBuilders = {};
  Map<MemberBuilder, macro.Declaration?> _memberDeclarations = {};

  // TODO(johnniwinther): Support all members.
  macro.Declaration? _getMemberDeclaration(MemberBuilder memberBuilder) {
    return _memberDeclarations[memberBuilder] ??=
        _createMemberDeclaration(memberBuilder);
  }

  macro.ClassDeclaration _getClassDeclaration(ClassBuilder builder) {
    return _classDeclarations[builder] ??= _createClassDeclaration(builder);
  }

  ClassBuilder _getClassBuilder(macro.ClassDeclaration declaration) {
    return _classBuilders[declaration]!;
  }

  macro.Declaration _createMemberDeclaration(MemberBuilder memberBuilder) {
    if (memberBuilder is SourceProcedureBuilder) {
      return _createFunctionDeclaration(memberBuilder);
    } else if (memberBuilder is SourceFieldBuilder) {
      return _createVariableDeclaration(memberBuilder);
    } else if (memberBuilder is SourceConstructorBuilder) {
      return _createConstructorDeclaration(memberBuilder);
    } else if (memberBuilder is SourceFactoryBuilder) {
      return _createFactoryDeclaration(memberBuilder);
    } else {
      // TODO(johnniwinther): Throw when all members are supported.
      throw new UnimplementedError(
          'Unsupported member ${memberBuilder} (${memberBuilder.runtimeType})');
    }
  }

  macro.ResolvedIdentifier _resolveIdentifier(macro.Identifier identifier) {
    if (identifier is _IdentifierImpl) {
      MemberBuilder? memberBuilder = identifier.memberBuilder;
      FormalParameterBuilder? parameterBuilder = identifier.parameterBuilder;
      TypeDeclarationBuilder? typeDeclarationBuilder =
          identifier.typeDeclarationBuilder ??
              identifier.typeBuilder?.declaration;
      if (memberBuilder != null) {
        Uri? uri;
        String? staticScope;
        macro.IdentifierKind kind;
        if (memberBuilder.isStatic || memberBuilder.isConstructor) {
          ClassBuilder classBuilder = memberBuilder.classBuilder!;
          staticScope = classBuilder.name;
          uri = classBuilder.library.importUri;
          kind = macro.IdentifierKind.staticInstanceMember;
        } else if (memberBuilder.isTopLevel) {
          uri = memberBuilder.library.importUri;
          kind = macro.IdentifierKind.topLevelMember;
        } else {
          kind = macro.IdentifierKind.instanceMember;
        }
        return new macro.ResolvedIdentifier(
            kind: kind,
            name: identifier.name,
            staticScope: staticScope,
            uri: uri);
      } else if (typeDeclarationBuilder != null) {
        Uri? uri;
        if (typeDeclarationBuilder is ClassBuilder) {
          uri = typeDeclarationBuilder.library.importUri;
        } else if (typeDeclarationBuilder is TypeAliasBuilder) {
          uri = typeDeclarationBuilder.library.importUri;
        } else if (identifier.name == 'dynamic') {
          uri = Uri.parse('dart:core');
        }
        return new macro.ResolvedIdentifier(
            kind: macro.IdentifierKind.topLevelMember,
            name: identifier.name,
            staticScope: null,
            uri: uri);
      } else if (parameterBuilder != null) {
        return new macro.ResolvedIdentifier(
            kind: macro.IdentifierKind.local,
            name: identifier.name,
            staticScope: null,
            uri: null);
      } else {
        throw new StateError('Unable to resolve identifier $identifier');
      }
    } else {
      // TODO(johnniwinther): Use [_IdentifierImpl] for all identifiers.
      if (identical(identifier, dynamicIdentifier)) {
        return new macro.ResolvedIdentifier(
            kind: macro.IdentifierKind.topLevelMember,
            name: identifier.name,
            staticScope: null,
            uri: Uri.parse('dart:core'));
      } else {
        return new macro.ResolvedIdentifier(
            kind: macro.IdentifierKind.topLevelMember,
            name: identifier.name,
            staticScope: null,
            uri: null);
      }
    }
  }

  Iterable<_ApplicationData> get _applicationData {
    if (_applicationDataCache == null) {
      List<_ApplicationData> data = _applicationDataCache = [];
      for (MapEntry<SourceLibraryBuilder,
          LibraryMacroApplicationData> libraryEntry in libraryData.entries) {
        SourceLibraryBuilder libraryBuilder = libraryEntry.key;
        LibraryMacroApplicationData libraryMacroApplicationData =
            libraryEntry.value;
        for (MapEntry<MemberBuilder, List<MacroApplication>> memberEntry
            in libraryMacroApplicationData.memberApplications.entries) {
          MemberBuilder memberBuilder = memberEntry.key;
          macro.Declaration? declaration = _getMemberDeclaration(memberBuilder);
          if (declaration != null) {
            data.add(new _ApplicationData(
                libraryBuilder, memberBuilder, declaration, memberEntry.value));
          }
        }
        for (MapEntry<SourceClassBuilder, ClassMacroApplicationData> classEntry
            in libraryMacroApplicationData.classData.entries) {
          SourceClassBuilder classBuilder = classEntry.key;
          ClassMacroApplicationData classData = classEntry.value;
          List<MacroApplication>? classApplications =
              classData.classApplications;
          if (classApplications != null) {
            macro.ClassDeclaration classDeclaration =
                _getClassDeclaration(classBuilder);
            data.add(new _ApplicationData(libraryBuilder, classBuilder,
                classDeclaration, classApplications));
          }
          for (MapEntry<MemberBuilder, List<MacroApplication>> memberEntry
              in classData.memberApplications.entries) {
            MemberBuilder memberBuilder = memberEntry.key;
            macro.Declaration? declaration =
                _getMemberDeclaration(memberBuilder);
            if (declaration != null) {
              data.add(new _ApplicationData(libraryBuilder, memberBuilder,
                  declaration, memberEntry.value));
            }
          }
        }
      }
    }
    return _applicationDataCache!;
  }

  Future<List<macro.MacroExecutionResult>> _applyTypeMacros(
      _ApplicationData applicationData) async {
    macro.Declaration declaration = applicationData.declaration;
    List<macro.MacroExecutionResult> results = [];
    for (MacroApplication macroApplication
        in applicationData.macroApplications) {
      if (macroApplication.instanceIdentifier
          .shouldExecute(_declarationKind(declaration), macro.Phase.types)) {
        macro.MacroExecutionResult result =
            await _macroExecutor.executeTypesPhase(
                macroApplication.instanceIdentifier,
                declaration,
                identifierResolver);
        if (result.isNotEmpty) {
          results.add(result);
        }
      }
    }

    if (retainDataForTesting) {
      Builder builder = applicationData.builder;
      if (builder is SourceClassBuilder) {
        dataForTesting?.classTypesResults[builder] = results;
      } else {
        dataForTesting?.memberTypesResults[builder as MemberBuilder] = results;
      }
    }
    return results;
  }

  late macro.IdentifierResolver identifierResolver;
  late SourceLoader sourceLoader;

  Future<List<SourceLibraryBuilder>> applyTypeMacros(
      SourceLoader sourceLoader) async {
    identifierResolver = new _IdentifierResolver(sourceLoader);
    List<SourceLibraryBuilder> augmentationLibraries = [];
    Map<SourceLibraryBuilder, List<macro.MacroExecutionResult>> results = {};
    for (_ApplicationData macroApplication in _applicationData) {
      List<macro.MacroExecutionResult> executionResults =
          await _applyTypeMacros(macroApplication);
      if (executionResults.isNotEmpty) {
        (results[macroApplication.libraryBuilder] ??= [])
            .addAll(executionResults);
      }
    }
    for (MapEntry<SourceLibraryBuilder, List<macro.MacroExecutionResult>> entry
        in results.entries) {
      SourceLibraryBuilder sourceLibraryBuilder = entry.key;
      assert(entry.value.isNotEmpty);
      String result = _macroExecutor
          .buildAugmentationLibrary(entry.value, _resolveIdentifier)
          .trim();
      assert(
          result.trim().isNotEmpty,
          "Empty types phase augmentation library source for "
          "$sourceLibraryBuilder}");
      if (result.isNotEmpty) {
        if (retainDataForTesting) {
          dataForTesting?.libraryTypesResult[sourceLibraryBuilder] = result;
        }
        augmentationLibraries
            .add(await sourceLibraryBuilder.createAugmentationLibrary(result));
      }
    }
    return augmentationLibraries;
  }

  Future<void> _applyDeclarationsMacros(_ApplicationData applicationData,
      Future<void> Function(SourceLibraryBuilder) onAugmentationLibrary) async {
    List<macro.MacroExecutionResult> results = [];
    macro.Declaration declaration = applicationData.declaration;
    for (MacroApplication macroApplication
        in applicationData.macroApplications) {
      if (macroApplication.instanceIdentifier.shouldExecute(
          _declarationKind(declaration), macro.Phase.declarations)) {
        macro.MacroExecutionResult result =
            await _macroExecutor.executeDeclarationsPhase(
                macroApplication.instanceIdentifier,
                declaration,
                identifierResolver,
                typeResolver,
                classIntrospector);
        if (result.isNotEmpty) {
          String source = _macroExecutor
              .buildAugmentationLibrary([result], _resolveIdentifier);
          SourceLibraryBuilder augmentationLibrary = await applicationData
              .libraryBuilder
              .createAugmentationLibrary(source);
          await onAugmentationLibrary(augmentationLibrary);
          if (retainDataForTesting) {
            results.add(result);
          }
        }
      }
    }
    if (retainDataForTesting) {
      Builder builder = applicationData.builder;
      if (builder is SourceClassBuilder) {
        dataForTesting?.classDeclarationsResults[builder] = results;
      } else {
        dataForTesting?.memberDeclarationsResults[builder as MemberBuilder] =
            results;
      }
    }
  }

  late Types types;
  late macro.TypeResolver typeResolver;
  late macro.ClassIntrospector classIntrospector;

  Future<void> applyDeclarationsMacros(ClassHierarchyBuilder classHierarchy,
      Future<void> Function(SourceLibraryBuilder) onAugmentationLibrary) async {
    types = new Types(classHierarchy);
    typeResolver = new _TypeResolver(this);
    classIntrospector = new _ClassIntrospector(this, classHierarchy);
    for (_ApplicationData macroApplication in _applicationData) {
      await _applyDeclarationsMacros(macroApplication, onAugmentationLibrary);
    }
  }

  Future<List<macro.MacroExecutionResult>> _applyDefinitionMacros(
      _ApplicationData applicationData) async {
    List<macro.MacroExecutionResult> results = [];
    macro.Declaration declaration = applicationData.declaration;
    for (MacroApplication macroApplication
        in applicationData.macroApplications) {
      if (macroApplication.instanceIdentifier.shouldExecute(
          _declarationKind(declaration), macro.Phase.definitions)) {
        macro.MacroExecutionResult result =
            await _macroExecutor.executeDefinitionsPhase(
                macroApplication.instanceIdentifier,
                declaration,
                identifierResolver,
                typeResolver,
                classIntrospector,
                typeDeclarationResolver);
        if (result.isNotEmpty) {
          results.add(result);
        }
      }
    }
    if (retainDataForTesting) {
      Builder builder = applicationData.builder;
      if (builder is SourceClassBuilder) {
        dataForTesting?.classDefinitionsResults[builder] = results;
      } else {
        dataForTesting?.memberDefinitionsResults[builder as MemberBuilder] =
            results;
      }
    }
    return results;
  }

  late macro.TypeDeclarationResolver typeDeclarationResolver;

  Future<List<SourceLibraryBuilder>> applyDefinitionMacros() async {
    typeDeclarationResolver = new _TypeDeclarationResolver();
    List<SourceLibraryBuilder> augmentationLibraries = [];
    Map<SourceLibraryBuilder, List<macro.MacroExecutionResult>> results = {};
    for (_ApplicationData macroApplication in _applicationData) {
      List<macro.MacroExecutionResult> executionResults =
          await _applyDefinitionMacros(macroApplication);
      if (executionResults.isNotEmpty) {
        (results[macroApplication.libraryBuilder] ??= [])
            .addAll(executionResults);
      }
    }
    for (MapEntry<SourceLibraryBuilder, List<macro.MacroExecutionResult>> entry
        in results.entries) {
      SourceLibraryBuilder sourceLibraryBuilder = entry.key;
      String result = _macroExecutor.buildAugmentationLibrary(
          entry.value, _resolveIdentifier);
      assert(
          result.trim().isNotEmpty,
          "Empty definitions phase augmentation library source for "
          "$sourceLibraryBuilder}");
      if (retainDataForTesting) {
        dataForTesting?.libraryDefinitionResult[sourceLibraryBuilder] = result;
      }
      augmentationLibraries
          .add(await sourceLibraryBuilder.createAugmentationLibrary(result));
    }
    return augmentationLibraries;
  }

  void close() {
    _macroExecutor.close();
    _staticTypeCache.clear();
    _typeAnnotationCache.clear();
    _applicationDataCache?.clear();
  }

  macro.ClassDeclaration _createClassDeclaration(ClassBuilder builder) {
    macro.ClassDeclaration declaration = new macro.ClassDeclarationImpl(
        id: macro.RemoteInstance.uniqueId,
        identifier: new _IdentifierImpl.forTypeDeclarationBuilder(
            typeDeclarationBuilder: builder,
            libraryBuilder: builder.library,
            id: macro.RemoteInstance.uniqueId,
            name: builder.name),
        // TODO(johnniwinther): Support typeParameters
        typeParameters: [],
        // TODO(johnniwinther): Support interfaces
        interfaces: [],
        isAbstract: builder.isAbstract,
        isExternal: builder.isExternal,
        // TODO(johnniwinther): Support mixins
        mixins: [],
        // TODO(johnniwinther): Support superclass
        superclass: null);
    _classBuilders[declaration] = builder;
    return declaration;
  }

  List<List<macro.ParameterDeclarationImpl>> _createParameters(
      MemberBuilder builder, List<FormalParameterBuilder>? formals) {
    List<macro.ParameterDeclarationImpl>? positionalParameters;
    List<macro.ParameterDeclarationImpl>? namedParameters;
    if (formals == null) {
      positionalParameters = namedParameters = const [];
    } else {
      positionalParameters = [];
      namedParameters = [];
      for (FormalParameterBuilder formal in formals) {
        macro.TypeAnnotationImpl type =
            computeTypeAnnotation(builder.library, formal.type);
        macro.IdentifierImpl identifier =
            new _IdentifierImpl.forParameterBuilder(
                id: macro.RemoteInstance.uniqueId,
                name: formal.name,
                parameterBuilder: formal,
                libraryBuilder: builder.library);
        if (formal.isNamed) {
          namedParameters.add(new macro.ParameterDeclarationImpl(
            id: macro.RemoteInstance.uniqueId,
            identifier: identifier,
            isRequired: formal.isNamedRequired,
            isNamed: true,
            type: type,
          ));
        } else {
          positionalParameters.add(new macro.ParameterDeclarationImpl(
            id: macro.RemoteInstance.uniqueId,
            identifier: identifier,
            isRequired: formal.isRequired,
            isNamed: false,
            type: type,
          ));
        }
      }
    }
    return [positionalParameters, namedParameters];
  }

  macro.ConstructorDeclaration _createConstructorDeclaration(
      SourceConstructorBuilder builder) {
    List<FormalParameterBuilder>? formals = null;
    // TODO(johnniwinther): Support formals for other constructors.
    if (builder is DeclaredSourceConstructorBuilder) {
      formals = builder.formals;
    }
    List<List<macro.ParameterDeclarationImpl>> parameters =
        _createParameters(builder, formals);
    macro.ClassDeclaration definingClass =
        _getClassDeclaration(builder.classBuilder as SourceClassBuilder);
    return new macro.ConstructorDeclarationImpl(
      id: macro.RemoteInstance.uniqueId,
      identifier: new _IdentifierImpl.forMemberBuilder(
          memberBuilder: builder,
          id: macro.RemoteInstance.uniqueId,
          name: builder.name),
      definingClass: definingClass.identifier as macro.IdentifierImpl,
      isFactory: builder.isFactory,
      isAbstract: builder.isAbstract,
      isExternal: builder.isExternal,
      isGetter: builder.isGetter,
      isOperator: builder.isOperator,
      isSetter: builder.isSetter,
      positionalParameters: parameters[0],
      namedParameters: parameters[1],
      // TODO(johnniwinther): Support constructor return type.
      returnType: computeTypeAnnotation(builder.library, null),
      // TODO(johnniwinther): Support typeParameters
      typeParameters: const [],
    );
  }

  macro.ConstructorDeclaration _createFactoryDeclaration(
      SourceFactoryBuilder builder) {
    List<List<macro.ParameterDeclarationImpl>> parameters =
        _createParameters(builder, builder.formals);
    macro.ClassDeclaration definingClass =
        _getClassDeclaration(builder.classBuilder as SourceClassBuilder);

    return new macro.ConstructorDeclarationImpl(
      id: macro.RemoteInstance.uniqueId,
      identifier: new _IdentifierImpl.forMemberBuilder(
          memberBuilder: builder,
          id: macro.RemoteInstance.uniqueId,
          name: builder.name),
      definingClass: definingClass.identifier as macro.IdentifierImpl,
      isFactory: builder.isFactory,
      isAbstract: builder.isAbstract,
      isExternal: builder.isExternal,
      isGetter: builder.isGetter,
      isOperator: builder.isOperator,
      isSetter: builder.isSetter,
      positionalParameters: parameters[0],
      namedParameters: parameters[1],
      // TODO(johnniwinther): Support constructor return type.
      returnType: computeTypeAnnotation(builder.library, null),
      // TODO(johnniwinther): Support typeParameters
      typeParameters: const [],
    );
  }

  macro.FunctionDeclaration _createFunctionDeclaration(
      SourceProcedureBuilder builder) {
    List<List<macro.ParameterDeclarationImpl>> parameters =
        _createParameters(builder, builder.formals);

    macro.ClassDeclaration? definingClass = null;
    if (builder.classBuilder != null) {
      definingClass =
          _getClassDeclaration(builder.classBuilder as SourceClassBuilder);
    }
    if (definingClass != null) {
      // TODO(johnniwinther): Should static fields be field or variable
      //  declarations?
      return new macro.MethodDeclarationImpl(
          id: macro.RemoteInstance.uniqueId,
          identifier: new _IdentifierImpl.forMemberBuilder(
              memberBuilder: builder,
              id: macro.RemoteInstance.uniqueId,
              name: builder.name),
          definingClass: definingClass.identifier as macro.IdentifierImpl,
          isAbstract: builder.isAbstract,
          isExternal: builder.isExternal,
          isGetter: builder.isGetter,
          isOperator: builder.isOperator,
          isSetter: builder.isSetter,
          isStatic: builder.isStatic,
          positionalParameters: parameters[0],
          namedParameters: parameters[1],
          returnType:
              computeTypeAnnotation(builder.library, builder.returnType),
          // TODO(johnniwinther): Support typeParameters
          typeParameters: const []);
    } else {
      return new macro.FunctionDeclarationImpl(
          id: macro.RemoteInstance.uniqueId,
          identifier: new _IdentifierImpl.forMemberBuilder(
              memberBuilder: builder,
              id: macro.RemoteInstance.uniqueId,
              name: builder.name),
          isAbstract: builder.isAbstract,
          isExternal: builder.isExternal,
          isGetter: builder.isGetter,
          isOperator: builder.isOperator,
          isSetter: builder.isSetter,
          positionalParameters: parameters[0],
          namedParameters: parameters[1],
          returnType:
              computeTypeAnnotation(builder.library, builder.returnType),
          // TODO(johnniwinther): Support typeParameters
          typeParameters: const []);
    }
  }

  macro.VariableDeclaration _createVariableDeclaration(
      SourceFieldBuilder builder) {
    macro.ClassDeclaration? definingClass = null;
    if (builder.classBuilder != null) {
      definingClass =
          _getClassDeclaration(builder.classBuilder as SourceClassBuilder);
    }
    if (definingClass != null) {
      // TODO(johnniwinther): Should static fields be field or variable
      //  declarations?
      return new macro.FieldDeclarationImpl(
          id: macro.RemoteInstance.uniqueId,
          identifier: new _IdentifierImpl.forMemberBuilder(
              memberBuilder: builder,
              id: macro.RemoteInstance.uniqueId,
              name: builder.name),
          definingClass: definingClass.identifier as macro.IdentifierImpl,
          isExternal: builder.isExternal,
          isFinal: builder.isFinal,
          isLate: builder.isLate,
          isStatic: builder.isStatic,
          type: computeTypeAnnotation(builder.library, builder.type));
    } else {
      return new macro.VariableDeclarationImpl(
          id: macro.RemoteInstance.uniqueId,
          identifier: new _IdentifierImpl.forMemberBuilder(
              memberBuilder: builder,
              id: macro.RemoteInstance.uniqueId,
              name: builder.name),
          isExternal: builder.isExternal,
          isFinal: builder.isFinal,
          isLate: builder.isLate,
          type: computeTypeAnnotation(builder.library, builder.type));
    }
  }

  Map<TypeBuilder?, macro.TypeAnnotationImpl> _typeAnnotationCache = {};

  List<macro.TypeAnnotationImpl> computeTypeAnnotations(
      LibraryBuilder library, List<TypeBuilder>? typeBuilders) {
    if (typeBuilders == null) return const [];
    return new List.generate(typeBuilders.length,
        (int index) => computeTypeAnnotation(library, typeBuilders[index]));
  }

  macro.TypeAnnotationImpl _computeTypeAnnotation(
      LibraryBuilder libraryBuilder, TypeBuilder? typeBuilder) {
    if (typeBuilder != null) {
      if (typeBuilder is NamedTypeBuilder) {
        Object name = typeBuilder.name;
        List<macro.TypeAnnotationImpl> typeArguments =
            computeTypeAnnotations(libraryBuilder, typeBuilder.arguments);
        bool isNullable = typeBuilder.nullabilityBuilder.isNullable;
        if (name is String) {
          return new macro.NamedTypeAnnotationImpl(
              id: macro.RemoteInstance.uniqueId,
              identifier: new _IdentifierImpl.forTypeBuilder(
                  typeBuilder: typeBuilder,
                  libraryBuilder: libraryBuilder,
                  id: macro.RemoteInstance.uniqueId,
                  name: name),
              typeArguments: typeArguments,
              isNullable: isNullable);
        } else if (name is QualifiedName) {
          assert(name.qualifier is String);
          return new macro.NamedTypeAnnotationImpl(
              id: macro.RemoteInstance.uniqueId,
              identifier: new _IdentifierImpl.forTypeBuilder(
                  typeBuilder: typeBuilder,
                  libraryBuilder: libraryBuilder,
                  id: macro.RemoteInstance.uniqueId,
                  name: name.name),
              typeArguments: typeArguments,
              isNullable: isNullable);
        }
      }
    }
    return new macro.NamedTypeAnnotationImpl(
        id: macro.RemoteInstance.uniqueId,
        identifier: dynamicIdentifier,
        isNullable: false,
        typeArguments: const []);
  }

  macro.TypeAnnotationImpl computeTypeAnnotation(
      LibraryBuilder libraryBuilder, TypeBuilder? typeBuilder) {
    return _typeAnnotationCache[typeBuilder] ??=
        _computeTypeAnnotation(libraryBuilder, typeBuilder);
  }

  TypeBuilder _typeBuilderForAnnotation(
      macro.TypeAnnotationCode typeAnnotation) {
    NullabilityBuilder nullabilityBuilder;
    if (typeAnnotation is macro.NullableTypeAnnotationCode) {
      nullabilityBuilder = const NullabilityBuilder.nullable();
      typeAnnotation = typeAnnotation.underlyingType;
    } else {
      nullabilityBuilder = const NullabilityBuilder.omitted();
    }

    if (typeAnnotation is macro.NamedTypeAnnotationCode) {
      _IdentifierImpl typeIdentifier = typeAnnotation.name as _IdentifierImpl;
      TypeDeclarationBuilder? typeDeclarationBuilder =
          typeIdentifier.typeDeclarationBuilder;
      InstanceTypeVariableAccessState instanceTypeVariableAccessState =
          InstanceTypeVariableAccessState.Unexpected;
      if (typeDeclarationBuilder == null) {
        TypeBuilder? originalTypeBuilder = typeIdentifier.typeBuilder;

        if (originalTypeBuilder == null) {
          throw new StateError('No type builder for $typeIdentifier');
        }
        if (originalTypeBuilder is! NamedTypeBuilder) {
          throw new StateError(
              'Type $typeIdentifier was not a named type as expected!');
        }
        typeDeclarationBuilder = originalTypeBuilder.declaration!;
        instanceTypeVariableAccessState =
            originalTypeBuilder.instanceTypeVariableAccess;
      }
      List<TypeBuilder> arguments = [
        for (macro.TypeAnnotationCode argumentCode
            in typeAnnotation.typeArguments)
          _typeBuilderForAnnotation(argumentCode),
      ];

      return new NamedTypeBuilder.fromTypeDeclarationBuilder(
          typeDeclarationBuilder, nullabilityBuilder,
          instanceTypeVariableAccess: instanceTypeVariableAccessState,
          arguments: arguments);
    }
    // TODO: Implement support for function types.
    throw new UnimplementedError(
        'Unimplemented type annotation kind ${typeAnnotation.kind}');
  }

  macro.StaticType resolveTypeAnnotation(
      macro.TypeAnnotationCode typeAnnotation) {
    TypeBuilder typeBuilder = _typeBuilderForAnnotation(typeAnnotation);
    // TODO: This should probably be passed in instead, possibly attached to the
    // TypeResolver class?
    LibraryBuilder libraryBuilder =
        typeAnnotation.parts.whereType<_IdentifierImpl>().first.libraryBuilder;
    return createStaticType(typeBuilder.build(libraryBuilder));
  }

  Map<DartType, _StaticTypeImpl> _staticTypeCache = {};

  macro.StaticType createStaticType(DartType dartType) {
    return _staticTypeCache[dartType] ??= new _StaticTypeImpl(this, dartType);
  }
}

class _IdentifierImpl extends macro.IdentifierImpl {
  final TypeDeclarationBuilder? typeDeclarationBuilder;
  final MemberBuilder? memberBuilder;
  final TypeBuilder? typeBuilder;
  final LibraryBuilder libraryBuilder;
  final FormalParameterBuilder? parameterBuilder;

  _IdentifierImpl.forTypeBuilder({
    required TypeBuilder this.typeBuilder,
    required this.libraryBuilder,
    required int id,
    required String name,
  })  : typeDeclarationBuilder = null,
        memberBuilder = null,
        parameterBuilder = null,
        super(id: id, name: name);

  _IdentifierImpl.forTypeDeclarationBuilder({
    required TypeDeclarationBuilder this.typeDeclarationBuilder,
    required this.libraryBuilder,
    required int id,
    required String name,
  })  : typeBuilder = null,
        memberBuilder = null,
        parameterBuilder = null,
        super(id: id, name: name);

  _IdentifierImpl.forMemberBuilder(
      {required MemberBuilder this.memberBuilder,
      required int id,
      required String name})
      : typeBuilder = null,
        typeDeclarationBuilder = null,
        parameterBuilder = null,
        libraryBuilder = memberBuilder.library,
        super(id: id, name: name);

  _IdentifierImpl.forParameterBuilder({
    required FormalParameterBuilder this.parameterBuilder,
    required this.libraryBuilder,
    required int id,
    required String name,
  })  : typeBuilder = null,
        typeDeclarationBuilder = null,
        memberBuilder = null,
        super(id: id, name: name);
}

class _StaticTypeImpl extends macro.StaticType {
  final MacroApplications macroApplications;
  final DartType type;

  _StaticTypeImpl(this.macroApplications, this.type);

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

  @override
  Future<bool> isSubtypeOf(covariant _StaticTypeImpl other) {
    return new Future.value(macroApplications.types
        .isSubtypeOf(type, other.type, SubtypeCheckMode.withNullabilities));
  }
}

class _IdentifierResolver implements macro.IdentifierResolver {
  final SourceLoader sourceLoader;

  _IdentifierResolver(this.sourceLoader);

  @override
  Future<macro.Identifier> resolveIdentifier(Uri library, String name) {
    LibraryBuilder? libraryBuilder = sourceLoader.lookupLibraryBuilder(library);
    if (libraryBuilder == null) {
      return new Future.error(
          new ArgumentError('Library at uri $library could not be resolved.'),
          StackTrace.current);
    }
    bool isSetter = false;
    String memberName = name;
    if (name.endsWith('=')) {
      memberName = name.substring(0, name.length - 1);
      isSetter = true;
    }
    Builder? builder =
        libraryBuilder.scope.lookupLocalMember(memberName, setter: isSetter);
    if (builder == null) {
      return new Future.error(
          new ArgumentError(
              'Unable to find top level identifier "$name" in $library'),
          StackTrace.current);
    } else if (builder is TypeDeclarationBuilder) {
      return new Future.value(new _IdentifierImpl.forTypeDeclarationBuilder(
          typeDeclarationBuilder: builder,
          libraryBuilder: libraryBuilder,
          id: macro.RemoteInstance.uniqueId,
          name: name));
    } else if (builder is MemberBuilder) {
      return new Future.value(new _IdentifierImpl.forMemberBuilder(
          memberBuilder: builder,
          id: macro.RemoteInstance.uniqueId,
          name: name));
    } else {
      return new Future.error(
          new UnsupportedError('Unsupported identifier kind $builder'),
          StackTrace.current);
    }
  }
}

class _TypeResolver implements macro.TypeResolver {
  final MacroApplications macroApplications;

  _TypeResolver(this.macroApplications);

  @override
  Future<macro.StaticType> resolve(macro.TypeAnnotationCode typeAnnotation) {
    return new Future.value(
        macroApplications.resolveTypeAnnotation(typeAnnotation));
  }
}

class _ClassIntrospector implements macro.ClassIntrospector {
  final MacroApplications macroApplications;
  final ClassHierarchyBuilder classHierarchy;

  _ClassIntrospector(this.macroApplications, this.classHierarchy);

  @override
  Future<List<macro.ConstructorDeclaration>> constructorsOf(
      macro.ClassDeclaration clazz) {
    ClassBuilder classBuilder = macroApplications._getClassBuilder(clazz);
    List<macro.ConstructorDeclaration> result = [];
    classBuilder.forEachConstructor((_, MemberBuilder memberBuilder) {
      if (memberBuilder is DeclaredSourceConstructorBuilder) {
        // TODO(johnniwinther): Should we support synthesized constructors?
        result.add(macroApplications._getMemberDeclaration(memberBuilder)
            as macro.ConstructorDeclaration);
      }
    });
    classBuilder.forEach((_, Builder memberBuilder) {
      if (memberBuilder is SourceFactoryBuilder) {
        result.add(macroApplications._getMemberDeclaration(memberBuilder)
            as macro.ConstructorDeclaration);
      }
    });
    return new Future.value(result);
  }

  @override
  Future<List<macro.FieldDeclaration>> fieldsOf(macro.ClassDeclaration clazz) {
    ClassBuilder classBuilder = macroApplications._getClassBuilder(clazz);
    List<macro.FieldDeclaration> result = [];
    classBuilder.forEach((_, Builder memberBuilder) {
      if (memberBuilder is SourceFieldBuilder) {
        result.add(macroApplications._getMemberDeclaration(memberBuilder)
            as macro.FieldDeclaration);
      }
    });
    return new Future.value(result);
  }

  @override
  Future<List<macro.ClassDeclaration>> interfacesOf(
      macro.ClassDeclaration clazz) {
    // TODO: implement interfacesOf
    throw new UnimplementedError('_ClassIntrospector.interfacesOf');
  }

  @override
  Future<List<macro.MethodDeclaration>> methodsOf(
      macro.ClassDeclaration clazz) {
    ClassBuilder classBuilder = macroApplications._getClassBuilder(clazz);
    List<macro.MethodDeclaration> result = [];
    classBuilder.forEach((_, Builder memberBuilder) {
      if (memberBuilder is SourceProcedureBuilder) {
        result.add(macroApplications._getMemberDeclaration(memberBuilder)
            as macro.MethodDeclaration);
      }
    });
    return new Future.value(result);
  }

  @override
  Future<List<macro.ClassDeclaration>> mixinsOf(macro.ClassDeclaration clazz) {
    // TODO: implement mixinsOf
    throw new UnimplementedError('_ClassIntrospector.mixinsOf');
  }

  @override
  Future<macro.ClassDeclaration?> superclassOf(macro.ClassDeclaration clazz) {
    ClassBuilder classBuilder = macroApplications._getClassBuilder(clazz);
    ClassHierarchyNode node =
        classHierarchy.getNodeFromClassBuilder(classBuilder);
    ClassHierarchyNode? superNode = node.supernode;
    while (superNode != null &&
        superNode.classBuilder.isAnonymousMixinApplication) {
      superNode = superNode.supernode;
    }
    if (superNode != null) {
      return new Future.value(
          macroApplications._getClassDeclaration(superNode.classBuilder));
    }
    return new Future.value();
  }
}

class _TypeDeclarationResolver implements macro.TypeDeclarationResolver {
  @override
  Future<macro.TypeDeclaration> declarationOf(macro.Identifier identifier) {
    // TODO: implement declarationOf
    throw new UnimplementedError('_TypeDeclarationResolver.declarationOf');
  }
}

macro.DeclarationKind _declarationKind(macro.Declaration declaration) {
  if (declaration is macro.ConstructorDeclaration) {
    return macro.DeclarationKind.constructor;
  } else if (declaration is macro.MethodDeclaration) {
    return macro.DeclarationKind.method;
  } else if (declaration is macro.FunctionDeclaration) {
    return macro.DeclarationKind.function;
  } else if (declaration is macro.FieldDeclaration) {
    return macro.DeclarationKind.field;
  } else if (declaration is macro.VariableDeclaration) {
    return macro.DeclarationKind.variable;
  } else if (declaration is macro.ClassDeclaration) {
    return macro.DeclarationKind.clazz;
  }
  throw new UnsupportedError(
      "Unexpected declaration ${declaration} (${declaration.runtimeType})");
}

/// Data needed to apply a list of macro applications to a class or member.
class _ApplicationData {
  final SourceLibraryBuilder libraryBuilder;
  final Builder builder;
  final macro.Declaration declaration;
  final List<MacroApplication> macroApplications;

  _ApplicationData(this.libraryBuilder, this.builder, this.declaration,
      this.macroApplications);
}

extension on macro.MacroExecutionResult {
  bool get isNotEmpty =>
      libraryAugmentations.isNotEmpty || classAugmentations.isNotEmpty;
}
