// 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/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/java_io.dart';
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:path/path.dart' as path;
import 'package:unittest/unittest.dart';

void initializeTestEnvironment([path.Context context]) {
  groupSep = ' | ';
  JavaFile.pathContext = context ?? path.posix;
}

/**
 * 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;
      }
    }
    fail('No class named $className in ${unit.element.source}');
    return null;
  }

  /**
   * 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 null;
  }

  /**
   * 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 null;
  }

  /**
   * 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 null;
  }

  /**
   * 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 null;
  }

  /**
   * 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 null;
  }

  /**
   * 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 => sameElement(_typeProvider.listType);

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

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

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

  /**
   * Given a type, produce an assertion that a type has the same element.
   */
  Asserter<DartType> hasElement(Element element) =>
      (DartType type) => expect(element, same(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 instantations.
   */
  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 one type is the same as another
   */
  Asserter<DartType> isType(DartType argument) => (DartType t) {
        expect(t, same(argument));
      };

  /**
   * Given a type, produce an assertion that a type has the same element.
   */
  Asserter<DartType> sameElement(DartType elementType) =>
      hasElement(elementType.element);
}
