// 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/ast/standard_resolution_map.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/testing/element_search.dart';
import 'package:analyzer/src/generated/source.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.where((e) => e is 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.where((e) => e is LocalVariableElement).toList();
  expect(localVariables, hasLength(1));
  return localVariables[0];
}

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

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

/**
 * The type of a function which given an [S0] and an S1, builds an assertion
 * over [T]s.
 */
typedef Asserter<T> AsserterBuilder2<S0, S1, T>(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 AsserterBuilder<S, T> AsserterBuilderBuilder<R, S, T>(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 = resolutionMap.elementDeclaredByCompilationUnit(unit).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 => hasElementOf(_typeProvider.listType);

  /**
   * Primitive assertion for the map type
   */
  Asserter<DartType> get isMap => hasElementOf(_typeProvider.mapType);

  /**
   * 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);

  /**
   * Assert that a type has the element that is equal to the element of the
   * given [type].
   */
  Asserter<DartType> hasElementOf(DartType type) => hasElement(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);
      };
}
