| // 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/src/dart/analysis/driver.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(() { |
| if (!AnalysisDriver.useSummary2) { |
| 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); |
| } |
| } |