// 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/dart/ast/ast.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../util/feature_sets.dart';
import 'parser_test_base.dart';
import 'test_support.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(GenericMetadataEnabledParserTest);
    defineReflectiveTests(GenericMetadataDisabledParserTest);
  });
}

@reflectiveTest
class GenericMetadataDisabledParserTest extends FastaParserTestCase
    with GenericMetadataParserTest {
  @override
  CompilationUnit _parseCompilationUnit(String content,
      {List<ExpectedError>? errors, required ExpectedError? disabledError}) {
    var combinedErrors =
        disabledError == null ? errors : [disabledError, ...?errors];
    return parseCompilationUnit(
      content,
      errors: combinedErrors,
      featureSet: FeatureSets.language_2_12,
    );
  }
}

@reflectiveTest
class GenericMetadataEnabledParserTest extends FastaParserTestCase
    with GenericMetadataParserTest {
  @override
  CompilationUnit _parseCompilationUnit(String content,
          {List<ExpectedError>? errors,
          required ExpectedError? disabledError}) =>
      parseCompilationUnit(content, errors: errors);
}

mixin GenericMetadataParserTest on FastaParserTestCase {
  void test_className_prefixed_constructorName_absent() {
    var compilationUnit = _parseCompilationUnit('@p.A<B>() class C {}',
        disabledError:
            expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 4, 1));
    var classDeclaration =
        compilationUnit.declarations.single as ClassDeclaration;
    var annotation = classDeclaration.metadata.single;
    var className = annotation.name as PrefixedIdentifier;
    expect(className.prefix.name, 'p');
    expect(className.identifier.name, 'A');
    var typeArgument = annotation.typeArguments!.arguments.single as NamedType;
    expect(typeArgument.name2.lexeme, 'B');
    expect(annotation.constructorName, isNull);
  }

  void test_className_prefixed_constructorName_present() {
    var compilationUnit = _parseCompilationUnit('@p.A<B>.ctor() class C {}',
        disabledError:
            expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 4, 1));
    var classDeclaration =
        compilationUnit.declarations.single as ClassDeclaration;
    var annotation = classDeclaration.metadata.single;
    var className = annotation.name as PrefixedIdentifier;
    expect(className.prefix.name, 'p');
    expect(className.identifier.name, 'A');
    var typeArgument = annotation.typeArguments!.arguments.single as NamedType;
    expect(typeArgument.name2.lexeme, 'B');
    expect(annotation.constructorName!.name, 'ctor');
  }

  void test_className_unprefixed_constructorName_absent() {
    var compilationUnit = _parseCompilationUnit('@A<B>() class C {}',
        disabledError:
            expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 2, 1));
    var classDeclaration =
        compilationUnit.declarations.single as ClassDeclaration;
    var annotation = classDeclaration.metadata.single;
    var className = annotation.name as SimpleIdentifier;
    expect(className.name, 'A');
    var typeArgument = annotation.typeArguments!.arguments.single as NamedType;
    expect(typeArgument.name2.lexeme, 'B');
    expect(annotation.constructorName, isNull);
  }

  void test_className_unprefixed_constructorName_present() {
    var compilationUnit = _parseCompilationUnit('@A<B>.ctor() class C {}',
        disabledError:
            expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 2, 1));
    var classDeclaration =
        compilationUnit.declarations.single as ClassDeclaration;
    var annotation = classDeclaration.metadata.single;
    var className = annotation.name as SimpleIdentifier;
    expect(className.name, 'A');
    var typeArgument = annotation.typeArguments!.arguments.single as NamedType;
    expect(typeArgument.name2.lexeme, 'B');
    expect(annotation.constructorName!.name, 'ctor');
  }

  void test_reference_prefixed() {
    var compilationUnit = _parseCompilationUnit('@p.x<A> class C {}',
        errors: [
          expectedError(
              ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED,
              6,
              1),
        ],
        disabledError:
            expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 4, 1));
    var classDeclaration =
        compilationUnit.declarations.single as ClassDeclaration;
    var annotation = classDeclaration.metadata.single;
    var name = annotation.name as PrefixedIdentifier;
    expect(name.prefix.name, 'p');
    expect(name.identifier.name, 'x');
    var typeArgument = annotation.typeArguments!.arguments.single as NamedType;
    expect(typeArgument.name2.lexeme, 'A');
    expect(annotation.constructorName, isNull);
  }

  void test_reference_unprefixed() {
    var compilationUnit = _parseCompilationUnit('@x<A> class C {}',
        errors: [
          expectedError(
              ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED,
              4,
              1),
        ],
        disabledError:
            expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 2, 1));
    var classDeclaration =
        compilationUnit.declarations.single as ClassDeclaration;
    var annotation = classDeclaration.metadata.single;
    var name = annotation.name as SimpleIdentifier;
    expect(name.name, 'x');
    var typeArgument = annotation.typeArguments!.arguments.single as NamedType;
    expect(typeArgument.name2.lexeme, 'A');
    expect(annotation.constructorName, isNull);
  }

  test_typeArguments_after_constructorName() {
    _parseCompilationUnit('@p.A.ctor<B>() class C {}',
        errors: [
          expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 9, 1),
          expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 10, 1),
          expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
          expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 11, 1),
          expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 15, 5),
        ],
        disabledError: null);
  }

  test_typeArguments_after_prefix() {
    _parseCompilationUnit('@p<A>.B.ctor() class C {}',
        errors: [
          expectedError(
              ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED,
              6,
              1),
          expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 7, 1),
          expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 15, 5),
        ],
        disabledError:
            expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 2, 1));
  }

  CompilationUnit _parseCompilationUnit(String content,
      {List<ExpectedError>? errors, required ExpectedError? disabledError});
}
