// Copyright (c) 2020, 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/error/error.dart';
import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag;
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../dart/resolution/context_collection_resolution.dart';

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

@reflectiveTest
class InstantiateTypeAliasExpandsToTypeParameterTest
    extends PubPackageResolutionTest {
  DiagnosticCode get _errorCode =>
      diag.instantiateTypeAliasExpandsToTypeParameter;

  test_const_generic_noArguments_unnamed_typeParameter() async {
    await assertErrorsInCode(
      r'''
typedef A<T> = T;

void f() {
  const A();
}
''',
      [error(_errorCode, 38, 1)],
    );
  }

  test_const_notGeneric_unnamed_class() async {
    await assertNoErrorsInCode(r'''
class A {
  const A();
}

typedef X = A;

void f() {
  const X();
}
''');
  }

  test_new_generic_noArguments_unnamed_typeParameter() async {
    await assertErrorsInCode(
      r'''
typedef A<T> = T;

void f() {
  new A();
}
''',
      [error(_errorCode, 36, 1)],
    );
  }

  test_new_generic_withArgument_named_typeParameter() async {
    await assertErrorsInCode(
      r'''
class A {
  A.named();
}

typedef B<T> = T;

void f() {
  new B<A>.named();
}
''',
      [error(_errorCode, 62, 1)],
    );
  }

  test_new_generic_withArgument_unnamed_typeParameter() async {
    await assertErrorsInCode(
      r'''
class A {}

typedef B<T> = T;

void f() {
  new B<A>();
}
''',
      [error(_errorCode, 48, 1)],
    );
  }

  test_new_notGeneric_unnamed_class() async {
    await assertNoErrorsInCode(r'''
class A {}

typedef X = A;

void f() {
  new X();
}
''');
  }

  test_new_notGeneric_unnamed_typeParameter2() async {
    await assertErrorsInCode(
      r'''
typedef A<T> = T;
typedef B<T> = A<T>;

void f() {
  new B();
}
''',
      [error(_errorCode, 57, 1)],
    );

    var node = findNode.instanceCreation('new B()');
    assertResolvedNodeText(node, r'''
InstanceCreationExpression
  keyword: new
  constructorName: ConstructorName
    type: NamedType
      name: B
      element: <testLibrary>::@typeAlias::B
      type: InvalidType
    element: <null>
  argumentList: ArgumentList
    leftParenthesis: (
    rightParenthesis: )
  staticType: InvalidType
''');
  }
}
