// Copyright 2019 Dart Mockito authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import 'dart:collection';

import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart' as analyzer;
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:build/build.dart';
// Do not expose [refer] in the default namespace.
//
// [refer] allows a reference to include or not include a URL. Omitting the URL
// of an element, like a class, has resulted in many bugs. [_MockLibraryInfo]
// provides a [refer] function and a [referBasic] function. The former requires
// a URL to be passed.
import 'package:code_builder/code_builder.dart' hide refer;
import 'package:collection/collection.dart';
import 'package:dart_style/dart_style.dart';
import 'package:mockito/src/version.dart';
import 'package:path/path.dart' as p;
import 'package:source_gen/source_gen.dart';

/// For a source Dart library, generate the mocks referenced therein.
///
/// Given an input library, 'foo.dart', this builder will search the top-level
/// elements for an annotation, `@GenerateMocks`, from the mockito package. For
/// example:
///
/// ```dart
/// @GenerateMocks([Foo])
/// void main() {}
/// ```
///
/// If this builder finds any classes to mock (for example, `Foo`, above), it
/// will produce a "'.mocks.dart' file with such mocks. In this example,
/// 'foo.mocks.dart' will be created.
class MockBuilder implements Builder {
  @override
  Future<void> build(BuildStep buildStep) async {
    if (!await buildStep.resolver.isLibrary(buildStep.inputId)) return;
    final entryLib = await buildStep.inputLibrary;
    if (entryLib == null) return;
    final sourceLibIsNonNullable = entryLib.isNonNullableByDefault;
    final mockLibraryAsset = buildStep.inputId.changeExtension('.mocks.dart');
    final mockTargetGatherer = _MockTargetGatherer(entryLib);

    var entryAssetId = await buildStep.resolver.assetIdForElement(entryLib);
    final assetUris = await _resolveAssetUris(buildStep.resolver,
        mockTargetGatherer._mockTargets, entryAssetId.path, entryLib);

    final mockLibraryInfo = _MockLibraryInfo(mockTargetGatherer._mockTargets,
        assetUris: assetUris, entryLib: entryLib);

    if (mockLibraryInfo.fakeClasses.isEmpty &&
        mockLibraryInfo.mockClasses.isEmpty) {
      // Nothing to mock here!
      return;
    }

    final mockLibrary = Library((b) {
      // These comments are added after import directives; leading newlines
      // are necessary.
      b.body.add(
          Code('\n\n// ignore_for_file: avoid_redundant_argument_values\n'));
      // We don't properly prefix imported class names in doc comments.
      b.body.add(Code('// ignore_for_file: comment_references\n'));
      // We might import a package's 'src' directory.
      b.body.add(Code('// ignore_for_file: implementation_imports\n'));
      // `Mock.noSuchMethod` is `@visibleForTesting`, but the generated code is
      // not always in a test directory; the Mockito `example/iss` tests, for
      // example.
      b.body.add(Code(
          '// ignore_for_file: invalid_use_of_visible_for_testing_member\n'));
      b.body.add(Code('// ignore_for_file: prefer_const_constructors\n'));
      // The code_builder `asA` API unconditionally adds defensive parentheses.
      b.body.add(Code('// ignore_for_file: unnecessary_parenthesis\n\n'));
      b.body.addAll(mockLibraryInfo.fakeClasses);
      b.body.addAll(mockLibraryInfo.mockClasses);
    });

    final emitter = DartEmitter.scoped(
        orderDirectives: true, useNullSafetySyntax: sourceLibIsNonNullable);
    final rawOutput = mockLibrary.accept(emitter).toString();
    final mockLibraryContent = DartFormatter().format('''
// Mocks generated by Mockito $packageVersion from annotations
// in ${entryLib.definingCompilationUnit.source.uri.path}.
// Do not manually edit this file.

$rawOutput
''');

    await buildStep.writeAsString(mockLibraryAsset, mockLibraryContent);
  }

  Future<Map<Element, String>> _resolveAssetUris(
      Resolver resolver,
      List<_MockTarget> mockTargets,
      String entryAssetPath,
      LibraryElement entryLib) async {
    final typeVisitor = _TypeVisitor();
    final seenTypes = <analyzer.InterfaceType>{};
    final librariesWithTypes = <LibraryElement>{};

    void addTypesFrom(analyzer.InterfaceType type) {
      // Prevent infinite recursion.
      if (seenTypes.contains(type)) {
        return;
      }
      seenTypes.add(type);
      librariesWithTypes.add(type.element.library);
      type.element.accept(typeVisitor);
      // For a type like `Foo<Bar>`, add the `Bar`.
      type.typeArguments
          .whereType<analyzer.InterfaceType>()
          .forEach(addTypesFrom);
      // For a type like `Foo extends Bar<Baz>`, add the `Baz`.
      for (var supertype in type.allSupertypes) {
        addTypesFrom(supertype);
      }
    }

    for (var mockTarget in mockTargets) {
      addTypesFrom(mockTarget.classType);
    }

    final typeUris = <Element, String>{};

    final elements = [
      // Types which may be referenced.
      ...typeVisitor._elements,
      // Fallback generator functions which may be referenced.
      for (final mockTarget in mockTargets)
        ...mockTarget.fallbackGenerators.values,
    ];

    for (final element in elements) {
      final elementLibrary = element.library!;
      if (elementLibrary.isInSdk) {
        // ignore:unnecessary_non_null_assertion
        if (elementLibrary.name!.startsWith('dart._')) {
          typeUris[element] = _findPublicExportOf(
              Queue.of(librariesWithTypes), elementLibrary)!;
        } else {
          typeUris[element] = elementLibrary.source.uri.toString();
        }
        continue;
      }

      try {
        final typeAssetId = await resolver.assetIdForElement(elementLibrary);

        if (typeAssetId.path.startsWith('lib/')) {
          typeUris[element] = typeAssetId.uri.toString();
        } else {
          typeUris[element] =
              p.relative(typeAssetId.path, from: p.dirname(entryAssetPath));
        }
      } on UnresolvableAssetException {
        // Asset may be in a summary.
        typeUris[element] = elementLibrary.source.uri.toString();
        continue;
      }
    }

    return typeUris;
  }

  /// Returns the String import path of the correct public library which
  /// exports [privateLibrary], selecting from the imports of [inputLibraries].
  static String? _findPublicExportOf(
      Queue<LibraryElement> inputLibraries, LibraryElement privateLibrary) {
    final libraries = Queue.of([
      for (final library in inputLibraries) ...library.importedLibraries,
    ]);

    while (libraries.isNotEmpty) {
      final library = libraries.removeFirst();
      if (library.exportedLibraries.contains(privateLibrary)) {
        return library.source.uri.toString();
      }
      // A library may provide [privateLibrary] by exporting a library which
      // provides it (directly or via further exporting).
      libraries.addAll(library.exportedLibraries);
    }
    return null;
  }

  @override
  final buildExtensions = const {
    '.dart': ['.mocks.dart']
  };
}

/// An [Element] visitor which collects the elements of all of the
/// [analyzer.InterfaceType]s which it encounters.
class _TypeVisitor extends RecursiveElementVisitor<void> {
  final _elements = <Element>{};

  @override
  void visitClassElement(ClassElement element) {
    _elements.add(element);
    super.visitClassElement(element);
  }

  @override
  void visitFieldElement(FieldElement element) {
    _addType(element.type);
    super.visitFieldElement(element);
  }

  @override
  void visitMethodElement(MethodElement element) {
    _addType(element.returnType);
    super.visitMethodElement(element);
  }

  @override
  void visitParameterElement(ParameterElement element) {
    _addType(element.type);
    if (element.hasDefaultValue) {
      _addTypesFromConstant(element.computeConstantValue()!);
    }
    super.visitParameterElement(element);
  }

  @override
  void visitTypeParameterElement(TypeParameterElement element) {
    _addType(element.bound);
    super.visitTypeParameterElement(element);
  }

  /// Adds [type] to the collected [_elements].
  void _addType(analyzer.DartType? type) {
    if (type == null) return;

    if (type is analyzer.InterfaceType) {
      final alreadyVisitedElement = _elements.contains(type.element);
      _elements.add(type.element);
      type.typeArguments.forEach(_addType);
      if (!alreadyVisitedElement) {
        type.element.typeParameters.forEach(visitTypeParameterElement);
      }
    } else if (type is analyzer.FunctionType) {
      _addType(type.returnType);

      // [RecursiveElementVisitor] does not "step out of" the element model,
      // into types, while traversing, so we must explicitly traverse [type]
      // here, in order to visit contained elements.
      if (type.typeFormals != null) {
        for (var typeParameter in type.typeFormals) {
          typeParameter.accept(this);
        }
      }
      for (var parameter in type.parameters) {
        parameter.accept(this);
      }
      var aliasElement = type.aliasElement;
      if (aliasElement != null) {
        _elements.add(aliasElement);
      }
    }
  }

  void _addTypesFromConstant(DartObject object) {
    final constant = ConstantReader(object);
    if (constant.isNull ||
        constant.isBool ||
        constant.isInt ||
        constant.isDouble ||
        constant.isString ||
        constant.isType) {
      // No types to add from a literal.
      return;
    } else if (constant.isList) {
      for (var element in constant.listValue) {
        _addTypesFromConstant(element);
      }
    } else if (constant.isSet) {
      for (var element in constant.setValue) {
        _addTypesFromConstant(element);
      }
    } else if (constant.isMap) {
      for (var pair in constant.mapValue.entries) {
        _addTypesFromConstant(pair.key!);
        _addTypesFromConstant(pair.value!);
      }
    } else if (object.toFunctionValue() != null) {
      _elements.add(object.toFunctionValue()!);
    } else {
      // If [constant] is not null, a literal, or a type, then it must be an
      // object constructed with `const`. Revive it.
      var revivable = constant.revive();
      for (var argument in revivable.positionalArguments) {
        _addTypesFromConstant(argument);
      }
      for (var pair in revivable.namedArguments.entries) {
        _addTypesFromConstant(pair.value);
      }
      _addType(object.type);
    }
  }
}

class _MockTarget {
  /// The class to be mocked.
  final analyzer.InterfaceType classType;

  /// The desired name of the mock class.
  final String mockName;

  final bool returnNullOnMissingStub;

  final Map<String, ExecutableElement> fallbackGenerators;

  _MockTarget(
    this.classType,
    this.mockName, {
    required this.returnNullOnMissingStub,
    required this.fallbackGenerators,
  });

  ClassElement get classElement => classType.element;
}

/// This class gathers and verifies mock targets referenced in `GenerateMocks`
/// annotations.
class _MockTargetGatherer {
  final LibraryElement _entryLib;

  final List<_MockTarget> _mockTargets;

  _MockTargetGatherer._(this._entryLib, this._mockTargets) {
    _checkClassesToMockAreValid();
  }

  /// Searches the top-level elements of [entryLib] for `GenerateMocks`
  /// annotations and creates a [_MockTargetGatherer] with all of the classes
  /// identified as mocking targets.
  factory _MockTargetGatherer(LibraryElement entryLib) {
    final mockTargets = <_MockTarget>{};

    for (final element in entryLib.topLevelElements) {
      // TODO(srawlins): Re-think the idea of multiple @GenerateMocks
      // annotations, on one element or even on different elements in a library.
      for (final annotation in element.metadata) {
        if (annotation == null) continue;
        if (annotation.element is! ConstructorElement) continue;
        final annotationClass = annotation.element!.enclosingElement!.name;
        // TODO(srawlins): check library as well.
        if (annotationClass == 'GenerateMocks') {
          mockTargets
              .addAll(_mockTargetsFromGenerateMocks(annotation, entryLib));
        }
      }
    }

    return _MockTargetGatherer._(entryLib, mockTargets.toList());
  }

  static Iterable<_MockTarget> _mockTargetsFromGenerateMocks(
      ElementAnnotation annotation, LibraryElement entryLib) {
    final generateMocksValue = annotation.computeConstantValue()!;
    final classesField = generateMocksValue.getField('classes')!;
    if (classesField.isNull) {
      throw InvalidMockitoAnnotationException(
          'The GenerateMocks "classes" argument is missing, includes an '
          'unknown type, or includes an extension');
    }
    final mockTargets = <_MockTarget>[];
    for (var objectToMock in classesField.toListValue()!) {
      final typeToMock = objectToMock.toTypeValue();
      if (typeToMock == null) {
        throw InvalidMockitoAnnotationException(
            'The "classes" argument includes a non-type: $objectToMock');
      }
      if (typeToMock.isDynamic) {
        throw InvalidMockitoAnnotationException(
            'Mockito cannot mock `dynamic`');
      }
      final type = _determineDartType(typeToMock, entryLib.typeProvider);
      // For a generic class like `Foo<T>` or `Foo<T extends num>`, a type
      // literal (`Foo`) cannot express type arguments. The type argument(s) on
      // `type` have been instantiated to bounds here. Switch to the
      // declaration, which will be an uninstantiated type.
      final declarationType =
          (type.element.declaration as ClassElement).thisType;
      final mockName = 'Mock${declarationType.element.name}';
      mockTargets.add(_MockTarget(declarationType, mockName,
          returnNullOnMissingStub: false, fallbackGenerators: {}));
    }
    final customMocksField = generateMocksValue.getField('customMocks');
    if (customMocksField != null && !customMocksField.isNull) {
      for (var mockSpec in customMocksField.toListValue()!) {
        final mockSpecType = mockSpec.type as analyzer.InterfaceType;
        assert(mockSpecType.typeArguments.length == 1);
        final typeToMock = mockSpecType.typeArguments.single;
        if (typeToMock.isDynamic) {
          throw InvalidMockitoAnnotationException(
              'Mockito cannot mock `dynamic`; be sure to declare type '
              'arguments on MockSpec(), in @GenerateMocks.');
        }
        var type = _determineDartType(typeToMock, entryLib.typeProvider);

        if (!type.hasExplicitTypeArguments) {
          // We assume the type was given without explicit type arguments. In
          // this case the type argument(s) on `type` have been instantiated to
          // bounds. Switch to the declaration, which will be an uninstantiated
          // type.
          type = (type.element.declaration as ClassElement).thisType;
        }
        final mockName = mockSpec.getField('mockName')!.toSymbolValue() ??
            'Mock${type.element.name}';
        final returnNullOnMissingStub =
            mockSpec.getField('returnNullOnMissingStub')!.toBoolValue()!;
        final fallbackGeneratorObjects =
            mockSpec.getField('fallbackGenerators')!.toMapValue()!;
        mockTargets.add(_MockTarget(type, mockName,
            returnNullOnMissingStub: returnNullOnMissingStub,
            fallbackGenerators:
                _extractFallbackGenerators(fallbackGeneratorObjects)));
      }
    }
    return mockTargets;
  }

  static Map<String, ExecutableElement> _extractFallbackGenerators(
      Map<DartObject?, DartObject?> objects) {
    final fallbackGenerators = <String, ExecutableElement>{};
    objects.forEach((methodName, generator) {
      if (methodName == null) {
        throw InvalidMockitoAnnotationException(
            'Unexpected null key in fallbackGenerators: $objects');
      }
      if (generator == null) {
        throw InvalidMockitoAnnotationException(
            'Unexpected null value in fallbackGenerators for key '
            '"$methodName"');
      }
      fallbackGenerators[methodName.toSymbolValue()!] =
          generator.toFunctionValue()!;
    });
    return fallbackGenerators;
  }

  /// Map the values passed to the GenerateMocks annotation to the classes which
  /// they represent.
  ///
  /// This function is responsible for ensuring that each value is an
  /// appropriate target for mocking. It will throw an
  /// [InvalidMockitoAnnotationException] under various conditions.
  static analyzer.InterfaceType _determineDartType(
      analyzer.DartType typeToMock, TypeProvider typeProvider) {
    if (typeToMock is analyzer.InterfaceType) {
      final elementToMock = typeToMock.element;
      if (elementToMock.isEnum) {
        throw InvalidMockitoAnnotationException(
            'Mockito cannot mock an enum: ${elementToMock.displayName}');
      }
      if (typeProvider.isNonSubtypableClass(elementToMock)) {
        throw InvalidMockitoAnnotationException(
            'Mockito cannot mock a non-subtypable type: '
            '${elementToMock.displayName}. It is illegal to subtype this '
            'type.');
      }
      if (elementToMock.isPrivate) {
        throw InvalidMockitoAnnotationException(
            'Mockito cannot mock a private type: '
            '${elementToMock.displayName}.');
      }
      var typeParameterErrors =
          _checkTypeParameters(elementToMock.typeParameters, elementToMock);
      if (typeParameterErrors.isNotEmpty) {
        var joinedMessages =
            typeParameterErrors.map((m) => '    $m').join('\n');
        throw InvalidMockitoAnnotationException(
            'Mockito cannot generate a valid mock class which implements '
            "'${elementToMock.displayName}' for the following reasons:\n"
            '$joinedMessages');
      }
      return typeToMock;
    }

    var aliasElement = typeToMock.aliasElement;
    if (aliasElement != null) {
      throw InvalidMockitoAnnotationException('Mockito cannot mock a typedef: '
          '${aliasElement.displayName}');
    } else {
      throw InvalidMockitoAnnotationException(
          'Mockito cannot mock a non-class: $typeToMock');
    }
  }

  void _checkClassesToMockAreValid() {
    final classesInEntryLib =
        _entryLib.topLevelElements.whereType<ClassElement>();
    final classNamesToMock = <String, _MockTarget>{};
    final uniqueNameSuggestion =
        "use the 'customMocks' argument in @GenerateMocks to specify a unique "
        'name';
    for (final mockTarget in _mockTargets) {
      final name = mockTarget.mockName;
      if (classNamesToMock.containsKey(name)) {
        final firstClass = classNamesToMock[name]!.classElement;
        final firstSource = firstClass.source.fullName;
        final secondSource = mockTarget.classElement.source.fullName;
        throw InvalidMockitoAnnotationException(
            'Mockito cannot generate two mocks with the same name: $name (for '
            '${firstClass.name} declared in $firstSource, and for '
            '${mockTarget.classElement.name} declared in $secondSource); '
            '$uniqueNameSuggestion.');
      }
      classNamesToMock[name] = mockTarget;
    }

    classNamesToMock.forEach((name, mockTarget) {
      var conflictingClass =
          classesInEntryLib.firstWhereOrNull((c) => c.name == name);
      if (conflictingClass != null) {
        throw InvalidMockitoAnnotationException(
            'Mockito cannot generate a mock with a name which conflicts with '
            'another class declared in this library: ${conflictingClass.name}; '
            '$uniqueNameSuggestion.');
      }

      var preexistingMock = classesInEntryLib.firstWhereOrNull((c) =>
          c.interfaces
              .map((type) => type.element)
              .contains(mockTarget.classElement) &&
          _isMockClass(c.supertype!));
      if (preexistingMock != null) {
        throw InvalidMockitoAnnotationException(
            'The GenerateMocks annotation contains a class which appears to '
            'already be mocked inline: ${preexistingMock.name}; '
            '$uniqueNameSuggestion.');
      }

      _checkMethodsToStubAreValid(mockTarget);
    });
  }

  /// Throws if any public instance methods of [classElement] are not valid
  /// stubbing candidates.
  ///
  /// A method is not valid for stubbing if:
  /// - It has a private type anywhere in its signature; Mockito cannot override
  ///   such a method.
  /// - It has a non-nullable type variable return type, for example `T m<T>()`,
  ///   and no corresponding dummy generator. Mockito cannot generate its own
  ///   dummy return values for unknown types.
  void _checkMethodsToStubAreValid(_MockTarget mockTarget) {
    final classElement = mockTarget.classElement;
    final className = classElement.name;
    final unstubbableErrorMessages = classElement.methods
        .where((m) => !m.isPrivate && !m.isStatic)
        .expand((m) => _checkFunction(m.type, m,
            hasDummyGenerator:
                mockTarget.fallbackGenerators.containsKey(m.name)))
        .toList();

    if (unstubbableErrorMessages.isNotEmpty) {
      var joinedMessages =
          unstubbableErrorMessages.map((m) => '    $m').join('\n');
      throw InvalidMockitoAnnotationException(
          'Mockito cannot generate a valid mock class which implements '
          "'$className' for the following reasons:\n$joinedMessages");
    }
  }

  /// Checks [function] for properties that would make it un-stubbable.
  ///
  /// Types are checked in the following positions:
  /// - return type
  /// - parameter types
  /// - bounds of type parameters
  /// - type arguments
  List<String> _checkFunction(
    analyzer.FunctionType function,
    Element enclosingElement, {
    bool isParameter = false,
    bool hasDummyGenerator = false,
  }) {
    final errorMessages = <String>[];
    final returnType = function.returnType;
    if (returnType is analyzer.InterfaceType) {
      if (returnType.element.isPrivate) {
        errorMessages.add(
            '${enclosingElement.fullName} features a private return type, and '
            'cannot be stubbed.');
      }
      errorMessages.addAll(
          _checkTypeArguments(returnType.typeArguments, enclosingElement));
    } else if (returnType is analyzer.FunctionType) {
      errorMessages.addAll(_checkFunction(returnType, enclosingElement));
    } else if (returnType is analyzer.TypeParameterType) {
      if (!isParameter &&
          !hasDummyGenerator &&
          _entryLib.typeSystem.isPotentiallyNonNullable(returnType)) {
        errorMessages
            .add('${enclosingElement.fullName} features a non-nullable unknown '
                'return type, and cannot be stubbed without a dummy generator '
                'specified on the MockSpec.');
      }
    }

    for (var parameter in function.parameters) {
      var parameterType = parameter.type;
      if (parameterType is analyzer.InterfaceType) {
        var parameterTypeElement = parameterType.element;
        if (parameterTypeElement.isPrivate) {
          // Technically, we can expand the type in the mock to something like
          // `Object?`. However, until there is a decent use case, we will not
          // generate such a mock.
          errorMessages.add(
              '${enclosingElement.fullName} features a private parameter type, '
              "'${parameterTypeElement.name}', and cannot be stubbed.");
        }
        errorMessages.addAll(
            _checkTypeArguments(parameterType.typeArguments, enclosingElement));
      } else if (parameterType is analyzer.FunctionType) {
        errorMessages.addAll(
            _checkFunction(parameterType, enclosingElement, isParameter: true));
      }
    }

    errorMessages
        .addAll(_checkTypeParameters(function.typeFormals, enclosingElement));

    var aliasArguments = function.aliasArguments;
    if (aliasArguments != null) {
      errorMessages
          .addAll(_checkTypeArguments(aliasArguments, enclosingElement));
    }

    return errorMessages;
  }

  /// Checks the bounds of [typeParameters] for properties that would make the
  /// enclosing method un-stubbable.
  static List<String> _checkTypeParameters(
      List<TypeParameterElement> typeParameters, Element enclosingElement) {
    var errorMessages = <String>[];
    for (var element in typeParameters) {
      var typeParameter = element.bound;
      if (typeParameter == null) continue;
      if (typeParameter is analyzer.InterfaceType) {
        if (typeParameter.element.isPrivate) {
          errorMessages.add(
              '${enclosingElement.fullName} features a private type parameter '
              'bound, and cannot be stubbed.');
        }
      }
    }
    return errorMessages;
  }

  /// Checks [typeArguments] for properties that would make the enclosing
  /// method un-stubbable.
  ///
  /// See [_checkMethodsToStubAreValid] for what properties make a function
  /// un-stubbable.
  List<String> _checkTypeArguments(
      List<analyzer.DartType> typeArguments, Element enclosingElement) {
    var errorMessages = <String>[];
    for (var typeArgument in typeArguments) {
      if (typeArgument is analyzer.InterfaceType) {
        if (typeArgument.element.isPrivate) {
          errorMessages.add(
              '${enclosingElement.fullName} features a private type argument, '
              'and cannot be stubbed.');
        }
      } else if (typeArgument is analyzer.FunctionType) {
        errorMessages.addAll(_checkFunction(typeArgument, enclosingElement));
      }
    }
    return errorMessages;
  }

  /// Return whether [type] is the Mock class declared by mockito.
  bool _isMockClass(analyzer.InterfaceType type) =>
      type.element.name == 'Mock' &&
      type.element.source.fullName.endsWith('lib/src/mock.dart');
}

class _MockLibraryInfo {
  /// Mock classes to be added to the generated library.
  final mockClasses = <Class>[];

  /// Fake classes to be added to the library.
  ///
  /// A fake class is only generated when it is needed for non-nullable return
  /// values.
  final fakeClasses = <Class>[];

  /// [ClassElement]s which are used in non-nullable return types, for which
  /// fake classes are added to the generated library.
  final fakedClassElements = <ClassElement>[];

  /// A mapping of each necessary [Element] to a URI from which it can be
  /// imported.
  ///
  /// This mapping is generated eagerly so as to avoid any asynchronous
  /// Asset-resolving while building the mock library.
  final Map<Element, String> assetUris;

  /// Build mock classes for [mockTargets].
  _MockLibraryInfo(
    Iterable<_MockTarget> mockTargets, {
    required this.assetUris,
    required LibraryElement entryLib,
  }) {
    for (final mockTarget in mockTargets) {
      final fallbackGenerators = mockTarget.fallbackGenerators;
      mockClasses.add(_MockClassInfo(
        mockTarget: mockTarget,
        sourceLibIsNonNullable: entryLib.isNonNullableByDefault,
        typeProvider: entryLib.typeProvider,
        typeSystem: entryLib.typeSystem,
        mockLibraryInfo: this,
        fallbackGenerators: fallbackGenerators,
      )._buildMockClass());
    }
  }
}

class _MockClassInfo {
  final _MockTarget mockTarget;

  final bool sourceLibIsNonNullable;

  /// The type provider which applies to the source library.
  final TypeProvider typeProvider;

  /// The type system which applies to the source library.
  final TypeSystem typeSystem;

  final _MockLibraryInfo mockLibraryInfo;

  /// A mapping of any fallback generators specified for the classes-to-mock.
  ///
  /// Each value is another mapping from method names to the generator
  /// function elements.
  final Map<String, ExecutableElement> fallbackGenerators;

  _MockClassInfo({
    required this.mockTarget,
    required this.sourceLibIsNonNullable,
    required this.typeProvider,
    required this.typeSystem,
    required this.mockLibraryInfo,
    required this.fallbackGenerators,
  });

  Class _buildMockClass() {
    final typeToMock = mockTarget.classType;
    final classToMock = mockTarget.classElement;
    final classIsImmutable = classToMock.metadata.any((it) => it.isImmutable);
    final className = classToMock.name;

    return Class((cBuilder) {
      cBuilder
        ..name = mockTarget.mockName
        ..extend = referImported('Mock', 'package:mockito/mockito.dart')
        // TODO(srawlins): Refer to [classToMock] properly, which will yield the
        // appropriate import prefix.
        ..docs.add('/// A class which mocks [$className].')
        ..docs.add('///')
        ..docs.add('/// See the documentation for Mockito\'s code generation '
            'for more information.');
      if (classIsImmutable) {
        cBuilder.docs.add('// ignore: must_be_immutable');
      }
      // For each type parameter on [classToMock], the Mock class needs a type
      // parameter with same type variables, and a mirrored type argument for
      // the "implements" clause.
      var typeArguments = <Reference>[];
      if (typeToMock.hasExplicitTypeArguments) {
        // [typeToMock] is a reference to a type with type arguments (for
        // example: `Foo<int>`). Generate a non-generic mock class which
        // implements the mock target with said type arguments. For example:
        // `class MockFoo extends Mock implements Foo<int> {}`
        for (var typeArgument in typeToMock.typeArguments) {
          typeArguments.add(referImported(
              typeArgument.getDisplayString(
                  withNullability: sourceLibIsNonNullable),
              _typeImport(typeArgument.element)));
        }
      } else if (classToMock.typeParameters != null) {
        // [typeToMock] is a simple reference to a generic type (for example:
        // `Foo`, a reference to `class Foo<T> {}`). Generate a generic mock
        // class which perfectly mirrors the type parameters on [typeToMock],
        // forwarding them to the "implements" clause.
        for (var typeParameter in classToMock.typeParameters) {
          cBuilder.types.add(_typeParameterReference(typeParameter));
          typeArguments.add(refer(typeParameter.name));
        }
      }
      cBuilder.implements.add(TypeReference((b) {
        b
          ..symbol = classToMock.name
          ..url = _typeImport(mockTarget.classElement)
          ..types.addAll(typeArguments);
      }));
      if (!mockTarget.returnNullOnMissingStub) {
        cBuilder.constructors.add(_constructorWithThrowOnMissingStub);
      }

      // Only override members of a class declared in a library which uses the
      // non-nullable type system.
      if (!sourceLibIsNonNullable) {
        return;
      }
      cBuilder.methods.addAll(fieldOverrides(typeToMock, {}));
      cBuilder.methods.addAll(methodOverrides(typeToMock, {}));
    });
  }

  /// Yields all of the field overrides required for [type].
  ///
  /// This includes fields of supertypes and mixed in types. [overriddenFields]
  /// is used to track which fields have already been yielded.
  ///
  /// Only public instance fields which have either a potentially non-nullable
  /// return type (for getters) or a parameter with a potentially non-nullable
  /// type (for setters) are yielded.
  Iterable<Method> fieldOverrides(
      analyzer.InterfaceType type, Set<String> overriddenFields) sync* {
    for (final accessor in type.accessors) {
      if (accessor.isPrivate || accessor.isStatic) {
        continue;
      }
      if (overriddenFields.contains(accessor.name)) {
        continue;
      }
      if (accessor.name == 'hashCode') {
        // Never override this getter; user code cannot narrow the return type.
        continue;
      }
      overriddenFields.add(accessor.name);
      if (accessor.isGetter && _returnTypeIsNonNullable(accessor)) {
        yield Method((mBuilder) => _buildOverridingGetter(mBuilder, accessor));
      }
      if (accessor.isSetter) {
        yield Method((mBuilder) => _buildOverridingSetter(mBuilder, accessor));
      }
    }
    if (type.mixins != null) {
      for (var mixin in type.mixins) {
        yield* fieldOverrides(mixin, overriddenFields);
      }
    }
    if (type.interfaces != null) {
      for (var interface in type.interfaces) {
        yield* fieldOverrides(interface, overriddenFields);
      }
    }
    var superclass = type.superclass;
    if (superclass != null && !superclass.isDartCoreObject) {
      yield* fieldOverrides(superclass, overriddenFields);
    }
  }

  /// Yields all of the method overrides required for [type].
  ///
  /// This includes methods of supertypes and mixed in types.
  /// [overriddenMethods] is used to track which methods have already been
  /// yielded.
  ///
  /// Only public instance methods which have either a potentially non-nullable
  /// return type or a parameter with a potentially non-nullable type are
  /// yielded.
  Iterable<Method> methodOverrides(
      analyzer.InterfaceType type, Set<String> overriddenMethods) sync* {
    for (final method in type.methods) {
      if (method.isPrivate || method.isStatic) {
        continue;
      }
      var methodName = method.name;
      if (overriddenMethods.contains(methodName)) {
        continue;
      }
      overriddenMethods.add(methodName);
      if (methodName == 'noSuchMethod') {
        continue;
      }
      if (methodName == '==') {
        // Never override this operator; user code cannot add parameters or
        // narrow the return type.
        continue;
      }
      if (_returnTypeIsNonNullable(method) ||
          _hasNonNullableParameter(method) ||
          _needsOverrideForVoidStub(method)) {
        yield Method((mBuilder) => _buildOverridingMethod(mBuilder, method));
      }
    }
    if (type.mixins != null) {
      for (var mixin in type.mixins) {
        yield* methodOverrides(mixin, overriddenMethods);
      }
    }
    if (type.interfaces != null) {
      for (var interface in type.interfaces) {
        yield* methodOverrides(interface, overriddenMethods);
      }
    }
    var superclass = type.superclass;
    if (superclass != null && !superclass.isDartCoreObject) {
      yield* methodOverrides(superclass, overriddenMethods);
    }
  }

  /// The default behavior of mocks is to return null for unstubbed methods. To
  /// use the new behavior of throwing an error, we must explicitly call
  /// `throwOnMissingStub`.
  Constructor get _constructorWithThrowOnMissingStub =>
      Constructor((cBuilder) => cBuilder.body =
          referImported('throwOnMissingStub', 'package:mockito/mockito.dart')
              .call([refer('this').expression]).statement);

  bool _returnTypeIsNonNullable(ExecutableElement method) =>
      typeSystem.isPotentiallyNonNullable(method.returnType);

  bool _needsOverrideForVoidStub(ExecutableElement method) =>
      method.returnType.isVoid || method.returnType.isFutureOfVoid;

  // Returns whether [method] has at least one parameter whose type is
  // potentially non-nullable.
  //
  // A parameter whose type uses a type variable may be non-nullable on certain
  // instances. For example:
  //
  //     class C<T> {
  //       void m(T a) {}
  //     }
  //     final c1 = C<int?>(); // m's parameter's type is nullable.
  //     final c2 = C<int>(); // m's parameter's type is non-nullable.
  bool _hasNonNullableParameter(ExecutableElement method) =>
      method.parameters.any((p) => typeSystem.isPotentiallyNonNullable(p.type));

  /// Build a method which overrides [method], with all non-nullable
  /// parameter types widened to be nullable.
  ///
  /// This new method just calls `super.noSuchMethod`, optionally passing a
  /// return value for methods with a non-nullable return type.
  void _buildOverridingMethod(MethodBuilder builder, MethodElement method) {
    var name = method.displayName;
    if (method.isOperator) name = 'operator$name';
    builder
      ..name = name
      ..annotations.addAll([refer('override')])
      ..returns = _typeReference(method.returnType);

    if (method.typeParameters != null) {
      builder.types.addAll(method.typeParameters.map(_typeParameterReference));
    }

    // These two variables store the arguments that will be passed to the
    // [Invocation] built for `noSuchMethod`.
    final invocationPositionalArgs = <Expression>[];
    final invocationNamedArgs = <Expression, Expression>{};

    for (final parameter in method.parameters) {
      if (parameter.isRequiredPositional) {
        builder.requiredParameters
            .add(_matchingParameter(parameter, forceNullable: true));
        invocationPositionalArgs.add(refer(parameter.displayName));
      } else if (parameter.isOptionalPositional) {
        builder.optionalParameters
            .add(_matchingParameter(parameter, forceNullable: true));
        invocationPositionalArgs.add(refer(parameter.displayName));
      } else if (parameter.isNamed) {
        builder.optionalParameters
            .add(_matchingParameter(parameter, forceNullable: true));
        invocationNamedArgs[refer('#${parameter.displayName}')] =
            refer(parameter.displayName);
      }
    }

    if (name == 'toString') {
      // We cannot call `super.noSuchMethod` here; we must use [Mock]'s
      // implementation.
      builder.body = refer('super').property('toString').call([]).code;
      return;
    }

    final invocation = refer('Invocation').property('method').call([
      refer('#${method.displayName}'),
      literalList(invocationPositionalArgs),
      if (invocationNamedArgs.isNotEmpty) literalMap(invocationNamedArgs),
    ]);

    Expression? returnValueForMissingStub;
    if (method.returnType.isVoid) {
      returnValueForMissingStub = refer('null');
    } else if (method.returnType.isFutureOfVoid) {
      returnValueForMissingStub = _futureReference().property('value').call([]);
    }
    final fallbackGenerator = fallbackGenerators[method.name];
    final namedArgs = {
      if (fallbackGenerator != null)
        'returnValue': _fallbackGeneratorCode(method, fallbackGenerator)
      else if (_returnTypeIsNonNullable(method))
        'returnValue': _dummyValue(method.returnType),
      if (returnValueForMissingStub != null)
        'returnValueForMissingStub': returnValueForMissingStub,
    };

    var superNoSuchMethod =
        refer('super').property('noSuchMethod').call([invocation], namedArgs);
    if (!method.returnType.isVoid && !method.returnType.isDynamic) {
      superNoSuchMethod =
          superNoSuchMethod.asA(_typeReference(method.returnType));
    }

    builder.body = superNoSuchMethod.code;
  }

  Expression _fallbackGeneratorCode(
      MethodElement method, ExecutableElement function) {
    final positionalArguments = <Expression>[];
    final namedArguments = <String, Expression>{};
    for (final parameter in method.parameters) {
      if (parameter.isPositional) {
        positionalArguments.add(refer(parameter.name));
      } else if (parameter.isNamed) {
        namedArguments[parameter.name] = refer(parameter.name);
      }
    }
    final functionReference =
        referImported(function.name, _typeImport(function));
    return functionReference.call(positionalArguments, namedArguments,
        [for (var t in method.typeParameters) refer(t.name)]);
  }

  Expression _dummyValue(analyzer.DartType type) {
    if (type is analyzer.FunctionType) {
      return _dummyFunctionValue(type);
    }

    if (type is! analyzer.InterfaceType) {
      // TODO(srawlins): This case is not known.
      return literalNull;
    }

    var typeArguments = type.typeArguments;
    if (type.isDartCoreBool) {
      return literalFalse;
    } else if (type.isDartCoreDouble) {
      return literalNum(0.0);
    } else if (type.isDartAsyncFuture || type.isDartAsyncFutureOr) {
      final typeArgument = typeArguments.first;
      final futureValueArguments =
          typeSystem.isPotentiallyNonNullable(typeArgument)
              ? [_dummyValue(typeArgument)]
              : <Expression>[];
      return _futureReference(_typeReference(typeArgument))
          .property('value')
          .call(futureValueArguments);
    } else if (type.isDartCoreInt) {
      return literalNum(0);
    } else if (type.isDartCoreIterable) {
      return literalList([]);
    } else if (type.isDartCoreList) {
      assert(typeArguments.length == 1);
      var elementType = _typeReference(typeArguments[0]);
      return literalList([], elementType);
    } else if (type.isDartCoreMap) {
      assert(typeArguments.length == 2);
      var keyType = _typeReference(typeArguments[0]);
      var valueType = _typeReference(typeArguments[1]);
      return literalMap({}, keyType, valueType);
    } else if (type.isDartCoreNum) {
      return literalNum(0);
    } else if (type.isDartCoreSet) {
      assert(typeArguments.length == 1);
      var elementType = _typeReference(typeArguments[0]);
      return literalSet({}, elementType);
    } else if (type.element.declaration == typeProvider.streamElement) {
      assert(typeArguments.length == 1);
      var elementType = _typeReference(typeArguments[0]);
      return TypeReference((b) {
        b
          ..symbol = 'Stream'
          ..types.add(elementType);
      }).property('empty').call([]);
    } else if (type.isDartCoreString) {
      return literalString('');
    } else if (type.isDartTypedDataList) {
      // These "List" types from dart:typed_data are "non-subtypeable", but they
      // have predicatble constructors; each has an unnamed constructor which
      // takes a single int argument.
      return referImported(type.displayName, 'dart:typed_data')
          .call([literalNum(0)]);
      // TODO(srawlins): Do other types from typed_data have a "non-subtypeable"
      // restriction as well?
    }

    // This class is unknown; we must likely generate a fake class, and return
    // an instance here.
    return _dummyValueImplementing(type);
  }

  /// Returns a reference to [Future], optionally with a type argument for the
  /// value of the Future.
  TypeReference _futureReference([Reference? valueType]) => TypeReference((b) {
        b.symbol = 'Future';
        if (valueType != null) {
          b.types.add(valueType);
        }
      });

  Expression _dummyFunctionValue(analyzer.FunctionType type) {
    return Method((b) {
      // The positional parameters in a FunctionType have no names. This
      // counter lets us create unique dummy names.
      var counter = 0;
      if (type.typeFormals != null) {
        b.types.addAll(type.typeFormals.map(_typeParameterReference));
      }
      for (final parameter in type.parameters) {
        if (parameter.isRequiredPositional) {
          b.requiredParameters
              .add(_matchingParameter(parameter, defaultName: '__p$counter'));
          counter++;
        } else if (parameter.isOptionalPositional) {
          b.optionalParameters
              .add(_matchingParameter(parameter, defaultName: '__p$counter'));
          counter++;
        } else if (parameter.isNamed) {
          b.optionalParameters.add(_matchingParameter(parameter));
        }
      }
      if (type.returnType.isVoid) {
        b.body = Code('');
      } else {
        b.body = _dummyValue(type.returnType).code;
      }
    }).genericClosure;
  }

  Expression _dummyValueImplementing(analyzer.InterfaceType dartType) {
    final elementToFake = dartType.element;
    if (elementToFake.isEnum) {
      return _typeReference(dartType).property(
          elementToFake.fields.firstWhere((f) => f.isEnumConstant).name);
    } else {
      // There is a potential for these names to collide. If one mock class
      // requires a fake for a certain Foo, and another mock class requires a
      // fake for a different Foo, they will collide.
      final fakeName = '_Fake${elementToFake.name}';
      // Only make one fake class for each class that needs to be faked.
      if (!mockLibraryInfo.fakedClassElements.contains(elementToFake)) {
        _addFakeClass(fakeName, elementToFake);
      }
      final typeArguments = dartType.typeArguments;
      return TypeReference((b) {
        b
          ..symbol = fakeName
          ..types.addAll(typeArguments.map(_typeReference));
      }).newInstance([]);
    }
  }

  /// Adds a [Fake] implementation of [elementToFake], named [fakeName].
  void _addFakeClass(String fakeName, ClassElement elementToFake) {
    mockLibraryInfo.fakeClasses.add(Class((cBuilder) {
      // For each type parameter on [elementToFake], the Fake class needs a type
      // parameter with same type variables, and a mirrored type argument for
      // the "implements" clause.
      final typeParameters = <Reference>[];
      cBuilder
        ..name = fakeName
        ..extend = referImported('Fake', 'package:mockito/mockito.dart');
      if (elementToFake.typeParameters != null) {
        for (var typeParameter in elementToFake.typeParameters) {
          cBuilder.types.add(_typeParameterReference(typeParameter));
          typeParameters.add(refer(typeParameter.name));
        }
      }
      cBuilder.implements.add(TypeReference((b) {
        b
          ..symbol = elementToFake.name
          ..url = _typeImport(elementToFake)
          ..types.addAll(typeParameters);
      }));

      final toStringMethod = elementToFake.methods
          .firstWhereOrNull((method) => method.name == 'toString');
      if (toStringMethod != null) {
        // If [elementToFake] includes an overriding `toString` implementation,
        // we need to include an implementation which matches the signature.
        cBuilder.methods.add(Method(
            (mBuilder) => _buildOverridingMethod(mBuilder, toStringMethod)));
      }
    }));
    mockLibraryInfo.fakedClassElements.add(elementToFake);
  }

  /// Returns a [Parameter] which matches [parameter].
  ///
  /// If [parameter] is unnamed (like a positional parameter in a function
  /// type), a [defaultName] can be passed as the name.
  ///
  /// If the type needs to be nullable, rather than matching the nullability of
  /// [parameter], use [forceNullable].
  Parameter _matchingParameter(ParameterElement parameter,
      {String? defaultName, bool forceNullable = false}) {
    assert(
        parameter.name.isNotEmpty || defaultName != null,
        'parameter must have a non-empty name, or non-null defaultName must be '
        'passed, but parameter name is "${parameter.name}" and defaultName is '
        '$defaultName');
    var name = parameter.name.isEmpty ? defaultName! : parameter.name;
    return Parameter((pBuilder) {
      pBuilder
        ..name = name
        ..type = _typeReference(parameter.type, forceNullable: forceNullable);
      if (parameter.isNamed) pBuilder.named = true;
      if (parameter.defaultValueCode != null) {
        try {
          pBuilder.defaultTo =
              _expressionFromDartObject(parameter.computeConstantValue()!).code;
        } on _ReviveException catch (e) {
          final method = parameter.enclosingElement!;
          final clazz = method.enclosingElement!;
          throw InvalidMockitoAnnotationException(
              'Mockito cannot generate a valid stub for method '
              "'${clazz.displayName}.${method.displayName}'; parameter "
              "'${parameter.displayName}' causes a problem: ${e.message}");
        }
      }
    });
  }

  /// Creates a code_builder [Expression] from [object], a constant object from
  /// analyzer.
  ///
  /// This is very similar to Angular's revive code, in
  /// angular_compiler/analyzer/di/injector.dart.
  Expression _expressionFromDartObject(DartObject object) {
    final constant = ConstantReader(object);
    if (constant.isNull) {
      return literalNull;
    } else if (constant.isBool) {
      return literalBool(constant.boolValue);
    } else if (constant.isDouble) {
      return literalNum(constant.doubleValue);
    } else if (constant.isInt) {
      return literalNum(constant.intValue);
    } else if (constant.isString) {
      return literalString(constant.stringValue, raw: true);
    } else if (constant.isList) {
      return literalConstList([
        for (var element in constant.listValue)
          _expressionFromDartObject(element)
      ]);
    } else if (constant.isMap) {
      return literalConstMap({
        for (var pair in constant.mapValue.entries)
          _expressionFromDartObject(pair.key!):
              _expressionFromDartObject(pair.value!)
      });
    } else if (constant.isSet) {
      return literalConstSet({
        for (var element in constant.setValue)
          _expressionFromDartObject(element)
      });
    } else if (constant.isType) {
      // TODO(srawlins): It seems like this might be revivable, but Angular
      // does not revive Types; we should investigate this if users request it.
      var type = object.toTypeValue()!;
      var typeStr = type.getDisplayString(withNullability: false);
      throw _ReviveException('default value is a Type: $typeStr.');
    } else {
      // If [constant] is not null, a literal, or a type, then it must be an
      // object constructed with `const`. Revive it.
      var revivable = constant.revive();
      if (revivable.isPrivate) {
        final privateReference = revivable.accessor.isNotEmpty
            ? '${revivable.source}::${revivable.accessor}'
            : '${revivable.source}';
        throw _ReviveException(
            'default value has a private type: $privateReference.');
      }
      if (object.toFunctionValue() != null) {
        // A top-level function, like `void f() {}` must be referenced by its
        // identifier, rather than a revived value.
        var element = object.toFunctionValue();
        return referImported(revivable.accessor, _typeImport(element));
      } else if (revivable.source.fragment.isEmpty) {
        // We can create this invocation by referring to a const field or
        // top-level variable.
        return referImported(
            revivable.accessor, _typeImport(object.type!.element));
      }

      final name = revivable.source.fragment;
      final positionalArgs = [
        for (var argument in revivable.positionalArguments)
          _expressionFromDartObject(argument)
      ];
      final namedArgs = {
        for (var pair in revivable.namedArguments.entries)
          pair.key: _expressionFromDartObject(pair.value)
      };
      final type = referImported(name, _typeImport(object.type!.element));
      if (revivable.accessor.isNotEmpty) {
        return type.constInstanceNamed(
          revivable.accessor,
          positionalArgs,
          namedArgs,
          // No type arguments. See
          // https://github.com/dart-lang/source_gen/issues/478.
        );
      }
      return type.constInstance(positionalArgs, namedArgs);
    }
  }

  /// Build a getter which overrides [getter].
  ///
  /// This new method just calls `super.noSuchMethod`, optionally passing a
  /// return value for non-nullable getters.
  void _buildOverridingGetter(
      MethodBuilder builder, PropertyAccessorElement getter) {
    builder
      ..name = getter.displayName
      ..annotations.addAll([refer('override')])
      ..type = MethodType.getter
      ..returns = _typeReference(getter.returnType);

    final invocation = refer('Invocation').property('getter').call([
      refer('#${getter.displayName}'),
    ]);
    final namedArgs = {'returnValue': _dummyValue(getter.returnType)};
    var superNoSuchMethod =
        refer('super').property('noSuchMethod').call([invocation], namedArgs);
    if (!getter.returnType.isVoid && !getter.returnType.isDynamic) {
      superNoSuchMethod =
          superNoSuchMethod.asA(_typeReference(getter.returnType));
    }

    builder.body = superNoSuchMethod.code;
  }

  /// Build a setter which overrides [setter], widening the single parameter
  /// type to be nullable if it is non-nullable.
  ///
  /// This new setter just calls `super.noSuchMethod`.
  void _buildOverridingSetter(
      MethodBuilder builder, PropertyAccessorElement setter) {
    builder
      ..name = setter.displayName
      ..annotations.addAll([refer('override')])
      ..type = MethodType.setter;

    assert(setter.parameters.length == 1);
    final parameter = setter.parameters.single;
    builder.requiredParameters.add(Parameter((pBuilder) => pBuilder
      ..name = parameter.displayName
      ..type = _typeReference(parameter.type, forceNullable: true)));
    final invocationPositionalArg = refer(parameter.displayName);

    final invocation = refer('Invocation').property('setter').call([
      refer('#${setter.displayName}'),
      invocationPositionalArg,
    ]);
    final returnNoSuchMethod = refer('super')
        .property('noSuchMethod')
        .call([invocation], {'returnValueForMissingStub': refer('null')});

    builder.body = returnNoSuchMethod.code;
  }

  /// Create a reference for [typeParameter], properly referencing all types
  /// in bounds.
  TypeReference _typeParameterReference(TypeParameterElement typeParameter) {
    return TypeReference((b) {
      b.symbol = typeParameter.name;
      if (typeParameter.bound != null) {
        b.bound = _typeReference(typeParameter.bound!);
      }
    });
  }

  /// Create a reference for [type], properly referencing all attached types.
  ///
  /// If the type needs to be nullable, rather than matching the nullability of
  /// [type], use [forceNullable].
  ///
  /// This creates proper references for:
  /// * InterfaceTypes (classes, generic classes),
  /// * FunctionType parameters (like `void callback(int i)`),
  /// * type aliases (typedefs), both new- and old-style,
  /// * enums,
  /// * type variables.
  // TODO(srawlins): Contribute this back to a common location, like
  // package:source_gen?
  Reference _typeReference(analyzer.DartType type,
      {bool forceNullable = false}) {
    if (type is analyzer.InterfaceType) {
      return TypeReference((b) {
        b
          ..symbol = type.element.name
          ..isNullable = forceNullable || typeSystem.isPotentiallyNullable(type)
          ..url = _typeImport(type.element)
          ..types.addAll(type.typeArguments.map(_typeReference));
      });
    } else if (type is analyzer.FunctionType) {
      final element = type.aliasElement;
      if (element == null || element.isPrivate) {
        // [type] does not refer to a type alias, or it refers to a private type
        // alias; we must instead write out its signature.
        return FunctionType((b) {
          b
            ..isNullable =
                forceNullable || typeSystem.isPotentiallyNullable(type)
            ..returnType = _typeReference(type.returnType)
            ..requiredParameters
                .addAll(type.normalParameterTypes.map(_typeReference))
            ..optionalParameters
                .addAll(type.optionalParameterTypes.map(_typeReference));
          for (var parameter in type.namedParameterTypes.entries) {
            b.namedParameters[parameter.key] = _typeReference(parameter.value);
          }
          if (type.typeFormals != null) {
            b.types.addAll(type.typeFormals.map(_typeParameterReference));
          }
        });
      }
      return TypeReference((b) {
        b
          ..symbol = element.name
          ..url = _typeImport(element)
          ..isNullable = forceNullable || typeSystem.isNullable(type);
        for (var typeArgument in type.aliasArguments!) {
          b.types.add(_typeReference(typeArgument));
        }
      });
    } else if (type is analyzer.TypeParameterType) {
      return TypeReference((b) {
        b
          ..symbol = type.element.name
          ..isNullable = forceNullable || typeSystem.isNullable(type);
      });
    } else {
      return referImported(
        type.getDisplayString(withNullability: false),
        _typeImport(type.element),
      );
    }
  }

  /// Returns the import URL for [element].
  ///
  /// For some types, like `dynamic` and type variables, this may return null.
  String? _typeImport(Element? element) {
    // For type variables, no import needed.
    if (element is TypeParameterElement) return null;

    // For types like `dynamic`, return null; no import needed.
    if (element?.library == null) return null;

    assert(mockLibraryInfo.assetUris.containsKey(element),
        'An element, "$element", is missing from the asset URI mapping');

    return mockLibraryInfo.assetUris[element]!;
  }

  /// Returns a [Reference] to [symbol] with [url].
  ///
  /// This function overrides [code_builder.refer] so as to ensure that [url] is
  /// given.
  static Reference referImported(String symbol, String? url) =>
      Reference(symbol, url);

  /// Returns a [Reference] to [symbol] with no URL.
  static Reference refer(String symbol) => Reference(symbol);
}

/// An exception thrown when reviving a potentially deep value in a constant.
///
/// This exception should always be caught within this library. An
/// [InvalidMockitoAnnotationException] can be presented to the user after
/// catching this exception.
class _ReviveException implements Exception {
  final String message;

  _ReviveException(this.message);
}

/// An exception which is thrown when Mockito encounters an invalid annotation.
class InvalidMockitoAnnotationException implements Exception {
  final String message;

  InvalidMockitoAnnotationException(this.message);

  @override
  String toString() => 'Invalid @GenerateMocks annotation: $message';
}

/// A [MockBuilder] instance for use by `build.yaml`.
Builder buildMocks(BuilderOptions options) => MockBuilder();

extension on Element {
  /// Returns the "full name" of a class or method element.
  String get fullName {
    if (this is ClassElement) {
      return "The class '$name'";
    } else if (this is MethodElement) {
      var className = enclosingElement!.name;
      return "The method '$className.$name'";
    } else {
      return 'unknown element';
    }
  }
}

extension on analyzer.DartType {
  /// Returns whether this type is `Future<void>` or `Future<void>?`.
  bool get isFutureOfVoid =>
      isDartAsyncFuture &&
      (this as analyzer.InterfaceType).typeArguments.first.isVoid;

  /// Returns whether this type is a "List" type from the dart:typed_data
  /// library.
  bool get isDartTypedDataList {
    if (element!.library!.name != 'dart.typed_data') {
      return false;
    }
    final name = element!.name;
    return name == 'Float32List' ||
        name == 'Float64List' ||
        name == 'Int8List' ||
        name == 'Int16List' ||
        name == 'Int32List' ||
        name == 'Int64List' ||
        name == 'Uint8List' ||
        name == 'Uint16List' ||
        name == 'Uint32List' ||
        name == 'Uint64List';
  }
}

extension on analyzer.InterfaceType {
  bool get hasExplicitTypeArguments {
    if (typeArguments == null) return false;

    // If it appears that one type argument was given, then they all were. This
    // returns the wrong result when the type arguments given are all `dynamic`,
    // or are each equal to the bound of the corresponding type parameter. There
    // may not be a way to get around this.
    for (var i = 0; i < typeArguments.length; i++) {
      final typeArgument = typeArguments[i];
      // If [typeArgument] is a type parameter, this indicates that no type
      // arguments were passed. This likely came from the 'classes' argument of
      // GenerateMocks, and [type] is the declaration type (`Foo<T>` vs
      // `Foo<dynamic>`).
      if (typeArgument is analyzer.TypeParameterType) return false;

      // If [type] was given to @GenerateMocks as a Type, and no explicit type
      // argument is given, [typeArgument] is `dynamic` (_not_ the bound, as one
      // might think). We determine that an explicit type argument was given if
      // it is not `dynamic`.
      if (typeArgument.isDynamic) continue;

      // If, on the other hand, [type] was given to @GenerateMock as a type
      // argument to `MockSpec()`, and no type argument is given, [typeArgument]
      // is the bound of the corresponding type paramter (`dynamic` or
      // otherwise). We determine that an explicit type argument was given if
      // [typeArgument] is not equal to [bound].
      final bound = element.typeParameters[i].bound;
      if (!typeArgument.isDynamic && typeArgument != bound) return true;
    }
    return false;
  }
}
