// 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.

library analyzer.test.utils;

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:front_end/src/base/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://www.dartdocs.org/documentation/matcher/0.12.0%2B1/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);
      };
}
