// 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/element/nullability_suffix.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:source_span/source_span.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../generated/test_support.dart';
import '../src/dart/resolution/context_collection_resolution.dart';

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

@reflectiveTest
class ErrorReporterTest extends PubPackageResolutionTest {
  var listener = GatheringErrorListener();

  test_creation() async {
    var source = TestSource();
    var reporter = ErrorReporter(
      listener,
      source,
      isNonNullableByDefault: false,
    );
    expect(reporter, isNotNull);
  }

  test_reportErrorForElement_named() async {
    await resolveTestCode('class A {}');
    var element = findElement.class_('A');
    var reporter = ErrorReporter(
      listener,
      element.source,
      isNonNullableByDefault: false,
    );
    reporter.reportErrorForElement(
      CompileTimeErrorCode.CAST_TO_NON_TYPE,
      element,
      ['A'],
    );

    var error = listener.errors[0];
    expect(error.offset, element.nameOffset);
  }

  test_reportErrorForElement_unnamed() async {
    await resolveTestCode(r'''
import 'dart:async';
import 'dart:math';
''');
    var element = findElement.import('dart:math');

    var reporter = ErrorReporter(
      listener,
      element.source,
      isNonNullableByDefault: false,
    );
    reporter.reportErrorForElement(
      CompileTimeErrorCode.CAST_TO_NON_TYPE,
      element,
      ['A'],
    );

    var error = listener.errors[0];
    expect(error.offset, element.nameOffset);
  }

  test_reportErrorForNode_types_differentNames() async {
    newFile2('$testPackageLibPath/a.dart', 'class A {}');
    newFile2('$testPackageLibPath/b.dart', 'class B {}');
    await resolveTestCode(r'''
import 'package:test/a.dart';
import 'package:test/b.dart';

main() {
  x;
}
''');
    var aImport = findElement.importFind('package:test/a.dart');
    var bImport = findElement.importFind('package:test/b.dart');

    var firstType = aImport.class_('A').instantiate(
      typeArguments: [],
      nullabilitySuffix: NullabilitySuffix.none,
    );
    var secondType = bImport.class_('B').instantiate(
      typeArguments: [],
      nullabilitySuffix: NullabilitySuffix.none,
    );

    var reporter = ErrorReporter(
      listener,
      firstType.element.source,
      isNonNullableByDefault: false,
    );

    reporter.reportErrorForNode(
      CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
      findNode.simple('x'),
      [firstType, secondType],
    );

    var error = listener.errors[0];
    expect(error.message, isNot(contains('(')));
  }

  test_reportErrorForNode_types_sameName() async {
    newFile2('$testPackageLibPath/a.dart', 'class A {}');
    newFile2('$testPackageLibPath/b.dart', 'class A {}');
    await resolveTestCode(r'''
import 'package:test/a.dart';
import 'package:test/b.dart';

main() {
  x;
}
''');
    var aImport = findElement.importFind('package:test/a.dart');
    var bImport = findElement.importFind('package:test/b.dart');

    var firstType = aImport.class_('A').instantiate(
      typeArguments: [],
      nullabilitySuffix: NullabilitySuffix.none,
    );
    var secondType = bImport.class_('A').instantiate(
      typeArguments: [],
      nullabilitySuffix: NullabilitySuffix.none,
    );

    var reporter = ErrorReporter(
      listener,
      firstType.element.source,
      isNonNullableByDefault: false,
    );
    reporter.reportErrorForNode(
      CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
      findNode.simple('x'),
      [firstType, secondType],
    );

    var error = listener.errors[0];
    expect(error.message, contains('('));
  }

  test_reportErrorForNode_types_sameName_functionType() async {
    newFile2('$testPackageLibPath/a.dart', 'class A{}');
    newFile2('$testPackageLibPath/b.dart', 'class A{}');
    await resolveTestCode(r'''
import 'a.dart' as a;
import 'b.dart' as b;

a.A Function() fa;
b.A Function() fb;

main() {
  x;
}
''');
    var fa = findNode.topLevelVariableDeclaration('fa');
    var fb = findNode.topLevelVariableDeclaration('fb');

    var source = result.unit.declaredElement!.source;
    var reporter = ErrorReporter(
      listener,
      source,
      isNonNullableByDefault: false,
    );
    reporter.reportErrorForNode(
      CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
      findNode.simple('x'),
      [fa.variables.type!.type!, fb.variables.type!.type!],
    );

    var error = listener.errors[0];
    expect(error.message, contains('a.dart'));
    expect(error.message, contains('b.dart'));
  }

  test_reportErrorForNode_types_sameName_nested() async {
    newFile2('$testPackageLibPath/a.dart', 'class A{}');
    newFile2('$testPackageLibPath/b.dart', 'class A{}');
    await resolveTestCode(r'''
import 'a.dart' as a;
import 'b.dart' as b;

B<a.A> ba;
B<b.A> bb;
class B<T> {}

main() {
  x;
}
''');
    var ba = findNode.topLevelVariableDeclaration('ba');
    var bb = findNode.topLevelVariableDeclaration('bb');

    var source = result.unit.declaredElement!.source;
    var reporter = ErrorReporter(
      listener,
      source,
      isNonNullableByDefault: false,
    );
    reporter.reportErrorForNode(
      CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
      findNode.simple('x'),
      [ba.variables.type!.type!, bb.variables.type!.type!],
    );

    var error = listener.errors[0];
    expect(error.message, contains('a.dart'));
    expect(error.message, contains('b.dart'));
  }

  test_reportErrorForSpan() async {
    var source = TestSource();
    var reporter = ErrorReporter(
      listener,
      source,
      isNonNullableByDefault: false,
    );

    var text = '''
foo: bar
zap: baz
''';

    var offset = text.indexOf('baz');
    var length = 'baz'.length;

    var span = SourceSpanBase(
      SourceLocation(offset),
      SourceLocation(offset + length),
      'baz',
    );

    reporter.reportErrorForSpan(
      AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUE,
      span,
      ['test', 'zip', 'zap'],
    );
    expect(listener.errors, hasLength(1));
    expect(listener.errors.first.offset, offset);
    expect(listener.errors.first.length, length);
  }
}
