// Copyright (c) 2022, 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/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

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

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

@reflectiveTest
class InvalidReferenceToGenerativeEnumConstructorTest
    extends PubPackageResolutionTest {
  test_factory_named() async {
    await assertNoErrorsInCode('''
enum E {
  v();

  factory E.named() => v;
}

void f() {
  E.named;
  E.named();
}
''');
  }

  test_factory_unnamed() async {
    await assertNoErrorsInCode('''
enum E {
  v.named();

  const E.named();
  factory E() => v;
}

void f() {
  E.new;
  E();
}
''');
  }

  test_generative_named_constructorReference() async {
    await assertErrorsInCode(
      '''
enum E {
  v.named();

  const E.named();
}

void f() {
  E.named;
}
''',
      [
        error(
          CompileTimeErrorCode
              .invalidReferenceToGenerativeEnumConstructorTearoff,
          58,
          7,
        ),
      ],
    );
  }

  test_generative_named_instanceCreation_implicitNew() async {
    await assertErrorsInCode(
      '''
enum E {
  v.named();

  const E.named();
}

void f() {
  E.named();
}
''',
      [
        error(
          CompileTimeErrorCode.invalidReferenceToGenerativeEnumConstructor,
          58,
          7,
        ),
      ],
    );
  }

  test_generative_named_redirectingConstructorInvocation() async {
    await assertNoErrorsInCode('''
enum E {
  v;

  const E() : this.named();
  const E.named();
}
''');
  }

  test_generative_named_redirectingFactory() async {
    await assertErrorsInCode(
      '''
enum E {
  v;

  const factory E() = E.named;
  const E.named();
}
''',
      [
        error(
          CompileTimeErrorCode.enumConstantInvokesFactoryConstructor,
          11,
          1,
        ),
        error(
          CompileTimeErrorCode.invalidReferenceToGenerativeEnumConstructor,
          37,
          7,
        ),
      ],
    );
  }

  test_generative_unnamed_constructorReference() async {
    await assertErrorsInCode(
      '''
enum E {
  v
}

void f() {
  E.new;
}
''',
      [
        error(
          CompileTimeErrorCode
              .invalidReferenceToGenerativeEnumConstructorTearoff,
          29,
          5,
        ),
      ],
    );
  }

  test_generative_unnamed_instanceCreation_explicitConst() async {
    await assertErrorsInCode(
      '''
enum E {
  v
}

void f() {
  const E();
}
''',
      [
        error(
          CompileTimeErrorCode.invalidReferenceToGenerativeEnumConstructor,
          35,
          1,
        ),
      ],
    );
  }

  test_generative_unnamed_instanceCreation_explicitNew() async {
    await assertErrorsInCode(
      '''
enum E {
  v
}

void f() {
  new E();
}
''',
      [
        error(
          CompileTimeErrorCode.invalidReferenceToGenerativeEnumConstructor,
          33,
          1,
        ),
      ],
    );
  }

  test_generative_unnamed_instanceCreation_implicitNew() async {
    await assertErrorsInCode(
      '''
enum E {
  v
}

void f() {
  E();
}
''',
      [
        error(
          CompileTimeErrorCode.invalidReferenceToGenerativeEnumConstructor,
          29,
          1,
        ),
      ],
    );
  }

  test_generative_unnamed_redirectingConstructorInvocation() async {
    await assertNoErrorsInCode('''
enum E {
  v1,
  v2.named();

  const E();
  const E.named() : this();
}
''');
  }

  test_generative_unnamed_redirectingFactory() async {
    await assertErrorsInCode(
      '''
enum E {
  v;

  const factory E.named() = E;
  const E();
}
''',
      [
        error(
          CompileTimeErrorCode.invalidReferenceToGenerativeEnumConstructor,
          43,
          1,
        ),
      ],
    );
  }
}
