// Copyright (c) 2019, 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/analysis/features.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/dart/element/type_visitor.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../../../generated/elements_types_mixin.dart';
import '../../../generated/test_analysis_context.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(NormalizeTypeTest);
  });
}

@reflectiveTest
class NormalizeTypeTest with ElementsTypesMixin {
  @override
  TypeProvider typeProvider;

  TypeSystemImpl typeSystem;

  FeatureSet get testFeatureSet {
    return FeatureSet.forTesting(
      additionalFeatures: [Feature.non_nullable],
    );
  }

  void setUp() {
    var analysisContext = TestAnalysisContext(
      featureSet: testFeatureSet,
    );
    typeProvider = analysisContext.typeProviderNonNullableByDefault;
    typeSystem = analysisContext.typeSystemNonNullableByDefault;
  }

  test_functionType_parameter() {
    _check(
      functionTypeNone(
        returnType: voidNone,
        parameters: [
          requiredParameter(type: futureOrNone(objectNone)),
        ],
      ),
      functionTypeNone(
        returnType: voidNone,
        parameters: [
          requiredParameter(type: objectNone),
        ],
      ),
    );

    _check(
      functionTypeNone(
        returnType: voidNone,
        parameters: [
          namedParameter(name: 'a', type: futureOrNone(objectNone)),
        ],
      ),
      functionTypeNone(
        returnType: voidNone,
        parameters: [
          namedParameter(name: 'a', type: objectNone),
        ],
      ),
    );

    _check(
      functionTypeNone(
        returnType: voidNone,
        parameters: [
          namedRequiredParameter(name: 'a', type: futureOrNone(objectNone)),
        ],
      ),
      functionTypeNone(
        returnType: voidNone,
        parameters: [
          namedRequiredParameter(name: 'a', type: objectNone),
        ],
      ),
    );

    _check(
      functionTypeNone(
        returnType: voidNone,
        parameters: [
          positionalParameter(type: futureOrNone(objectNone)),
        ],
      ),
      functionTypeNone(
        returnType: voidNone,
        parameters: [
          positionalParameter(type: objectNone),
        ],
      ),
    );
  }

  test_functionType_parameter_covariant() {
    _check(
      functionTypeNone(
        returnType: voidNone,
        parameters: [
          requiredParameter(type: futureOrNone(objectNone), isCovariant: true),
        ],
      ),
      functionTypeNone(
        returnType: voidNone,
        parameters: [
          requiredParameter(type: objectNone, isCovariant: true),
        ],
      ),
    );
  }

  test_functionType_parameter_typeParameter() {
    TypeParameterElement T;
    TypeParameterElement T2;

    T = typeParameter('T', bound: neverNone);
    T2 = typeParameter('T2', bound: neverNone);
    _check(
      functionTypeNone(
        returnType: voidNone,
        typeFormals: [T],
        parameters: [
          requiredParameter(type: typeParameterTypeNone(T)),
        ],
      ),
      functionTypeNone(
        returnType: voidNone,
        typeFormals: [T2],
        parameters: [
          requiredParameter(type: neverNone),
        ],
      ),
    );

    T = typeParameter('T', bound: iterableNone(futureOrNone(dynamicNone)));
    T2 = typeParameter('T2', bound: iterableNone(dynamicNone));
    _check(
      functionTypeNone(
        returnType: voidNone,
        typeFormals: [T],
        parameters: [
          requiredParameter(type: typeParameterTypeNone(T)),
        ],
      ),
      functionTypeNone(
        returnType: voidNone,
        typeFormals: [T2],
        parameters: [
          requiredParameter(type: typeParameterTypeNone(T2)),
        ],
      ),
    );
  }

  test_functionType_returnType() {
    _check(
      functionTypeNone(
        returnType: futureOrNone(objectNone),
      ),
      functionTypeNone(
        returnType: objectNone,
      ),
    );

    _check(
      functionTypeNone(
        returnType: intNone,
      ),
      functionTypeNone(
        returnType: intNone,
      ),
    );
  }

  test_functionType_typeParameter_bound_normalized() {
    _check(
      functionTypeNone(
        returnType: voidNone,
        typeFormals: [
          typeParameter('T', bound: futureOrNone(objectNone)),
        ],
      ),
      functionTypeNone(
        returnType: voidNone,
        typeFormals: [
          typeParameter('T', bound: objectNone),
        ],
      ),
    );
  }

  test_functionType_typeParameter_bound_unchanged() {
    _check(
      functionTypeNone(
        returnType: intNone,
        typeFormals: [
          typeParameter('T', bound: numNone),
        ],
      ),
      functionTypeNone(
        returnType: intNone,
        typeFormals: [
          typeParameter('T', bound: numNone),
        ],
      ),
    );
  }

  test_functionType_typeParameter_fresh() {
    var T = typeParameter('T');
    var T2 = typeParameter('T');
    _check(
      functionTypeNone(
        returnType: typeParameterTypeNone(T),
        typeFormals: [T],
        parameters: [
          requiredParameter(
            type: typeParameterTypeNone(T),
          ),
        ],
      ),
      functionTypeNone(
        returnType: typeParameterTypeNone(T2),
        typeFormals: [T2],
        parameters: [
          requiredParameter(
            type: typeParameterTypeNone(T2),
          ),
        ],
      ),
    );
  }

  test_functionType_typeParameter_fresh_bound() {
    var T = typeParameter('T');
    var S = typeParameter('S', bound: typeParameterTypeNone(T));
    var T2 = typeParameter('T');
    var S2 = typeParameter('S', bound: typeParameterTypeNone(T2));
    _check(
      functionTypeNone(
        returnType: typeParameterTypeNone(T),
        typeFormals: [T, S],
        parameters: [
          requiredParameter(
            type: typeParameterTypeNone(T),
          ),
          requiredParameter(
            type: typeParameterTypeNone(S),
          ),
        ],
      ),
      functionTypeNone(
        returnType: typeParameterTypeNone(T2),
        typeFormals: [T2, S2],
        parameters: [
          requiredParameter(
            type: typeParameterTypeNone(T2),
          ),
          requiredParameter(
            type: typeParameterTypeNone(S2),
          ),
        ],
      ),
    );
  }

  /// NORM(FutureOr<T>)
  /// * let S be NORM(T)
  test_futureOr() {
    void check(DartType T, DartType expected) {
      var input = futureOrNone(T);
      _check(input, expected);
    }

    // * if S is a top type then S
    check(dynamicNone, dynamicNone);
    check(voidNone, voidNone);
    check(objectQuestion, objectQuestion);

    // * if S is Object then S
    check(objectNone, objectNone);

    // * if S is Object* then S
    check(objectStar, objectStar);

    // * if S is Never then Future<Never>
    check(neverNone, futureNone(neverNone));

    // * if S is Null then Future<Null>?
    check(nullNone, futureQuestion(nullNone));

    // * else FutureOr<S>
    check(intNone, futureOrNone(intNone));
  }

  test_interfaceType() {
    _check(listNone(intNone), listNone(intNone));

    _check(
      listNone(
        futureOrNone(objectNone),
      ),
      listNone(objectNone),
    );
  }

  test_primitive() {
    _check(dynamicNone, dynamicNone);
    _check(neverNone, neverNone);
    _check(voidNone, voidNone);
    _check(intNone, intNone);
  }

  /// NORM(T?)
  /// * let S be NORM(T)
  test_question() {
    void check(DartType T, DartType expected) {
      _assertNullabilityQuestion(T);
      _check(T, expected);
    }

    // * if S is a top type then S
    check(futureOrQuestion(dynamicNone), dynamicNone);
    check(futureOrQuestion(voidNone), voidNone);
    check(futureOrQuestion(objectQuestion), objectQuestion);

    // * if S is Never then Null
    check(neverQuestion, nullNone);

    // * if S is Never* then Null
    // Analyzer: impossible, we have only one suffix

    // * if S is Null then Null
    check(nullQuestion, nullNone);

    // * if S is FutureOr<R> and R is nullable then S
    check(futureOrQuestion(intQuestion), futureOrNone(intQuestion));

    // * if S is FutureOr<R>* and R is nullable then FutureOr<R>
    // Analyzer: impossible, we have only one suffix

    // * if S is R? then R?
    // * if S is R* then R?
    // * else S?
    check(intQuestion, intQuestion);
    check(objectQuestion, objectQuestion);
    check(futureOrQuestion(objectNone), objectQuestion);
    check(futureOrQuestion(objectStar), objectStar);
  }

  /// NORM(T*)
  /// * let S be NORM(T)
  test_star() {
    void check(DartType T, DartType expected) {
      _assertNullabilityStar(T);
      _check(T, expected);
    }

    // * if S is a top type then S
    check(futureOrStar(dynamicNone), dynamicNone);
    check(futureOrStar(voidNone), voidNone);
    check(futureOrStar(objectQuestion), objectQuestion);

    // * if S is Null then Null
    check(nullStar, nullNone);

    // * if S is R? then R?
    check(futureOrStar(nullNone), futureQuestion(nullNone));

    // * if S is R* then R*
    // * else S*
    check(intStar, intStar);
  }

  /// NORM(X & T)
  /// * let S be NORM(T)
  test_typeParameter_bound() {
    TypeParameterElement T;

    // * if S is Never then Never
    T = typeParameter('T', bound: neverNone);
    _check(typeParameterTypeNone(T), neverNone);

    // * else X
    T = typeParameter('T');
    _check(typeParameterTypeNone(T), typeParameterTypeNone(T));

    // * else X
    T = typeParameter('T', bound: futureOrNone(objectNone));
    _check(typeParameterTypeNone(T), typeParameterTypeNone(T));
  }

  test_typeParameter_bound_recursive() {
    var T = typeParameter('T');
    T.bound = iterableNone(typeParameterTypeNone(T));
    _check(typeParameterTypeNone(T), typeParameterTypeNone(T));
  }

  test_typeParameter_promoted() {
    var T = typeParameter('T');

    // * if S is Never then Never
    _check(
      promotedTypeParameterTypeNone(T, neverNone),
      neverNone,
    );

    // * if S is a top type then X
    _check(
      promotedTypeParameterTypeNone(T, objectQuestion),
      typeParameterTypeNone(T),
    );
    _check(
      promotedTypeParameterTypeNone(T, futureOrQuestion(objectNone)),
      typeParameterTypeNone(T),
    );

    // * if S is X then X
    _check(
      promotedTypeParameterTypeNone(T, typeParameterTypeNone(T)),
      typeParameterTypeNone(T),
    );

    // * if S is Object and NORM(B) is Object where B is the bound of X then X
    T = typeParameter('T', bound: objectNone);
    _check(
      promotedTypeParameterTypeNone(T, futureOrNone(objectNone)),
      typeParameterTypeNone(T),
    );

    // else X & S
    T = typeParameter('T');
    _check(
      promotedTypeParameterType(
        element: T,
        nullabilitySuffix: NullabilitySuffix.none,
        promotedBound: futureOrNone(neverNone),
      ),
      promotedTypeParameterType(
        element: T,
        nullabilitySuffix: NullabilitySuffix.none,
        promotedBound: futureNone(neverNone),
      ),
    );
  }

  void _assertNullability(DartType type, NullabilitySuffix expected) {
    if (type.nullabilitySuffix != expected) {
      fail('Expected $expected in ' + _typeString(type));
    }
  }

  void _assertNullabilityQuestion(DartType type) {
    _assertNullability(type, NullabilitySuffix.question);
  }

  void _assertNullabilityStar(DartType type) {
    _assertNullability(type, NullabilitySuffix.star);
  }

  void _check(DartType T, DartType expected) {
    var expectedStr = _typeString(expected);

    var result = typeSystem.normalize(T);
    var resultStr = _typeString(result);
    expect(result, expected, reason: '''
expected: $expectedStr
actual: $resultStr
''');
    _checkFormalParametersIsCovariant(result, expected);
  }

  void _checkFormalParametersIsCovariant(DartType T1, DartType T2) {
    if (T1 is FunctionType && T2 is FunctionType) {
      var parameters1 = T1.parameters;
      var parameters2 = T2.parameters;
      expect(parameters1, hasLength(parameters2.length));
      for (var i = 0; i < parameters1.length; i++) {
        var parameter1 = parameters1[i];
        var parameter2 = parameters2[i];
        if (parameter1.isCovariant != parameter2.isCovariant) {
          fail('''
parameter1: $parameter1, isCovariant: ${parameter1.isCovariant}
parameter2: $parameter2, isCovariant: ${parameter2.isCovariant}
T1: ${_typeString(T1 as TypeImpl)}
T2: ${_typeString(T2 as TypeImpl)}
''');
        }
        _checkFormalParametersIsCovariant(parameter1.type, parameter2.type);
      }
    }
  }

  String _typeParametersStr(TypeImpl type) {
    var typeStr = '';

    var typeParameterCollector = _TypeParameterCollector();
    type.accept(typeParameterCollector);
    for (var typeParameter in typeParameterCollector.typeParameters) {
      typeStr += ', $typeParameter';
    }
    return typeStr;
  }

  String _typeString(TypeImpl type) {
    if (type == null) return null;
    return type.getDisplayString(withNullability: true) +
        _typeParametersStr(type);
  }
}

class _TypeParameterCollector extends TypeVisitor<void> {
  final Set<String> typeParameters = {};

  /// We don't need to print bounds for these type parameters, because
  /// they are already included into the function type itself, and cannot
  /// be promoted.
  final Set<TypeParameterElement> functionTypeParameters = {};

  @override
  void visitDynamicType(DynamicType type) {}

  @override
  void visitFunctionType(FunctionType type) {
    functionTypeParameters.addAll(type.typeFormals);
    for (var typeParameter in type.typeFormals) {
      var bound = typeParameter.bound;
      if (bound != null) {
        bound.accept(this);
      }
    }
    for (var parameter in type.parameters) {
      parameter.type.accept(this);
    }
    type.returnType.accept(this);
  }

  @override
  void visitInterfaceType(InterfaceType type) {
    for (var typeArgument in type.typeArguments) {
      typeArgument.accept(this);
    }
  }

  @override
  void visitNeverType(NeverType type) {}

  @override
  void visitTypeParameterType(TypeParameterType type) {
    if (!functionTypeParameters.contains(type.element)) {
      var bound = type.element.bound;
      var promotedBound = (type as TypeParameterTypeImpl).promotedBound;

      if (bound == null && promotedBound == null) {
        return;
      }

      var str = '';

      if (bound != null) {
        var boundStr = bound.getDisplayString(withNullability: true);
        str += '${type.element.name} extends ' + boundStr;
      }

      if (promotedBound != null) {
        var promotedBoundStr = promotedBound.getDisplayString(
          withNullability: true,
        );
        if (str.isNotEmpty) {
          str += ', ';
        }
        str += '${type.element.name} & ' + promotedBoundStr;
      }

      typeParameters.add(str);
    }
  }

  @override
  void visitVoidType(VoidType type) {}
}
