blob: 000ba70d46afa5266f93bee1d071c8e9d2d53da9 [file] [log] [blame]
// 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 'dart:async';
import 'package:analysis_server/protocol/protocol.dart';
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';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(DeclarationsTest);
});
}
@reflectiveTest
class DeclarationsTest extends AbstractSearchDomainTest {
SearchGetElementDeclarationsResult declarationsResult;
ElementDeclaration assertHas(String name, ElementKind kind,
{String className, String mixinName}) {
return declarationsResult.declarations.singleWhere((ElementDeclaration d) =>
declarationsResult.files[d.fileIndex] == testFile &&
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 &&
d.name == name))));
}
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');
assertHas('s', ElementKind.SETTER, className: 'C');
assertHas('m', ElementKind.METHOD, className: 'C');
}
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);
}
test_maxResults() async {
newFile(join(testFolder, 'a.dart'), content: r'''
class A {}
class B {}
''').path;
newFile(join(testFolder, 'b.dart'), content: 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));
}
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');
}
test_multipleFiles() async {
var a = newFile(join(testFolder, 'a.dart'), content: 'class A {}').path;
var b = newFile(join(testFolder, 'b.dart'), content: 'class B {}').path;
await _getDeclarations();
expect(declarationsResult.files, contains(a));
expect(declarationsResult.files, contains(b));
{
ElementDeclaration 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);
}
{
ElementDeclaration declaration =
declarationsResult.declarations.singleWhere((d) => d.name == 'B');
expect(declaration.name, 'B');
expect(declaration.kind, ElementKind.CLASS);
expect(declarationsResult.files[declaration.fileIndex], b);
}
}
test_onlyForFile() async {
var a = newFile(join(testFolder, 'a.dart'), content: 'class A {}').path;
newFile(join(testFolder, 'b.dart'), content: '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);
}
test_parameters() async {
addTestFile(r'''
void f(bool a, String b) {}
''');
await _getDeclarations();
ElementDeclaration declaration = assertHas('f', ElementKind.FUNCTION);
expect(declaration.parameters, '(bool a, String b)');
}
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');
}
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);
''');
await _getDeclarations();
assertHas('g', ElementKind.GETTER);
assertHas('s', ElementKind.SETTER);
assertHas('f', ElementKind.FUNCTION);
assertHas('v', ElementKind.TOP_LEVEL_VARIABLE);
assertHas('tf1', ElementKind.FUNCTION_TYPE_ALIAS);
assertHas('tf2', ElementKind.FUNCTION_TYPE_ALIAS);
}
Future<void> _getDeclarations(
{String file, String pattern, int maxResults}) async {
Request request = new SearchGetElementDeclarationsParams(
file: file, pattern: pattern, maxResults: maxResults)
.toRequest('0');
Response response = await waitResponse(request);
declarationsResult =
new SearchGetElementDeclarationsResult.fromResponse(response);
}
}