| // Copyright (c) 2014, 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. |
| |
| library test.search.element_references; |
| |
| import 'dart:async'; |
| |
| import 'package:analysis_server/src/protocol.dart'; |
| import 'package:unittest/unittest.dart'; |
| |
| import '../reflective_tests.dart'; |
| import 'abstract_search_domain.dart'; |
| |
| |
| main() { |
| groupSep = ' | '; |
| runReflectiveTests(ElementReferencesTest); |
| } |
| |
| |
| @ReflectiveTestCase() |
| class ElementReferencesTest extends AbstractSearchDomainTest { |
| Element searchElement; |
| |
| void assertHasRef(SearchResultKind kind, String search, bool isPotential) { |
| assertHasResult(kind, search); |
| expect(result.isPotential, isPotential); |
| } |
| |
| Future findElementReferences(String search, bool includePotential) { |
| int offset = findOffset(search); |
| return waitForTasksFinished().then((_) { |
| Request request = new SearchFindElementReferencesParams( |
| testFile, |
| offset, |
| includePotential).toRequest('0'); |
| Response response = handleSuccessfulRequest(request); |
| var result = new SearchFindElementReferencesResult.fromResponse(response); |
| searchId = result.id; |
| searchElement = result.element; |
| results.clear(); |
| if (searchId == null) { |
| return null; |
| } else { |
| return waitForSearchResults(); |
| } |
| }); |
| } |
| |
| test_constructor_named() { |
| addTestFile(''' |
| class A { |
| A.named(p); |
| } |
| main() { |
| new A.named(1); |
| new A.named(2); |
| } |
| '''); |
| return findElementReferences('named(p)', false).then((_) { |
| expect(searchElement.kind, ElementKind.CONSTRUCTOR); |
| assertHasResult(SearchResultKind.REFERENCE, '.named(1)', 6); |
| assertHasResult(SearchResultKind.REFERENCE, '.named(2)', 6); |
| }); |
| } |
| |
| test_constructor_named_potential() { |
| // Constructors in other classes shouldn't be considered potential matches, |
| // nor should unresolved method calls, since constructor call sites are |
| // statically bound to their targets). |
| addTestFile(''' |
| class A { |
| A.named(p); // A |
| } |
| class B { |
| B.named(p); |
| } |
| f(x) { |
| new A.named(1); |
| new B.named(2); |
| x.named(3); |
| } |
| '''); |
| return findElementReferences('named(p); // A', true).then((_) { |
| expect(searchElement.kind, ElementKind.CONSTRUCTOR); |
| assertHasResult(SearchResultKind.DECLARATION, '.named(p)', 6); |
| assertHasResult(SearchResultKind.REFERENCE, '.named(1)', 6); |
| expect(results, hasLength(2)); |
| }); |
| } |
| |
| test_constructor_unnamed() { |
| addTestFile(''' |
| class A { |
| A(p); |
| } |
| main() { |
| new A(1); |
| new A(2); |
| } |
| '''); |
| return findElementReferences('A(p)', false).then((_) { |
| expect(searchElement.kind, ElementKind.CONSTRUCTOR); |
| assertHasResult(SearchResultKind.REFERENCE, '(1)', 0); |
| assertHasResult(SearchResultKind.REFERENCE, '(2)', 0); |
| }); |
| } |
| |
| test_constructor_unnamed_potential() { |
| // Constructors in other classes shouldn't be considered potential matches, |
| // even if they are also unnamed (since constructor call sites are |
| // statically bound to their targets). |
| // Also, assignments to local variables shouldn't be considered potential |
| // matches. |
| addTestFile(''' |
| class A { |
| A(p); // A |
| } |
| class B { |
| B(p); |
| foo() { |
| int k; |
| k = 3; |
| } |
| } |
| main() { |
| new A(1); |
| new B(2); |
| } |
| '''); |
| return findElementReferences('A(p)', true).then((_) { |
| expect(searchElement.kind, ElementKind.CONSTRUCTOR); |
| assertHasResult(SearchResultKind.DECLARATION, '(p); // A', 0); |
| assertHasResult(SearchResultKind.REFERENCE, '(1)', 0); |
| expect(results, hasLength(2)); |
| }); |
| } |
| |
| test_field_explicit() { |
| addTestFile(''' |
| class A { |
| var fff; // declaration |
| A(this.fff); // in constructor |
| m() { |
| fff = 2; |
| fff += 3; |
| print(fff); // in m() |
| fff(); // in m() |
| } |
| } |
| main(A a) { |
| a.fff = 20; |
| a.fff += 30; |
| print(a.fff); // in main() |
| a.fff(); // in main() |
| } |
| '''); |
| return findElementReferences('fff; // declaration', false).then((_) { |
| expect(searchElement.kind, ElementKind.FIELD); |
| expect(results, hasLength(10)); |
| assertHasResult(SearchResultKind.DECLARATION, 'fff; // declaration'); |
| assertHasResult(SearchResultKind.REFERENCE, 'fff); // in constructor'); |
| // m() |
| assertHasResult(SearchResultKind.WRITE, 'fff = 2;'); |
| assertHasResult(SearchResultKind.WRITE, 'fff += 3;'); |
| assertHasResult(SearchResultKind.READ, 'fff); // in m()'); |
| assertHasResult(SearchResultKind.INVOCATION, 'fff(); // in m()'); |
| // main() |
| assertHasResult(SearchResultKind.WRITE, 'fff = 20;'); |
| assertHasResult(SearchResultKind.WRITE, 'fff += 30;'); |
| assertHasResult(SearchResultKind.READ, 'fff); // in main()'); |
| assertHasResult(SearchResultKind.INVOCATION, 'fff(); // in main()'); |
| }); |
| } |
| |
| test_field_implicit() { |
| addTestFile(''' |
| class A { |
| var get fff => null; |
| void set fff(x) {} |
| m() { |
| print(fff); // in m() |
| fff = 1; |
| } |
| } |
| main(A a) { |
| print(a.fff); // in main() |
| a.fff = 10; |
| } |
| '''); |
| var forGetter = findElementReferences('fff =>', false).then((_) { |
| expect(searchElement.kind, ElementKind.FIELD); |
| expect(results, hasLength(4)); |
| assertHasResult(SearchResultKind.READ, 'fff); // in m()'); |
| assertHasResult(SearchResultKind.WRITE, 'fff = 1;'); |
| assertHasResult(SearchResultKind.READ, 'fff); // in main()'); |
| assertHasResult(SearchResultKind.WRITE, 'fff = 10;'); |
| }); |
| var forSetter = findElementReferences('fff(x) {}', false).then((_) { |
| expect(results, hasLength(4)); |
| assertHasResult(SearchResultKind.READ, 'fff); // in m()'); |
| assertHasResult(SearchResultKind.WRITE, 'fff = 1;'); |
| assertHasResult(SearchResultKind.READ, 'fff); // in main()'); |
| assertHasResult(SearchResultKind.WRITE, 'fff = 10;'); |
| }); |
| return Future.wait([forGetter, forSetter]); |
| } |
| |
| test_field_inFormalParameter() { |
| addTestFile(''' |
| class A { |
| var fff; // declaration |
| A(this.fff); // in constructor |
| m() { |
| fff = 2; |
| print(fff); // in m() |
| } |
| } |
| '''); |
| return findElementReferences('fff); // in constructor', false).then((_) { |
| expect(searchElement.kind, ElementKind.FIELD); |
| expect(results, hasLength(4)); |
| assertHasResult(SearchResultKind.DECLARATION, 'fff; // declaration'); |
| assertHasResult(SearchResultKind.REFERENCE, 'fff); // in constructor'); |
| assertHasResult(SearchResultKind.WRITE, 'fff = 2;'); |
| assertHasResult(SearchResultKind.READ, 'fff); // in m()'); |
| }); |
| } |
| |
| test_function() { |
| addTestFile(''' |
| fff(p) {} |
| main() { |
| fff(1); |
| print(fff); |
| } |
| '''); |
| return findElementReferences('fff(p) {}', false).then((_) { |
| expect(searchElement.kind, ElementKind.FUNCTION); |
| expect(results, hasLength(2)); |
| assertHasResult(SearchResultKind.INVOCATION, 'fff(1)'); |
| assertHasResult(SearchResultKind.REFERENCE, 'fff);'); |
| }); |
| } |
| |
| test_hierarchy_whenExtends_field() { |
| addTestFile(''' |
| class A { |
| int mmm; |
| use_mmm_a() { |
| mmm = 1; |
| } |
| } |
| class B extends A { |
| int mmm; |
| use_mmm_b() { |
| mmm = 2; |
| } |
| } |
| class C extends B { |
| int mmm; // of C |
| use_mmm_c() { |
| mmm = 3; |
| } |
| } |
| class D extends A { |
| int mmm; |
| use_mmm_d() { |
| mmm = 4; |
| } |
| } |
| class E extends C { |
| use_mmm_e() { |
| mmm = 5; |
| } |
| } |
| class F extends C { |
| int mmm; |
| use_mmm_f() { |
| mmm = 6; |
| mmm(6); |
| } |
| } |
| main(A a, B b, C c, D d, E e, F f) { |
| a.mmm = 10; |
| b.mmm = 20; |
| c.mmm = 30; |
| d.mmm = 40; |
| e.mmm = 50; |
| f.mmm = 60; |
| } |
| '''); |
| return findElementReferences('mmm; // of C', false).then((_) { |
| expect(searchElement.kind, ElementKind.FIELD); |
| // unqualified |
| { |
| assertHasResult(SearchResultKind.WRITE, 'mmm = 1'); |
| assertHasResult(SearchResultKind.WRITE, 'mmm = 2'); |
| assertHasResult(SearchResultKind.WRITE, 'mmm = 3'); |
| assertNoResult(SearchResultKind.WRITE, 'mmm = 4'); |
| assertHasResult(SearchResultKind.WRITE, 'mmm = 5'); |
| assertNoResult(SearchResultKind.WRITE, 'mmm = 6'); |
| } |
| // qualified |
| { |
| assertHasResult(SearchResultKind.WRITE, 'mmm = 10'); |
| assertHasResult(SearchResultKind.WRITE, 'mmm = 20'); |
| assertHasResult(SearchResultKind.WRITE, 'mmm = 30'); |
| assertNoResult(SearchResultKind.WRITE, 'mmm = 40'); |
| assertHasResult(SearchResultKind.WRITE, 'mmm = 50'); |
| assertNoResult(SearchResultKind.WRITE, 'mmm = 60'); |
| } |
| }); |
| } |
| |
| test_hierarchy_whenExtends_method() { |
| // TODO(scheglov) ideally we need to remove D.mmm() declaration |
| // to actually test that we have fixed |
| // https://code.google.com/p/dart/issues/detail?id=19697 |
| addTestFile(''' |
| class A { |
| mmm(_) {} |
| use_mmm_a() { |
| mmm(1); |
| } |
| } |
| class B extends A { |
| mmm(_) {} |
| use_mmm_b() { |
| mmm(2); |
| } |
| } |
| class C extends B { |
| mmm(_) {} // of C |
| use_mmm_c() { |
| mmm(3); |
| } |
| } |
| class D extends A { |
| mmm(_) {} |
| use_mmm_d() { |
| mmm(4); |
| } |
| } |
| class E extends C { |
| use_mmm_e() { |
| mmm(5); |
| } |
| } |
| class F extends C { |
| mmm(_) {} |
| use_mmm_f() { |
| mmm(6); |
| } |
| } |
| main(A a, B b, C c, D d, E e, F f) { |
| a.mmm(10); |
| b.mmm(20); |
| c.mmm(30); |
| d.mmm(40); |
| e.mmm(50); |
| f.mmm(60); |
| } |
| '''); |
| return findElementReferences('mmm(_) {} // of C', false).then((_) { |
| expect(searchElement.kind, ElementKind.METHOD); |
| // unqualified |
| { |
| assertHasResult(SearchResultKind.INVOCATION, 'mmm(1)'); |
| assertHasResult(SearchResultKind.INVOCATION, 'mmm(2)'); |
| assertHasResult(SearchResultKind.INVOCATION, 'mmm(3)'); |
| assertNoResult(SearchResultKind.INVOCATION, 'mmm(4)'); |
| assertHasResult(SearchResultKind.INVOCATION, 'mmm(5)'); |
| assertNoResult(SearchResultKind.INVOCATION, 'mmm(6)'); |
| } |
| // qualified |
| { |
| assertHasResult(SearchResultKind.INVOCATION, 'mmm(10)'); |
| assertHasResult(SearchResultKind.INVOCATION, 'mmm(20)'); |
| assertHasResult(SearchResultKind.INVOCATION, 'mmm(30)'); |
| assertNoResult(SearchResultKind.INVOCATION, 'mmm(40)'); |
| assertHasResult(SearchResultKind.INVOCATION, 'mmm(50)'); |
| assertNoResult(SearchResultKind.INVOCATION, 'mmm(60)'); |
| } |
| }); |
| } |
| |
| test_label() { |
| addTestFile(''' |
| main() { |
| myLabel: |
| for (int i = 0; i < 10; i++) { |
| if (i == 2) { |
| continue myLabel; // continue |
| } |
| break myLabel; // break |
| } |
| } |
| '''); |
| return findElementReferences('myLabel; // break', false).then((_) { |
| expect(searchElement.kind, ElementKind.LABEL); |
| expect(results, hasLength(3)); |
| assertHasResult(SearchResultKind.DECLARATION, 'myLabel:'); |
| assertHasResult(SearchResultKind.REFERENCE, 'myLabel; // continue'); |
| assertHasResult(SearchResultKind.REFERENCE, 'myLabel; // break'); |
| }); |
| } |
| |
| test_localVariable() { |
| addTestFile(''' |
| main() { |
| var vvv = 1; |
| print(vvv); |
| vvv += 3; |
| vvv = 2; |
| vvv(); |
| } |
| '''); |
| return findElementReferences('vvv = 1', false).then((_) { |
| expect(searchElement.kind, ElementKind.LOCAL_VARIABLE); |
| expect(results, hasLength(5)); |
| assertHasResult(SearchResultKind.DECLARATION, 'vvv = 1'); |
| assertHasResult(SearchResultKind.READ, 'vvv);'); |
| assertHasResult(SearchResultKind.READ_WRITE, 'vvv += 3'); |
| assertHasResult(SearchResultKind.WRITE, 'vvv = 2'); |
| assertHasResult(SearchResultKind.INVOCATION, 'vvv();'); |
| }); |
| } |
| |
| test_method() { |
| addTestFile(''' |
| class A { |
| mmm(p) {} |
| m() { |
| mmm(1); |
| print(mmm); // in m() |
| } |
| } |
| main(A a) { |
| a.mmm(10); |
| print(a.mmm); // in main() |
| } |
| '''); |
| return findElementReferences('mmm(p) {}', false).then((_) { |
| expect(searchElement.kind, ElementKind.METHOD); |
| expect(results, hasLength(4)); |
| assertHasResult(SearchResultKind.INVOCATION, 'mmm(1);'); |
| assertHasResult(SearchResultKind.REFERENCE, 'mmm); // in m()'); |
| assertHasResult(SearchResultKind.INVOCATION, 'mmm(10);'); |
| assertHasResult(SearchResultKind.REFERENCE, 'mmm); // in main()'); |
| }); |
| } |
| |
| test_method_propagatedType() { |
| addTestFile(''' |
| class A { |
| mmm(p) {} |
| } |
| main() { |
| var a = new A(); |
| a.mmm(10); |
| print(a.mmm); |
| } |
| '''); |
| return findElementReferences('mmm(p) {}', false).then((_) { |
| expect(searchElement.kind, ElementKind.METHOD); |
| expect(results, hasLength(2)); |
| assertHasResult(SearchResultKind.INVOCATION, 'mmm(10);'); |
| assertHasResult(SearchResultKind.REFERENCE, 'mmm);'); |
| }); |
| } |
| |
| test_noElement() { |
| addTestFile(''' |
| main() { |
| print(noElement); |
| } |
| '''); |
| return findElementReferences('noElement', false).then((_) { |
| expect(searchId, isNull); |
| }); |
| } |
| |
| test_oneUnit_twoLibraries() { |
| var pathA = '/project/bin/libA.dart'; |
| var pathB = '/project/bin/libB.dart'; |
| var codeA = ''' |
| library lib; |
| part 'test.dart'; |
| main() { |
| fff(1); |
| } |
| '''; |
| var codeB = ''' |
| library lib; |
| part 'test.dart'; |
| main() { |
| fff(2); |
| } |
| '''; |
| addFile(pathA, codeA); |
| addFile(pathB, codeB); |
| addTestFile(''' |
| part of lib; |
| fff(p) {} |
| '''); |
| return findElementReferences('fff(p) {}', false).then((_) { |
| expect(searchElement.kind, ElementKind.FUNCTION); |
| expect(results, hasLength(2)); |
| findResult( |
| SearchResultKind.INVOCATION, |
| pathA, |
| codeA.indexOf('fff(1)'), |
| 3, |
| true); |
| findResult( |
| SearchResultKind.INVOCATION, |
| pathB, |
| codeB.indexOf('fff(2)'), |
| 3, |
| true); |
| }); |
| } |
| |
| test_oneUnit_zeroLibraries() { |
| addTestFile(''' |
| part of lib; |
| fff(p) {} |
| main() { |
| fff(10); |
| } |
| '''); |
| return findElementReferences('fff(p) {}', false).then((_) { |
| expect(results, isEmpty); |
| }); |
| } |
| |
| test_parameter() { |
| addTestFile(''' |
| main(ppp) { |
| print(ppp); |
| ppp += 3; |
| ppp = 2; |
| ppp(); |
| } |
| '''); |
| return findElementReferences('ppp) {', false).then((_) { |
| expect(searchElement.kind, ElementKind.PARAMETER); |
| expect(results, hasLength(5)); |
| assertHasResult(SearchResultKind.DECLARATION, 'ppp) {'); |
| assertHasResult(SearchResultKind.READ, 'ppp);'); |
| assertHasResult(SearchResultKind.READ_WRITE, 'ppp += 3'); |
| assertHasResult(SearchResultKind.WRITE, 'ppp = 2'); |
| assertHasResult(SearchResultKind.INVOCATION, 'ppp();'); |
| }); |
| } |
| |
| test_path_inConstructor_named() { |
| addTestFile(''' |
| library my_lib; |
| class A {} |
| class B { |
| B.named() { |
| A a = null; |
| } |
| } |
| '''); |
| return findElementReferences('A {}', false).then((_) { |
| assertHasResult(SearchResultKind.REFERENCE, 'A a = null;'); |
| expect(getPathString(result.path), ''' |
| LOCAL_VARIABLE a |
| CONSTRUCTOR named |
| CLASS B |
| COMPILATION_UNIT test.dart |
| LIBRARY my_lib'''); |
| }); |
| } |
| |
| test_path_inConstructor_unnamed() { |
| addTestFile(''' |
| library my_lib; |
| class A {} |
| class B { |
| B() { |
| A a = null; |
| } |
| } |
| '''); |
| return findElementReferences('A {}', false).then((_) { |
| assertHasResult(SearchResultKind.REFERENCE, 'A a = null;'); |
| expect(getPathString(result.path), ''' |
| LOCAL_VARIABLE a |
| CONSTRUCTOR |
| CLASS B |
| COMPILATION_UNIT test.dart |
| LIBRARY my_lib'''); |
| }); |
| } |
| |
| test_path_inFunction() { |
| addTestFile(''' |
| library my_lib; |
| class A {} |
| main() { |
| A a = null; |
| } |
| '''); |
| return findElementReferences('A {}', false).then((_) { |
| assertHasResult(SearchResultKind.REFERENCE, 'A a = null;'); |
| expect(getPathString(result.path), ''' |
| LOCAL_VARIABLE a |
| FUNCTION main |
| COMPILATION_UNIT test.dart |
| LIBRARY my_lib'''); |
| }); |
| } |
| |
| test_potential_disabled() { |
| addTestFile(''' |
| class A { |
| test(p) {} |
| } |
| main(A a, p) { |
| a.test(1); |
| p.test(2); |
| } |
| '''); |
| return findElementReferences('test(p) {}', false).then((_) { |
| assertHasResult(SearchResultKind.INVOCATION, 'test(1);'); |
| assertNoResult(SearchResultKind.INVOCATION, 'test(2);'); |
| }); |
| } |
| |
| test_potential_field() { |
| addTestFile(''' |
| class A { |
| var test; // declaration |
| } |
| main(A a, p) { |
| a.test = 1; |
| p.test = 2; |
| print(p.test); // p |
| } |
| '''); |
| return findElementReferences('test; // declaration', true).then((_) { |
| { |
| assertHasResult(SearchResultKind.WRITE, 'test = 1;'); |
| expect(result.isPotential, isFalse); |
| } |
| { |
| assertHasResult(SearchResultKind.WRITE, 'test = 2;'); |
| expect(result.isPotential, isTrue); |
| } |
| { |
| assertHasResult(SearchResultKind.READ, 'test); // p'); |
| expect(result.isPotential, isTrue); |
| } |
| }); |
| } |
| |
| test_potential_method() { |
| addTestFile(''' |
| class A { |
| test(p) {} |
| } |
| main(A a, p) { |
| a.test(1); |
| p.test(2); |
| } |
| '''); |
| return findElementReferences('test(p) {}', true).then((_) { |
| { |
| assertHasResult(SearchResultKind.INVOCATION, 'test(1);'); |
| expect(result.isPotential, isFalse); |
| } |
| { |
| assertHasResult(SearchResultKind.INVOCATION, 'test(2);'); |
| expect(result.isPotential, isTrue); |
| } |
| }); |
| } |
| |
| test_potential_method_definedInSubclass() { |
| addTestFile(''' |
| class Base { |
| methodInBase() { |
| test(1); |
| } |
| } |
| class Derived extends Base { |
| test(_) {} // of Derived |
| methodInDerived() { |
| test(2); |
| } |
| } |
| globalFunction(Base b) { |
| b.test(3); |
| } |
| '''); |
| return findElementReferences('test(_) {} // of Derived', true).then((_) { |
| assertHasRef(SearchResultKind.INVOCATION, 'test(1);', true); |
| assertHasRef(SearchResultKind.INVOCATION, 'test(2);', false); |
| assertHasRef(SearchResultKind.INVOCATION, 'test(3);', true); |
| }); |
| } |
| |
| test_topLevelVariable_explicit() { |
| addTestFile(''' |
| var vvv = 1; |
| main() { |
| print(vvv); |
| vvv += 3; |
| vvv = 2; |
| vvv(); |
| } |
| '''); |
| return findElementReferences('vvv = 1', false).then((_) { |
| expect(searchElement.kind, ElementKind.TOP_LEVEL_VARIABLE); |
| expect(results, hasLength(5)); |
| assertHasResult(SearchResultKind.DECLARATION, 'vvv = 1;'); |
| assertHasResult(SearchResultKind.READ, 'vvv);'); |
| assertHasResult(SearchResultKind.WRITE, 'vvv += 3'); |
| assertHasResult(SearchResultKind.WRITE, 'vvv = 2'); |
| assertHasResult(SearchResultKind.INVOCATION, 'vvv();'); |
| }); |
| } |
| |
| test_topLevelVariable_implicit() { |
| addTestFile(''' |
| get vvv => null; |
| set vvv(x) {} |
| main() { |
| print(vvv); |
| vvv = 1; |
| } |
| '''); |
| var forGetter = findElementReferences('vvv =>', false).then((_) { |
| expect(searchElement.kind, ElementKind.TOP_LEVEL_VARIABLE); |
| expect(results, hasLength(2)); |
| assertHasResult(SearchResultKind.READ, 'vvv);'); |
| assertHasResult(SearchResultKind.WRITE, 'vvv = 1;'); |
| }); |
| var forSetter = findElementReferences('vvv(x) {}', false).then((_) { |
| expect(results, hasLength(2)); |
| assertHasResult(SearchResultKind.READ, 'vvv);'); |
| assertHasResult(SearchResultKind.WRITE, 'vvv = 1;'); |
| }); |
| return Future.wait([forGetter, forSetter]); |
| } |
| |
| test_typeReference_class() { |
| addTestFile(''' |
| main() { |
| int a = 1; |
| int b = 2; |
| } |
| '''); |
| return findElementReferences('int a', false).then((_) { |
| expect(searchElement.kind, ElementKind.CLASS); |
| assertHasResult(SearchResultKind.REFERENCE, 'int a'); |
| assertHasResult(SearchResultKind.REFERENCE, 'int b'); |
| }); |
| } |
| |
| test_typeReference_functionType() { |
| addTestFile(''' |
| typedef F(); |
| main(F f) { |
| } |
| '''); |
| return findElementReferences('F()', false).then((_) { |
| expect(searchElement.kind, ElementKind.FUNCTION_TYPE_ALIAS); |
| expect(results, hasLength(1)); |
| assertHasResult(SearchResultKind.REFERENCE, 'F f'); |
| }); |
| } |
| |
| test_typeReference_typeVariable() { |
| addTestFile(''' |
| class A<T> { |
| T f; |
| T m() => null; |
| } |
| '''); |
| return findElementReferences('T> {', false).then((_) { |
| expect(searchElement.kind, ElementKind.TYPE_PARAMETER); |
| expect(results, hasLength(2)); |
| assertHasResult(SearchResultKind.REFERENCE, 'T f;'); |
| assertHasResult(SearchResultKind.REFERENCE, 'T m()'); |
| }); |
| } |
| } |