// Copyright (c) 2018, 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:analysis_server/protocol/protocol_generated.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'abstract_search_domain.dart';

void main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(DeclarationsTest);
  });
}

@reflectiveTest
class DeclarationsTest extends AbstractSearchDomainTest {
  late SearchGetElementDeclarationsResult declarationsResult;

  ElementDeclaration assertHas(String name, ElementKind kind,
      {String? className, String? mixinName}) {
    return declarationsResult.declarations.singleWhere((ElementDeclaration d) =>
        declarationsResult.files[d.fileIndex] == testFile.path &&
        d.name == name &&
        d.kind == kind &&
        d.className == className &&
        d.mixinName == mixinName);
  }

  void assertNo(String name) {
    expect(
        declarationsResult.declarations,
        isNot(contains(predicate((ElementDeclaration d) =>
            declarationsResult.files[d.fileIndex] == testFile.path &&
            d.name == name))));
  }

  Future<void> test_class() async {
    addTestFile(r'''
class C {
  int f;
  C();
  C.named();
  int get g => 0;
  void set s(_) {}
  void m() {}
}
''');
    await _getDeclarations();

    assertHas('C', ElementKind.CLASS);
    assertHas('f', ElementKind.FIELD, className: 'C');
    assertHas('named', ElementKind.CONSTRUCTOR, className: 'C');
    assertHas('g', ElementKind.GETTER, className: 'C');

    {
      var declaration = assertHas('s', ElementKind.SETTER, className: 'C');
      expect(declaration.codeOffset, 59);
      expect(declaration.codeLength, 16);
    }

    {
      var declaration = assertHas('m', ElementKind.METHOD, className: 'C');
      expect(declaration.codeOffset, 78);
      expect(declaration.codeLength, 11);
    }
  }

  Future<void> test_enum() async {
    addTestFile(r'''
enum E {
  a, b, c
}
''');
    await _getDeclarations();

    assertHas('E', ElementKind.ENUM);
    assertHas('a', ElementKind.ENUM_CONSTANT);
    assertHas('b', ElementKind.ENUM_CONSTANT);
    assertHas('c', ElementKind.ENUM_CONSTANT);
  }

  Future<void> test_maxResults() async {
    newFile('$testPackageLibPath/a.dart', r'''
class A {}
class B {}
''').path;
    newFile('$testPackageLibPath/b.dart', r'''
class C {}
class D {}
''').path;

    // Limit to exactly one file.
    await _getDeclarations(pattern: r'^[A-D]$', maxResults: 2);
    expect(declarationsResult.declarations, hasLength(2));

    // Limit in the middle of the second file.
    await _getDeclarations(pattern: r'^[A-D]$', maxResults: 3);
    expect(declarationsResult.declarations, hasLength(3));

    // No limit.
    await _getDeclarations(pattern: r'^[A-D]$');
    expect(declarationsResult.declarations, hasLength(4));
  }

  Future<void> test_mixin() async {
    addTestFile(r'''
mixin M {
  int f;
  int get g => 0;
  void set s(_) {}
  void m() {}
}
''');
    await _getDeclarations();

    assertHas('M', ElementKind.MIXIN);
    assertHas('f', ElementKind.FIELD, mixinName: 'M');
    assertHas('g', ElementKind.GETTER, mixinName: 'M');
    assertHas('s', ElementKind.SETTER, mixinName: 'M');
    assertHas('m', ElementKind.METHOD, mixinName: 'M');
  }

  Future<void> test_multipleFiles() async {
    var a = newFile('$testPackageLibPath/a.dart', 'class A {}').path;
    var b = newFile('$testPackageLibPath/b.dart', 'class B {}').path;

    await _getDeclarations();

    expect(declarationsResult.files, contains(a));
    expect(declarationsResult.files, contains(b));

    {
      var declaration =
          declarationsResult.declarations.singleWhere((d) => d.name == 'A');
      expect(declaration.name, 'A');
      expect(declaration.kind, ElementKind.CLASS);
      expect(declarationsResult.files[declaration.fileIndex], a);
      expect(declaration.offset, 6);
      expect(declaration.line, 1);
      expect(declaration.column, 7);
    }

    {
      var declaration =
          declarationsResult.declarations.singleWhere((d) => d.name == 'B');
      expect(declaration.name, 'B');
      expect(declaration.kind, ElementKind.CLASS);
      expect(declarationsResult.files[declaration.fileIndex], b);
    }
  }

  Future<void> test_onlyForFile() async {
    var a = newFile('$testPackageLibPath/a.dart', 'class A {}').path;
    newFile('$testPackageLibPath/b.dart', 'class B {}').path;

    await _getDeclarations(file: a);

    expect(declarationsResult.files, [a]);
    expect(declarationsResult.declarations, hasLength(1));

    var declaration = declarationsResult.declarations[0];
    expect(declaration.name, 'A');
    expect(declaration.kind, ElementKind.CLASS);
    expect(declarationsResult.files[declaration.fileIndex], a);
  }

  Future<void> test_parameters() async {
    addTestFile(r'''
void f(bool a, String b) {}
''');
    await _getDeclarations();

    var declaration = assertHas('f', ElementKind.FUNCTION);
    expect(declaration.parameters, '(bool a, String b)');
  }

  Future<void> test_regExp() async {
    addTestFile(r'''
class A {}
class B {}
class C {}
class D {}
''');
    await _getDeclarations(pattern: r'[A-C]');

    assertHas('A', ElementKind.CLASS);
    assertHas('B', ElementKind.CLASS);
    assertHas('C', ElementKind.CLASS);
    assertNo('D');
  }

  Future<void> test_top() async {
    addTestFile(r'''
int get g => 0;
void set s(_) {}
void f(int p) {}
int v;
typedef void tf1();
typedef tf2<T> = int Function<S>(T tp, S sp);
typedef td3 = double;
''');
    await _getDeclarations();

    assertHas('g', ElementKind.GETTER);
    assertHas('s', ElementKind.SETTER);
    assertHas('f', ElementKind.FUNCTION);
    assertHas('v', ElementKind.TOP_LEVEL_VARIABLE);
    assertHas('tf1', ElementKind.TYPE_ALIAS);
    assertHas('tf2', ElementKind.TYPE_ALIAS);
    assertHas('td3', ElementKind.TYPE_ALIAS);
  }

  Future<void> _getDeclarations(
      {String? file, String? pattern, int? maxResults}) async {
    var request = SearchGetElementDeclarationsParams(
            file: file, pattern: pattern, maxResults: maxResults)
        .toRequest('0');
    var response = await handleSuccessfulRequest(request);

    declarationsResult =
        SearchGetElementDeclarationsResult.fromResponse(response);
  }
}
