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

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/testing/element_search.dart';
import 'package:test/test.dart';

/// Search the [unit] for the [LocalVariableElement] with the given [name].
/// Fail if there is not exactly one such variable.
FunctionElement findLocalFunction(CompilationUnit unit, String name) {
  List<Element> elements = findElementsByName(unit, name);
  List<Element> functions = elements.whereType<FunctionElement>().toList();
  expect(functions, hasLength(1));
  return functions[0];
}

/// Search the [unit] for the [LocalVariableElement] with the given [name].
/// Fail if there is not exactly one such variable.
LocalVariableElement findLocalVariable(CompilationUnit unit, String name) {
  List<Element> elements = findElementsByName(unit, name);
  List<Element> localVariables =
      elements.whereType<LocalVariableElement>().toList();
  expect(localVariables, hasLength(1));
  return localVariables[0];
}

/// The type of an assertion which asserts properties of [T]s.
typedef Asserter<T> = void Function(T type);

/// The type of a function which given an [S], builds an assertion over [T]s.
typedef AsserterBuilder<S, T> = Asserter<T> Function(S arg);

/// The type of a function which given an [S0] and an S1, builds an assertion
/// over [T]s.
typedef AsserterBuilder2<S0, S1, T> = Asserter<T> Function(S0 arg0, S1 arg1);

/// The type of a function which given an [R] returns an [AsserterBuilder] over
/// [S]s and [T]s.  That is, it returns a function which given an [S], returns
/// a function over [T]s.
typedef AsserterBuilderBuilder<R, S, T> = AsserterBuilder<S, T> Function(R arg);

class AstFinder {
  /// Return the declaration of the class with the given [className] in the
  /// given compilation [unit].
  static ClassDeclaration getClass(CompilationUnit unit, String className) {
    NodeList<CompilationUnitMember> unitMembers = unit.declarations;
    for (CompilationUnitMember unitMember in unitMembers) {
      if (unitMember is ClassDeclaration && unitMember.name.name == className) {
        return unitMember;
      }
    }
    Source source = unit.declaredElement.source;
    fail('No class named $className in $source');
  }

  /// Return the declaration of the constructor with the given [constructorName]
  /// in the class with the given [className] in the given compilation [unit].
  /// If constructorName is null, return the default constructor;
  static ConstructorDeclaration getConstructorInClass(
      CompilationUnit unit, String className, String constructorName) {
    ClassDeclaration unitMember = getClass(unit, className);
    NodeList<ClassMember> classMembers = unitMember.members;
    for (ClassMember classMember in classMembers) {
      if (classMember is ConstructorDeclaration) {
        if (classMember.name?.name == constructorName) {
          return classMember;
        }
      }
    }
    fail('No constructor named $constructorName in $className');
  }

  /// Return the declaration of the field with the given [fieldName] in the
  /// class with the given [className] in the given compilation [unit].
  static VariableDeclaration getFieldInClass(
      CompilationUnit unit, String className, String fieldName) {
    ClassDeclaration unitMember = getClass(unit, className);
    NodeList<ClassMember> classMembers = unitMember.members;
    for (ClassMember classMember in classMembers) {
      if (classMember is FieldDeclaration) {
        NodeList<VariableDeclaration> fields = classMember.fields.variables;
        for (VariableDeclaration field in fields) {
          if (field.name.name == fieldName) {
            return field;
          }
        }
      }
    }
    fail('No field named $fieldName in $className');
  }

  /// Return the element of the field with the given [fieldName] in the class
  /// with the given [className] in the given compilation [unit].
  static FieldElement getFieldInClassElement(
      CompilationUnit unit, String className, String fieldName) {
    return getFieldInClass(unit, className, fieldName)?.name?.staticElement;
  }

  /// Return the declaration of the method with the given [methodName] in the
  /// class with the given [className] in the given compilation [unit].
  static MethodDeclaration getMethodInClass(
      CompilationUnit unit, String className, String methodName) {
    ClassDeclaration unitMember = getClass(unit, className);
    NodeList<ClassMember> classMembers = unitMember.members;
    for (ClassMember classMember in classMembers) {
      if (classMember is MethodDeclaration) {
        if (classMember.name.name == methodName) {
          return classMember;
        }
      }
    }
    fail('No method named $methodName in $className');
  }

  /// Return the statements in the body of a the method with the given
  /// [methodName] in the class with the given [className] in the given
  /// compilation [unit].
  static List<Statement> getStatementsInMethod(
      CompilationUnit unit, String className, String methodName) {
    MethodDeclaration method = getMethodInClass(unit, className, methodName);
    BlockFunctionBody body = method.body;
    return body.block.statements;
  }

  /// Return the statements in the body of the top-level function with the given
  /// [functionName] in the given compilation [unit].
  static List<Statement> getStatementsInTopLevelFunction(
      CompilationUnit unit, String functionName) {
    FunctionDeclaration function = getTopLevelFunction(unit, functionName);
    BlockFunctionBody body = function.functionExpression.body;
    return body.block.statements;
  }

  /// Return the declaration of the top-level function with the given
  /// [functionName] in the given compilation [unit].
  static FunctionDeclaration getTopLevelFunction(
      CompilationUnit unit, String functionName) {
    NodeList<CompilationUnitMember> unitMembers = unit.declarations;
    for (CompilationUnitMember unitMember in unitMembers) {
      if (unitMember is FunctionDeclaration) {
        if (unitMember.name.name == functionName) {
          return unitMember;
        }
      }
    }
    fail('No toplevel function named $functionName found');
  }

  /// Return the declaration of the top-level variable with the given
  /// [variableName] in the given compilation [unit].
  static VariableDeclaration getTopLevelVariable(
      CompilationUnit unit, String variableName) {
    NodeList<CompilationUnitMember> unitMembers = unit.declarations;
    for (CompilationUnitMember unitMember in unitMembers) {
      if (unitMember is TopLevelVariableDeclaration) {
        NodeList<VariableDeclaration> variables =
            unitMember.variables.variables;
        for (VariableDeclaration variable in variables) {
          if (variable.name.name == variableName) {
            return variable;
          }
        }
      }
    }
    fail('No toplevel variable named $variableName found');
  }

  /// Return the top-level variable element with the given [name].
  static TopLevelVariableElement getTopLevelVariableElement(
      CompilationUnit unit, String name) {
    return getTopLevelVariable(unit, name)?.name?.staticElement;
  }
}

/// Class for compositionally building up assertions on types
class TypeAssertions {
  // TODO(leafp): Make these matchers.
  // https://pub.dev/documentation/matcher/latest/matcher/Matcher-class.html

  /// Provides primitive types for basic type assertions.
  final TypeProvider _typeProvider;

  TypeAssertions(this._typeProvider);

  /// Primitive assertion for the dynamic type
  Asserter<DartType> get isDynamic => isType(_typeProvider.dynamicType);

  /// Primitive assertion for the int type
  Asserter<DartType> get isInt => isType(_typeProvider.intType);

  /// Primitive assertion for the list type
  Asserter<DartType> get isList => hasElement(_typeProvider.listElement);

  /// Primitive assertion for the map type
  Asserter<DartType> get isMap => hasElement(_typeProvider.mapElement);

  /// Primitive assertion for the Null type
  Asserter<DartType> get isNull => isType(_typeProvider.nullType);

  /// Primitive assertion for the num type
  Asserter<DartType> get isNum => isType(_typeProvider.numType);

  /// Primitive assertion for the Object type
  Asserter<DartType> get isObject => isType(_typeProvider.objectType);

  /// Primitive assertion for the string type
  Asserter<DartType> get isString => isType(_typeProvider.stringType);

  /// Assert that a type has the element that is equal to the [expected].
  Asserter<DartType> hasElement(Element expected) =>
      (DartType type) => expect(expected, type.element);

  /// Given assertions for the argument and return types, produce an
  /// assertion over unary function types.
  Asserter<DartType> isFunction2Of(
          Asserter<DartType> argType, Asserter<DartType> returnType) =>
      (DartType type) {
        FunctionType fType = type as FunctionType;
        argType(fType.normalParameterTypes[0]);
        returnType(fType.returnType);
      };

  /// Given an assertion for the base type and assertions over the type
  /// parameters, produce an assertion over instantiations.
  AsserterBuilder<List<Asserter<DartType>>, DartType> isInstantiationOf(
          Asserter<DartType> baseAssert) =>
      (List<Asserter<DartType>> argAsserts) => (DartType type) {
            InterfaceType t = type as InterfaceType;
            baseAssert(t);
            List<DartType> typeArguments = t.typeArguments;
            expect(typeArguments, hasLength(argAsserts.length));
            for (int i = 0; i < typeArguments.length; i++) {
              argAsserts[i](typeArguments[i]);
            }
          };

  /// Assert that a type is the List type, and that the given assertion holds
  /// over the type parameter.
  Asserter<InterfaceType> isListOf(Asserter<DartType> argAssert) =>
      isInstantiationOf(isList)([argAssert]);

  /// Assert that a type is the Map type, and that the given assertions hold
  /// over the type parameters.
  Asserter<InterfaceType> isMapOf(
          Asserter<DartType> argAssert0, Asserter<DartType> argAssert1) =>
      isInstantiationOf(isMap)([argAssert0, argAssert1]);

  /// Assert that a type is equal to the [expected].
  Asserter<DartType> isType(DartType expected) => (DartType t) {
        expect(t, expected);
      };
}
