| // Copyright (c) 2016, 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/ast/ast.dart'; |
| import 'package:analyzer/dart/element/element.dart'; |
| import 'package:analyzer/src/dart/analysis/index.dart'; |
| import 'package:analyzer/src/dart/element/element.dart'; |
| import 'package:analyzer/src/summary/idl.dart'; |
| import 'package:analyzer/src/test_utilities/find_element2.dart'; |
| import 'package:collection/collection.dart'; |
| import 'package:test/test.dart'; |
| import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| |
| import '../resolution/context_collection_resolution.dart'; |
| import '../resolution/node_text_expectations.dart'; |
| |
| main() { |
| defineReflectiveSuite(() { |
| defineReflectiveTests(IndexTest); |
| defineReflectiveTests(UpdateNodeTextExpectations); |
| }); |
| } |
| |
| class ExpectedLocation { |
| final int offset; |
| final int length; |
| final bool isQualified; |
| |
| ExpectedLocation(this.offset, this.length, this.isQualified); |
| |
| @override |
| String toString() { |
| return '(offset=$offset; length=$length; isQualified=$isQualified)'; |
| } |
| } |
| |
| @reflectiveTest |
| class IndexTest extends PubPackageResolutionTest with _IndexMixin { |
| void assertElementIndexText(Element element, String expected) { |
| var actual = _getRelationsText(element); |
| if (actual != expected) { |
| print(actual); |
| NodeTextExpectationsCollector.add(actual); |
| } |
| expect(actual, expected); |
| } |
| |
| void assertLibraryFragmentIndexText( |
| LibraryFragmentImpl fragment, |
| String expected, |
| ) { |
| var actual = _getLibraryFragmentReferenceText(fragment); |
| if (actual != expected) { |
| print(actual); |
| NodeTextExpectationsCollector.add(actual); |
| } |
| expect(actual, expected); |
| } |
| |
| test_class_constructorElement_unnamed_implicitInvocation() async { |
| await _indexTestUnit(''' |
| class A { |
| A(); |
| } |
| |
| class B extends A { |
| B(); |
| B.named(); |
| factory B.foo() = A; |
| } |
| |
| class C extends A {} |
| '''); |
| |
| var element = findElement2.unnamedConstructor('A'); |
| assertElementIndexText(element, r''' |
| 42 6:3 |B| IS_INVOKED_BY qualified |
| 49 7:3 |B.named| IS_INVOKED_BY qualified |
| 81 8:22 || IS_REFERENCED_BY qualified |
| 92 11:7 |C| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_fieldFormalParameter_noSuchField() async { |
| await _indexTestUnit(''' |
| class B<T> { |
| B({this.x}) {} |
| |
| foo() { |
| B<int>(x: 1); |
| } |
| } |
| '''); |
| // No exceptions. |
| } |
| |
| test_hasAncestor_ClassDeclaration() async { |
| await _indexTestUnit(''' |
| class A {} |
| class B1 extends A {} |
| class B2 implements A {} |
| class C1 extends B1 {} |
| class C2 extends B2 {} |
| class C3 implements B1 {} |
| class C4 implements B2 {} |
| class M extends Object with A {} |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 17 2:7 |B1| IS_ANCESTOR_OF |
| 28 2:18 |A| IS_EXTENDED_BY |
| 28 2:18 |A| IS_REFERENCED_BY |
| 39 3:7 |B2| IS_ANCESTOR_OF |
| 53 3:21 |A| IS_IMPLEMENTED_BY |
| 53 3:21 |A| IS_REFERENCED_BY |
| 64 4:7 |C1| IS_ANCESTOR_OF |
| 87 5:7 |C2| IS_ANCESTOR_OF |
| 110 6:7 |C3| IS_ANCESTOR_OF |
| 136 7:7 |C4| IS_ANCESTOR_OF |
| 162 8:7 |M| IS_ANCESTOR_OF |
| 184 8:29 |A| IS_MIXED_IN_BY |
| 184 8:29 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_hasAncestor_ClassTypeAlias() async { |
| await _indexTestUnit(''' |
| class A {} |
| class B extends A {} |
| class C1 = Object with A; |
| class C2 = Object with B; |
| '''); |
| |
| var elementA = findElement2.class_('A'); |
| assertElementIndexText(elementA, r''' |
| 17 2:7 |B| IS_ANCESTOR_OF |
| 27 2:17 |A| IS_EXTENDED_BY |
| 27 2:17 |A| IS_REFERENCED_BY |
| 38 3:7 |C1| IS_ANCESTOR_OF |
| 55 3:24 |A| IS_MIXED_IN_BY |
| 55 3:24 |A| IS_REFERENCED_BY |
| 64 4:7 |C2| IS_ANCESTOR_OF |
| '''); |
| |
| var elementB = findElement2.class_('B'); |
| assertElementIndexText(elementB, r''' |
| 64 4:7 |C2| IS_ANCESTOR_OF |
| 81 4:24 |B| IS_MIXED_IN_BY |
| 81 4:24 |B| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_hasAncestor_MixinDeclaration() async { |
| await _indexTestUnit(''' |
| class A {} |
| class B extends A {} |
| |
| mixin M1 on A {} |
| mixin M2 on B {} |
| mixin M3 implements A {} |
| mixin M4 implements B {} |
| mixin M5 on M2 {} |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 17 2:7 |B| IS_ANCESTOR_OF |
| 27 2:17 |A| IS_EXTENDED_BY |
| 27 2:17 |A| IS_REFERENCED_BY |
| 39 4:7 |M1| IS_ANCESTOR_OF |
| 45 4:13 |A| CONSTRAINS |
| 45 4:13 |A| IS_REFERENCED_BY |
| 56 5:7 |M2| IS_ANCESTOR_OF |
| 73 6:7 |M3| IS_ANCESTOR_OF |
| 87 6:21 |A| IS_IMPLEMENTED_BY |
| 87 6:21 |A| IS_REFERENCED_BY |
| 98 7:7 |M4| IS_ANCESTOR_OF |
| 123 8:7 |M5| IS_ANCESTOR_OF |
| '''); |
| } |
| |
| test_isConstraint_MixinDeclaration_onClause() async { |
| await _indexTestUnit(''' |
| class A {} // 1 |
| mixin M on A {} // 2 |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 22 2:7 |M| IS_ANCESTOR_OF |
| 27 2:12 |A| CONSTRAINS |
| 27 2:12 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isExtendedBy_ClassDeclaration_isQualified() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' as p; |
| class B extends p.A {} // 2 |
| '''); |
| var element = importFindLib().class_('A'); |
| assertElementIndexText(element, r''' |
| 30 2:7 |B| IS_ANCESTOR_OF |
| 42 2:19 |A| IS_EXTENDED_BY qualified |
| 42 2:19 |A| IS_REFERENCED_BY qualified |
| Prefixes: p |
| '''); |
| } |
| |
| test_isExtendedBy_ClassDeclaration_Object() async { |
| await _indexTestUnit(''' |
| class A {} |
| '''); |
| var elementA = findElement2.class_('A'); |
| var elementObject = elementA.supertype!.element3; |
| assertElementIndexText(elementObject, r''' |
| 6 1:7 |A| IS_ANCESTOR_OF |
| 6 1:7 || IS_EXTENDED_BY qualified |
| '''); |
| } |
| |
| test_isExtendedBy_ClassDeclaration_TypeAliasElement() async { |
| await _indexTestUnit(''' |
| class A<T> {} |
| typedef B = A<int>; |
| class C extends B {} |
| '''); |
| var element = findElement2.typeAlias('B'); |
| assertElementIndexText(element, r''' |
| 50 3:17 |B| IS_EXTENDED_BY |
| 50 3:17 |B| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isExtendedBy_ClassTypeAlias() async { |
| await _indexTestUnit(''' |
| class A {} |
| class B {} |
| class C = A with B; |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 28 3:7 |C| IS_ANCESTOR_OF |
| 32 3:11 |A| IS_EXTENDED_BY |
| 32 3:11 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isExtendedBy_ClassTypeAlias_isQualified() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' as p; |
| class B {} |
| class C = p.A with B; |
| '''); |
| var element = importFindLib().class_('A'); |
| assertElementIndexText(element, r''' |
| 41 3:7 |C| IS_ANCESTOR_OF |
| 47 3:13 |A| IS_EXTENDED_BY qualified |
| 47 3:13 |A| IS_REFERENCED_BY qualified |
| Prefixes: p |
| '''); |
| } |
| |
| test_isImplementedBy_ClassDeclaration() async { |
| await _indexTestUnit(''' |
| class A {} // 1 |
| class B implements A {} // 2 |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 22 2:7 |B| IS_ANCESTOR_OF |
| 35 2:20 |A| IS_IMPLEMENTED_BY |
| 35 2:20 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isImplementedBy_ClassDeclaration_isQualified() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' as p; |
| class B implements p.A {} // 2 |
| '''); |
| var element = importFindLib().class_('A'); |
| assertElementIndexText(element, r''' |
| 30 2:7 |B| IS_ANCESTOR_OF |
| 45 2:22 |A| IS_IMPLEMENTED_BY qualified |
| 45 2:22 |A| IS_REFERENCED_BY qualified |
| Prefixes: p |
| '''); |
| } |
| |
| test_isImplementedBy_ClassDeclaration_TypeAliasElement() async { |
| await _indexTestUnit(''' |
| class A<T> {} |
| typedef B = A<int>; |
| class C implements B {} |
| '''); |
| var element = findElement2.typeAlias('B'); |
| assertElementIndexText(element, r''' |
| 53 3:20 |B| IS_IMPLEMENTED_BY |
| 53 3:20 |B| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isImplementedBy_ClassTypeAlias() async { |
| await _indexTestUnit(''' |
| class A {} // 1 |
| class B {} // 2 |
| class C = Object with A implements B; // 3 |
| '''); |
| var element = findElement2.class_('B'); |
| assertElementIndexText(element, r''' |
| 38 3:7 |C| IS_ANCESTOR_OF |
| 67 3:36 |B| IS_IMPLEMENTED_BY |
| 67 3:36 |B| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isImplementedBy_enum() async { |
| await _indexTestUnit(''' |
| class A {} // 1 |
| enum E implements A { // 2 |
| v; |
| } |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 21 2:6 |E| IS_ANCESTOR_OF |
| 34 2:19 |A| IS_IMPLEMENTED_BY |
| 34 2:19 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isImplementedBy_extensionType_class() async { |
| await _indexTestUnit(''' |
| class A {} |
| extension type B(A it) implements A {} |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 26 2:16 |B| IS_ANCESTOR_OF |
| 28 2:18 |A| IS_REFERENCED_BY |
| 45 2:35 |A| IS_IMPLEMENTED_BY |
| 45 2:35 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isImplementedBy_extensionType_extensionType() async { |
| await _indexTestUnit(''' |
| extension type A(int it) {} |
| extension type B(int it) implements A {} |
| '''); |
| var element = findElement2.extensionType('A'); |
| assertElementIndexText(element, r''' |
| 43 2:16 |B| IS_ANCESTOR_OF |
| 64 2:37 |A| IS_IMPLEMENTED_BY |
| 64 2:37 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isImplementedBy_MixinDeclaration_implementsClause() async { |
| await _indexTestUnit(''' |
| class A {} // 1 |
| mixin M implements A {} // 2 |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 22 2:7 |M| IS_ANCESTOR_OF |
| 35 2:20 |A| IS_IMPLEMENTED_BY |
| 35 2:20 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isInvokedBy_FunctionElement() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| library lib; |
| foo() {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart'; |
| import 'lib.dart' as pref; |
| void f() { |
| pref.foo(); // q |
| foo(); // nq |
| }'''); |
| var element = importFindLib().topFunction('foo'); |
| assertElementIndexText(element, r''' |
| 64 4:8 |foo| IS_INVOKED_BY qualified |
| 78 5:3 |foo| IS_INVOKED_BY |
| '''); |
| } |
| |
| test_isInvokedBy_FunctionElement_synthetic_loadLibrary() async { |
| await _indexTestUnit(''' |
| import 'dart:math' deferred as math; |
| void f() { |
| math.loadLibrary(); // 1 |
| math.loadLibrary(); // 2 |
| } |
| '''); |
| var mathLib = findElement2.import('dart:math').importedLibrary2!; |
| var element = mathLib.loadLibraryFunction2; |
| assertElementIndexText(element, r''' |
| 55 3:8 |loadLibrary| IS_INVOKED_BY qualified |
| 82 4:8 |loadLibrary| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isInvokedBy_MethodElement_class() async { |
| await _indexTestUnit(''' |
| class A { |
| foo() {} |
| void m() { |
| this.foo(); // q |
| foo(); // nq |
| } |
| }'''); |
| var element = findElement2.method('foo'); |
| assertElementIndexText(element, r''' |
| 43 4:10 |foo| IS_INVOKED_BY qualified |
| 59 5:5 |foo| IS_INVOKED_BY |
| '''); |
| } |
| |
| test_isInvokedBy_MethodElement_enum() async { |
| await _indexTestUnit(''' |
| enum E { |
| v; |
| void foo() {} |
| void bar() { |
| this.foo(); // q1 |
| foo(); // nq |
| } |
| } |
| void f(E e) { |
| e.foo(); // q2 |
| } |
| '''); |
| var element = findElement2.method('foo'); |
| assertElementIndexText(element, r''' |
| 54 5:10 |foo| IS_INVOKED_BY qualified |
| 71 6:5 |foo| IS_INVOKED_BY |
| 108 10:5 |foo| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isInvokedBy_MethodElement_extensionType() async { |
| await _indexTestUnit(''' |
| extension type A(int it) { |
| void foo() {} |
| void m() { |
| this.foo(); |
| foo(); |
| } |
| }'''); |
| var element = findElement2.method('foo'); |
| assertElementIndexText(element, r''' |
| 65 4:10 |foo| IS_INVOKED_BY qualified |
| 76 5:5 |foo| IS_INVOKED_BY |
| '''); |
| } |
| |
| test_isInvokedBy_MethodElement_ofNamedExtension_instance() async { |
| await _indexTestUnit(''' |
| extension E on int { |
| void foo() {} |
| } |
| |
| void f() { |
| 0.foo(); |
| } |
| '''); |
| var element = findElement2.method('foo'); |
| assertElementIndexText(element, r''' |
| 55 6:5 |foo| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isInvokedBy_MethodElement_ofNamedExtension_static() async { |
| await _indexTestUnit(''' |
| extension E on int { |
| static void foo() {} |
| } |
| |
| void f() { |
| E.foo(); |
| } |
| '''); |
| var element = findElement2.method('foo'); |
| assertElementIndexText(element, r''' |
| 62 6:5 |foo| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isInvokedBy_MethodElement_ofUnnamedExtension_instance() async { |
| await _indexTestUnit(''' |
| extension on int { |
| void foo() {} // int |
| } |
| |
| extension on double { |
| void foo() {} // double |
| } |
| |
| void f() { |
| 0.foo(); // int ref |
| (1.2).foo(); // double ref |
| } |
| '''); |
| |
| var intMethod = findNode.methodDeclaration('foo() {} // int'); |
| assertElementIndexText(intMethod.declaredFragment!.element, r''' |
| 111 10:5 |foo| IS_INVOKED_BY qualified |
| '''); |
| |
| var doubleMethod = findNode.methodDeclaration('foo() {} // double'); |
| assertElementIndexText(doubleMethod.declaredFragment!.element, r''' |
| 137 11:9 |foo| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isInvokedBy_MethodElement_propagatedType() async { |
| await _indexTestUnit(''' |
| class A { |
| foo() {} |
| } |
| void f() { |
| var a = new A(); |
| a.foo(); |
| } |
| '''); |
| var element = findElement2.method('foo'); |
| assertElementIndexText(element, r''' |
| 57 6:5 |foo| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isInvokedBy_operator_class_binary() async { |
| await _indexTestUnit(''' |
| class A { |
| operator +(other) => this; |
| } |
| void f(A a) { |
| print(a + 1); |
| a += 2; |
| ++a; |
| a++; |
| } |
| '''); |
| var element = findElement2.method('+'); |
| assertElementIndexText(element, r''' |
| 65 5:11 |+| IS_INVOKED_BY qualified |
| 75 6:5 |+=| IS_INVOKED_BY qualified |
| 83 7:3 |++| IS_INVOKED_BY qualified |
| 91 8:4 |++| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isInvokedBy_operator_class_index() async { |
| await _indexTestUnit(''' |
| class A { |
| operator [](i) => null; |
| operator []=(i, v) {} |
| } |
| void f(A a) { |
| print(a[0]); |
| a[1] = 42; |
| } |
| '''); |
| var readElement = findElement2.method('[]'); |
| assertElementIndexText(readElement, r''' |
| 85 6:10 |[| IS_INVOKED_BY qualified |
| '''); |
| |
| var writeElement = findElement2.method('[]='); |
| assertElementIndexText(writeElement, r''' |
| 94 7:4 |[| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isInvokedBy_operator_class_prefix() async { |
| await _indexTestUnit(''' |
| class A { |
| A operator ~() => this; |
| } |
| void f(A a) { |
| print(~a); |
| } |
| '''); |
| var element = findElement2.method('~'); |
| assertElementIndexText(element, r''' |
| 60 5:9 |~| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isInvokedBy_operator_enum_binary() async { |
| await _indexTestUnit(''' |
| enum E { |
| v; |
| int operator +(other) => 0; |
| } |
| void f(E e) { |
| e + 1; |
| e += 2; |
| ++e; |
| e++; |
| } |
| '''); |
| var element = findElement2.method('+'); |
| assertElementIndexText(element, r''' |
| 64 6:5 |+| IS_INVOKED_BY qualified |
| 73 7:5 |+=| IS_INVOKED_BY qualified |
| 81 8:3 |++| IS_INVOKED_BY qualified |
| 89 9:4 |++| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isInvokedBy_operator_enum_index() async { |
| await _indexTestUnit(''' |
| enum E { |
| v; |
| int operator [](int index) => 0; |
| operator []=(int index, int value) {} |
| } |
| void f(E e) { |
| e[0]; |
| e[1] = 42; |
| } |
| '''); |
| var readElement = findElement2.method('[]'); |
| assertElementIndexText(readElement, r''' |
| 108 7:4 |[| IS_INVOKED_BY qualified |
| '''); |
| |
| var writeElement = findElement2.method('[]='); |
| assertElementIndexText(writeElement, r''' |
| 116 8:4 |[| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isInvokedBy_operator_enum_prefix() async { |
| await _indexTestUnit(''' |
| enum E { |
| e; |
| int operator ~() => 0; |
| } |
| void f(E e) { |
| ~e; |
| } |
| '''); |
| var element = findElement2.method('~'); |
| assertElementIndexText(element, r''' |
| 57 6:3 |~| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isMixedBy_ClassDeclaration_TypeAliasElement() async { |
| await _indexTestUnit(''' |
| class A<T> {} |
| typedef B = A<int>; |
| class C extends Object with B {} |
| '''); |
| var element = findElement2.typeAlias('B'); |
| assertElementIndexText(element, r''' |
| 62 3:29 |B| IS_MIXED_IN_BY |
| 62 3:29 |B| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isMixedInBy_ClassDeclaration_class() async { |
| await _indexTestUnit(''' |
| class A {} // 1 |
| class B extends Object with A {} // 2 |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 22 2:7 |B| IS_ANCESTOR_OF |
| 44 2:29 |A| IS_MIXED_IN_BY |
| 44 2:29 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isMixedInBy_ClassDeclaration_isQualified() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' as p; |
| class B extends Object with p.A {} // 2 |
| '''); |
| var element = importFindLib().class_('A'); |
| assertElementIndexText(element, r''' |
| 30 2:7 |B| IS_ANCESTOR_OF |
| 54 2:31 |A| IS_MIXED_IN_BY qualified |
| 54 2:31 |A| IS_REFERENCED_BY qualified |
| Prefixes: p |
| '''); |
| } |
| |
| test_isMixedInBy_ClassDeclaration_mixin() async { |
| await _indexTestUnit(''' |
| mixin A {} // 1 |
| class B extends Object with A {} // 2 |
| '''); |
| var element = findElement2.mixin('A'); |
| assertElementIndexText(element, r''' |
| 22 2:7 |B| IS_ANCESTOR_OF |
| 44 2:29 |A| IS_MIXED_IN_BY |
| 44 2:29 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isMixedInBy_ClassTypeAlias_class() async { |
| await _indexTestUnit(''' |
| class A {} // 1 |
| class B = Object with A; // 2 |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 22 2:7 |B| IS_ANCESTOR_OF |
| 38 2:23 |A| IS_MIXED_IN_BY |
| 38 2:23 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isMixedInBy_ClassTypeAlias_mixin() async { |
| await _indexTestUnit(''' |
| mixin A {} // 1 |
| class B = Object with A; // 2 |
| '''); |
| var element = findElement2.mixin('A'); |
| assertElementIndexText(element, r''' |
| 22 2:7 |B| IS_ANCESTOR_OF |
| 38 2:23 |A| IS_MIXED_IN_BY |
| 38 2:23 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isMixedInBy_enum_mixin() async { |
| await _indexTestUnit(''' |
| mixin M {} // 1 |
| enum E with M { // 2 |
| v |
| } |
| '''); |
| var element = findElement2.mixin('M'); |
| assertElementIndexText(element, r''' |
| 21 2:6 |E| IS_ANCESTOR_OF |
| 28 2:13 |M| IS_MIXED_IN_BY |
| 28 2:13 |M| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedAt_PropertyAccessorElement_field_call() async { |
| await _indexTestUnit(''' |
| class A { |
| var field; |
| void m() { |
| this.field(); // q |
| field(); // nq |
| } |
| }'''); |
| var element = findElement2.getter('field'); |
| assertElementIndexText(element, r''' |
| 45 4:10 |field| IS_REFERENCED_BY qualified |
| 63 5:5 |field| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedAt_PropertyAccessorElement_getter_call() async { |
| await _indexTestUnit(''' |
| class A { |
| get ggg => null; |
| void m() { |
| this.ggg(); // q |
| ggg(); // nq |
| } |
| }'''); |
| var element = findElement2.getter('ggg'); |
| assertElementIndexText(element, r''' |
| 51 4:10 |ggg| IS_REFERENCED_BY qualified |
| 67 5:5 |ggg| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_class_getter_in_objectPattern() async { |
| await _indexTestUnit(''' |
| void f(Object? x) { |
| if (x case A(foo: 0)) {} |
| if (x case A(: var foo)) {} |
| } |
| |
| class A { |
| int get foo => 0; |
| } |
| '''); |
| var element = findElement2.getter('foo'); |
| assertElementIndexText(element, r''' |
| 35 2:16 |foo| IS_REFERENCED_BY qualified |
| 62 3:16 || IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_class_method_in_objectPattern() async { |
| await _indexTestUnit(''' |
| void f(Object? x) { |
| if (x case A(foo: _)) {} |
| if (x case A(: var foo)) {} |
| } |
| |
| class A { |
| void foo() {} |
| } |
| '''); |
| var element = findElement2.method('foo'); |
| assertElementIndexText(element, r''' |
| 35 2:16 |foo| IS_REFERENCED_BY qualified |
| 62 3:16 || IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ClassElement() async { |
| await _indexTestUnit(''' |
| class A { |
| static var field; |
| } |
| void f(A p) { |
| A v; |
| new A(); // 2 |
| A.field = 1; |
| print(A.field); // 3 |
| } |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 39 4:8 |A| IS_REFERENCED_BY |
| 48 5:3 |A| IS_REFERENCED_BY |
| 59 6:7 |A| IS_REFERENCED_BY |
| 71 7:3 |A| IS_REFERENCED_BY |
| 92 8:9 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_ClassElement_enum() async { |
| await _indexTestUnit(''' |
| enum MyEnum {a} |
| |
| void f(MyEnum p) { |
| MyEnum v; |
| MyEnum.a; |
| } |
| '''); |
| var element = findElement2.enum_('MyEnum'); |
| assertElementIndexText(element, r''' |
| 24 3:8 |MyEnum| IS_REFERENCED_BY |
| 38 4:3 |MyEnum| IS_REFERENCED_BY |
| 50 5:3 |MyEnum| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_ClassElement_fromExtension() async { |
| await _indexTestUnit(''' |
| class A<T> {} |
| |
| extension E on A<int> {} |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 30 3:16 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_ClassElement_implicitNew() async { |
| await _indexTestUnit(''' |
| class A {} |
| void f() { |
| A(); // invalid code, but still a reference |
| }'''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 24 3:3 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_ClassElement_inGenericAnnotation() async { |
| await _indexTestUnit(''' |
| class A<T> { |
| const A(); |
| } |
| |
| @A<A>() |
| void f() {} |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 21 2:9 |A| IS_REFERENCED_BY |
| 30 5:2 |A| IS_REFERENCED_BY |
| 32 5:4 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_ClassElement_inRecordTypeAnnotation_named() async { |
| await _indexTestUnit(''' |
| class A {} |
| |
| void f(({int foo, A bar}) r) {} |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 30 3:19 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_ClassElement_inRecordTypeAnnotation_positional() async { |
| await _indexTestUnit(''' |
| class A {} |
| |
| void f((int, A) r) {} |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 25 3:14 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_ClassElement_inTypeAlias() async { |
| await _indexTestUnit(''' |
| class A<T> {} |
| |
| typedef B = A<int>; |
| '''); |
| var elementA = findElement2.class_('A'); |
| assertElementIndexText(elementA, r''' |
| 27 3:13 |A| IS_REFERENCED_BY |
| '''); |
| |
| assertElementIndexText(intElement, r''' |
| 29 3:15 |int| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_ClassElement_invocation_isQualified() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' as p; |
| void f() { |
| p.A(); // invalid code, but still a reference |
| }'''); |
| var element = importFindLib().class_('A'); |
| assertElementIndexText(element, r''' |
| 39 3:5 |A| IS_REFERENCED_BY qualified |
| Prefixes: p |
| '''); |
| } |
| |
| test_isReferencedBy_ClassElement_invocationTypeArgument() async { |
| await _indexTestUnit(''' |
| class A {} |
| void f<T>() {} |
| void g() { |
| f<A>(); |
| } |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 41 4:5 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_ClassTypeAlias() async { |
| await _indexTestUnit(''' |
| class A {} |
| class B = Object with A; |
| void f(B p) { |
| B v; |
| } |
| '''); |
| var element = findElement2.class_('B'); |
| assertElementIndexText(element, r''' |
| 43 3:8 |B| IS_REFERENCED_BY |
| 52 4:3 |B| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_commentReference() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart'; |
| |
| /// An [A]. |
| void f(A a) {} |
| '''); |
| var element = findElement2.function('f').formalParameters[0].type.element3!; |
| assertElementIndexText(element, r''' |
| 28 3:9 |A| IS_REFERENCED_BY |
| 39 4:8 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_commentReference_withAndWithoutPrefix() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart'; |
| import 'lib.dart' as p; |
| |
| /// A [p.A] and [A]. |
| void f(p.A a) {} |
| '''); |
| var element = findElement2.function('f').formalParameters[0].type.element3!; |
| assertElementIndexText(element, r''' |
| 53 4:10 |A| IS_REFERENCED_BY qualified |
| 61 4:18 |A| IS_REFERENCED_BY |
| 74 5:10 |A| IS_REFERENCED_BY qualified |
| Prefixes: p,(unprefixed) |
| '''); |
| } |
| |
| test_isReferencedBy_commentReference_withPrefix() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' as p; |
| |
| /// A [p.A]. |
| void f(p.A a) {} |
| '''); |
| var element = findElement2.function('f').formalParameters[0].type.element3!; |
| assertElementIndexText(element, r''' |
| 34 3:10 |A| IS_REFERENCED_BY qualified |
| 47 4:10 |A| IS_REFERENCED_BY qualified |
| Prefixes: p |
| '''); |
| } |
| |
| test_isReferencedBy_CompilationUnitElement_export() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| library lib; |
| '''); |
| await _indexTestUnit(''' |
| export 'lib.dart'; |
| '''); |
| var export = findElement2.export('package:test/lib.dart'); |
| var fragment = export.exportedLibrary2!.firstFragment; |
| assertLibraryFragmentIndexText(fragment, r''' |
| 7 1:8 |'lib.dart'| |
| '''); |
| } |
| |
| test_isReferencedBy_CompilationUnitElement_import() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| library lib; |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart'; |
| '''); |
| var import = findElement2.import('package:test/lib.dart'); |
| var fragment = import.importedLibrary2!.firstFragment; |
| assertLibraryFragmentIndexText(fragment, r''' |
| 7 1:8 |'lib.dart'| |
| '''); |
| } |
| |
| test_isReferencedBy_CompilationUnitElement_part() async { |
| newFile('$testPackageLibPath/my_unit.dart', 'part of my_lib;'); |
| await _indexTestUnit(''' |
| library my_lib; |
| part 'my_unit.dart'; |
| '''); |
| var fragment = findElement2.part('package:test/my_unit.dart'); |
| assertLibraryFragmentIndexText(fragment, r''' |
| 21 2:6 |'my_unit.dart'| |
| '''); |
| } |
| |
| test_isReferencedBy_CompilationUnitElement_part_inPart() async { |
| newFile('$testPackageLibPath/a.dart', 'part of lib;'); |
| newFile('$testPackageLibPath/b.dart', ''' |
| library lib; |
| part 'a.dart'; |
| '''); |
| await _indexTestUnit(''' |
| part 'b.dart'; |
| '''); |
| // No exception, even though a.dart is a part of b.dart part. |
| } |
| |
| test_isReferencedBy_ConstructorElement_class_named() async { |
| await _indexTestUnit(''' |
| /// [new A.foo] 1 |
| class A { |
| A.foo() {} |
| A.bar() : this.foo(); // 2 |
| } |
| class B extends A { |
| B() : super.foo(); // 3 |
| factory B.bar() = A.foo; // 4 |
| } |
| void f() { |
| A.foo(); // 5 |
| A.foo; // 6 |
| } |
| '''); |
| var element = findElement2.constructor('foo'); |
| assertElementIndexText(element, r''' |
| 10 1:11 |.foo| IS_REFERENCED_BY qualified |
| 57 4:17 |.foo| IS_INVOKED_BY qualified |
| 105 7:14 |.foo| IS_INVOKED_BY qualified |
| 139 8:22 |.foo| IS_REFERENCED_BY qualified |
| 166 11:4 |.foo| IS_INVOKED_BY qualified |
| 182 12:4 |.foo| IS_REFERENCED_BY_CONSTRUCTOR_TEAR_OFF qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ConstructorElement_class_namedOnlyWithDot() async { |
| await _indexTestUnit(''' |
| class A { |
| A.named() {} |
| } |
| void f() { |
| new A.named(); |
| } |
| '''); |
| // has ".named()", but does not have "named()" |
| var constructorName = findNode.constructorName('.named();'); |
| var offsetWithoutDot = constructorName.name!.offset; |
| var offsetWithDot = constructorName.period!.offset; |
| expect(index.usedElementOffsets, isNot(contains(offsetWithoutDot))); |
| expect(index.usedElementOffsets, contains(offsetWithDot)); |
| } |
| |
| test_isReferencedBy_ConstructorElement_class_redirection() async { |
| await _indexTestUnit(''' |
| class A { |
| A() : this.bar(); // 1 |
| A.foo() : this(); // 2 |
| A.bar(); |
| } |
| '''); |
| var constructor = findElement2.unnamedConstructor('A'); |
| assertElementIndexText(constructor, r''' |
| 51 3:17 || IS_INVOKED_BY qualified |
| '''); |
| |
| var constructor_bar = findElement2.constructor('bar'); |
| assertElementIndexText(constructor_bar, r''' |
| 22 2:13 |.bar| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ConstructorElement_class_unnamed_declared() async { |
| await _indexTestUnit(''' |
| /// [new A] 1 |
| class A { |
| A() {} |
| A.other() : this(); // 2 |
| } |
| class B extends A { |
| B() : super(); // 3 |
| factory B.other() = A; // 4 |
| } |
| void f() { |
| A(); // 5 |
| A.new; // 6 |
| } |
| '''); |
| var element = findElement2.unnamedConstructor('A'); |
| assertElementIndexText(element, r''' |
| 10 1:11 || IS_REFERENCED_BY qualified |
| 51 4:19 || IS_INVOKED_BY qualified |
| 95 7:14 || IS_INVOKED_BY qualified |
| 127 8:24 || IS_REFERENCED_BY qualified |
| 150 11:4 || IS_INVOKED_BY qualified |
| 162 12:4 |.new| IS_REFERENCED_BY_CONSTRUCTOR_TEAR_OFF qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ConstructorElement_class_unnamed_declared_new() async { |
| await _indexTestUnit(''' |
| /// [new A] 1 |
| class A { |
| A.new() {} |
| A.other() : this(); // 2 |
| } |
| class B extends A { |
| B() : super(); // 3 |
| factory B.bar() = A; // 4 |
| } |
| void f() { |
| A(); // 5 |
| A.new; // 6 |
| } |
| '''); |
| var element = findElement2.unnamedConstructor('A'); |
| assertElementIndexText(element, r''' |
| 10 1:11 || IS_REFERENCED_BY qualified |
| 55 4:19 || IS_INVOKED_BY qualified |
| 99 7:14 || IS_INVOKED_BY qualified |
| 129 8:22 || IS_REFERENCED_BY qualified |
| 152 11:4 || IS_INVOKED_BY qualified |
| 164 12:4 |.new| IS_REFERENCED_BY_CONSTRUCTOR_TEAR_OFF qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ConstructorElement_class_unnamed_synthetic() async { |
| await _indexTestUnit(''' |
| /// [new A] 1 |
| class A {} |
| class B extends A { |
| B() : super(); // 2 |
| factory B.bar() = A; // 3 |
| } |
| void f() { |
| A(); // 4 |
| A.new; // 5 |
| } |
| '''); |
| var element = findElement2.unnamedConstructor('A'); |
| assertElementIndexText(element, r''' |
| 10 1:11 || IS_REFERENCED_BY qualified |
| 58 4:14 || IS_INVOKED_BY qualified |
| 88 5:22 || IS_REFERENCED_BY qualified |
| 111 8:4 || IS_INVOKED_BY qualified |
| 123 9:4 |.new| IS_REFERENCED_BY_CONSTRUCTOR_TEAR_OFF qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ConstructorElement_classTypeAlias() async { |
| await _indexTestUnit(''' |
| class M {} |
| class A implements B { |
| A() {} |
| A.named() {} |
| } |
| class B = A with M; |
| class C = B with M; |
| void f() { |
| new B(); // B1 |
| new B.named(); // B2 |
| new C(); // C1 |
| new C.named(); // C2 |
| } |
| '''); |
| var constructor = findElement2.unnamedConstructor('A'); |
| assertElementIndexText(constructor, r''' |
| 118 9:8 || IS_INVOKED_BY qualified |
| 158 11:8 || IS_INVOKED_BY qualified |
| '''); |
| |
| var constructor_named = findElement2.constructor('named', of: 'A'); |
| assertElementIndexText(constructor_named, r''' |
| 135 10:8 |.named| IS_INVOKED_BY qualified |
| 175 12:8 |.named| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ConstructorElement_classTypeAlias_cycle() async { |
| await _indexTestUnit(''' |
| class M {} |
| class A = B with M; |
| class B = A with M; |
| void f() { |
| new A(); |
| new B(); |
| } |
| '''); |
| // No additional validation, but it should not fail with stack overflow. |
| } |
| |
| test_isReferencedBy_ConstructorElement_dotShorthand() async { |
| await _indexTestUnit(''' |
| class A {} |
| void f() { |
| A a = .new(); // 1 |
| A tearOff = .new; // 2, is also a compile-time error |
| } |
| '''); |
| var element = findElement2.unnamedConstructor('A'); |
| assertElementIndexText(element, r''' |
| 31 3:10 |new| IS_INVOKED_BY qualified |
| 58 4:16 |new| IS_REFERENCED_BY_CONSTRUCTOR_TEAR_OFF qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ConstructorElement_enum_named() async { |
| await _indexTestUnit(''' |
| /// [new E.foo] 1 |
| enum E { |
| v.foo(); // 2 |
| E.foo(); |
| E.bar() : this.foo(); // 3 |
| } |
| '''); |
| var element = findElement2.constructor('foo'); |
| assertElementIndexText(element, r''' |
| 10 1:11 |.foo| IS_REFERENCED_BY qualified |
| 30 3:4 |.foo| IS_INVOKED_BY qualified |
| 70 5:17 |.foo| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ConstructorElement_enum_unnamed_declared() async { |
| await _indexTestUnit(''' |
| /// [new E] 1 |
| enum E { |
| v1, // 2 |
| v2(), // 3 |
| v3.new(); // 4 |
| E(); |
| E.other() : this(); // 5 |
| } |
| '''); |
| var element = findElement2.unnamedConstructor('E'); |
| assertElementIndexText(element, r''' |
| 10 1:11 || IS_REFERENCED_BY qualified |
| 27 3:5 || IS_INVOKED_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS qualified |
| 38 4:5 || IS_INVOKED_BY qualified |
| 51 5:5 |.new| IS_INVOKED_BY qualified |
| 89 7:19 || IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ConstructorElement_enum_unnamed_declared_new() async { |
| await _indexTestUnit(''' |
| /// [new E] 1 |
| enum E { |
| v1, // 2 |
| v2(), // 3 |
| v3.new(); // 4 |
| E.new() {} |
| E.other() : this(); // 5 |
| } |
| '''); |
| var element = findElement2.unnamedConstructor('E'); |
| assertElementIndexText(element, r''' |
| 10 1:11 || IS_REFERENCED_BY qualified |
| 27 3:5 || IS_INVOKED_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS qualified |
| 38 4:5 || IS_INVOKED_BY qualified |
| 51 5:5 |.new| IS_INVOKED_BY qualified |
| 95 7:19 || IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ConstructorElement_enum_unnamed_synthetic() async { |
| await _indexTestUnit(''' |
| /// [new E] 1 |
| enum E { |
| v1, // 2 |
| v2(), // 3 |
| v3.new(); // 4 |
| } |
| '''); |
| var element = findElement2.unnamedConstructor('E'); |
| assertElementIndexText(element, r''' |
| 10 1:11 || IS_REFERENCED_BY qualified |
| 27 3:5 || IS_INVOKED_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS qualified |
| 38 4:5 || IS_INVOKED_BY qualified |
| 51 5:5 |.new| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ConstructorElement_extensionType_primary_named() async { |
| await _indexTestUnit(''' |
| /// [new A.foo] |
| extension type A.foo(int it) { |
| A.bar() : this.foo(0); |
| } |
| void f() { |
| A.foo(); |
| A.foo; |
| } |
| '''); |
| var element = findElement2.constructor('foo'); |
| assertElementIndexText(element, r''' |
| 10 1:11 |.foo| IS_REFERENCED_BY qualified |
| 63 3:17 |.foo| IS_INVOKED_BY qualified |
| 88 6:4 |.foo| IS_INVOKED_BY qualified |
| 99 7:4 |.foo| IS_REFERENCED_BY_CONSTRUCTOR_TEAR_OFF qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ConstructorElement_extensionType_primary_unnamed() async { |
| await _indexTestUnit(''' |
| /// [new A] |
| extension type A(int it) { |
| A.bar() : this(0); |
| } |
| void f() { |
| A(); |
| A.new; |
| } |
| '''); |
| var element = findElement2.unnamedConstructor('A'); |
| assertElementIndexText(element, r''' |
| 10 1:11 || IS_REFERENCED_BY qualified |
| 55 3:17 || IS_INVOKED_BY qualified |
| 76 6:4 || IS_INVOKED_BY qualified |
| 83 7:4 |.new| IS_REFERENCED_BY_CONSTRUCTOR_TEAR_OFF qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ConstructorElement_extensionType_secondary_named() async { |
| await _indexTestUnit(''' |
| /// [new A.foo] |
| extension type A(int it) { |
| A.foo(this.it); |
| A.bar() : this.foo(0); |
| } |
| void f() { |
| A.foo(); |
| A.foo; |
| } |
| '''); |
| var element = findElement2.constructor('foo'); |
| assertElementIndexText(element, r''' |
| 10 1:11 |.foo| IS_REFERENCED_BY qualified |
| 77 4:17 |.foo| IS_INVOKED_BY qualified |
| 102 7:4 |.foo| IS_INVOKED_BY qualified |
| 113 8:4 |.foo| IS_REFERENCED_BY_CONSTRUCTOR_TEAR_OFF qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ConstructorElement_extensionType_secondary_unnamed() async { |
| await _indexTestUnit(''' |
| /// [new A] |
| extension type A.named(int it) { |
| A(this.it); |
| A.bar() : this(0); |
| } |
| void f() { |
| A(); |
| A.new; |
| } |
| '''); |
| var element = findElement2.unnamedConstructor('A'); |
| assertElementIndexText(element, r''' |
| 10 1:11 || IS_REFERENCED_BY qualified |
| 75 4:17 || IS_INVOKED_BY qualified |
| 96 7:4 || IS_INVOKED_BY qualified |
| 103 8:4 |.new| IS_REFERENCED_BY_CONSTRUCTOR_TEAR_OFF qualified |
| '''); |
| } |
| |
| test_isReferencedBy_DynamicElement() async { |
| await _indexTestUnit(''' |
| dynamic f() { |
| }'''); |
| expect(index.usedElementOffsets, isEmpty); |
| } |
| |
| test_isReferencedBy_enumConstant() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| enum E { |
| c; |
| } |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart'; |
| |
| void f(E e) { |
| f(E.c); |
| } |
| '''); |
| var element = findElement2.function('f').formalParameters[0].type.element3!; |
| assertElementIndexText(element, r''' |
| 27 3:8 |E| IS_REFERENCED_BY |
| 38 4:5 |E| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_enumConstant_withAndWithoutPrefixes() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| enum E { |
| c; |
| } |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' as p; |
| import 'lib.dart'; |
| |
| void f(p.E e) { |
| f(E.c); |
| } |
| '''); |
| var element = findElement2.function('f').formalParameters[0].type.element3!; |
| assertElementIndexText(element, r''' |
| 53 4:10 |E| IS_REFERENCED_BY qualified |
| 64 5:5 |E| IS_REFERENCED_BY |
| Prefixes: p,(unprefixed) |
| '''); |
| } |
| |
| test_isReferencedBy_enumConstant_withMultiplePrefixes() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| enum E { |
| c; |
| } |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' as p; |
| import 'lib.dart' as q; |
| |
| void f(p.E e) { |
| f(q.E.c); |
| } |
| '''); |
| var element = findElement2.function('f').formalParameters[0].type.element3!; |
| assertElementIndexText(element, r''' |
| 58 4:10 |E| IS_REFERENCED_BY qualified |
| 71 5:7 |E| IS_REFERENCED_BY qualified |
| Prefixes: p,q |
| '''); |
| } |
| |
| test_isReferencedBy_enumConstant_withPrefix() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| enum E { |
| c; |
| } |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' as p; |
| |
| void f(p.E e) { |
| f(p.E.c); |
| } |
| '''); |
| var element = findElement2.function('f').formalParameters[0].type.element3!; |
| assertElementIndexText(element, r''' |
| 34 3:10 |E| IS_REFERENCED_BY qualified |
| 47 4:7 |E| IS_REFERENCED_BY qualified |
| Prefixes: p |
| '''); |
| } |
| |
| test_isReferencedBy_ExtensionElement() async { |
| await _indexTestUnit(''' |
| extension E on int { |
| void foo() {} |
| } |
| |
| void f() { |
| E(0).foo(); |
| } |
| '''); |
| var element = findElement2.extension_('E'); |
| assertElementIndexText(element, r''' |
| 53 6:3 |E| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_ExtensionElement_withPrefix() async { |
| await _indexTestUnit(''' |
| extension E on int { |
| void foo() {} |
| } |
| |
| void f() { |
| E(0).foo(); |
| } |
| '''); |
| var element = findElement2.extension_('E'); |
| assertElementIndexText(element, r''' |
| 53 6:3 |E| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_extensionType() async { |
| await _indexTestUnit(''' |
| extension type A(int it) { |
| static var field; |
| } |
| void f(A p) { |
| A v; |
| new A(); |
| A.field = 1; |
| A.field; |
| } |
| '''); |
| var element = findElement2.extensionType('A'); |
| assertElementIndexText(element, r''' |
| 56 4:8 |A| IS_REFERENCED_BY |
| 65 5:3 |A| IS_REFERENCED_BY |
| 76 6:7 |A| IS_REFERENCED_BY |
| 83 7:3 |A| IS_REFERENCED_BY |
| 98 8:3 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_FieldElement_class() async { |
| await _indexTestUnit(''' |
| class A { |
| var field; |
| A({this.field}); |
| m() { |
| field = 2; // nq |
| print(field); // nq |
| } |
| } |
| void f(A a) { |
| a.field = 3; // q |
| print(a.field); // q |
| new A(field: 4); |
| } |
| '''); |
| var field = findElement2.field('field'); |
| var getter = field.getter2!; |
| var setter = field.setter2!; |
| |
| assertElementIndexText(field, r''' |
| 33 3:11 |field| IS_WRITTEN_BY qualified |
| '''); |
| |
| assertElementIndexText(getter, r''' |
| 81 6:11 |field| IS_REFERENCED_BY |
| 145 11:11 |field| IS_REFERENCED_BY qualified |
| '''); |
| |
| assertElementIndexText(setter, r''' |
| 54 5:5 |field| IS_REFERENCED_BY |
| 119 10:5 |field| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_FieldElement_class_multiple() async { |
| await _indexTestUnit(''' |
| class A { |
| var aaa; |
| var bbb; |
| A(this.aaa, this.bbb) {} |
| m() { |
| print(aaa); |
| aaa = 1; |
| print(bbb); |
| bbb = 2; |
| } |
| } |
| '''); |
| // aaa |
| { |
| var field = findElement2.field('aaa'); |
| var getter = field.getter2!; |
| var setter = field.setter2!; |
| assertElementIndexText(field, r''' |
| 41 4:10 |aaa| IS_WRITTEN_BY qualified |
| '''); |
| assertElementIndexText(getter, r''' |
| 77 6:11 |aaa| IS_REFERENCED_BY |
| '''); |
| assertElementIndexText(setter, r''' |
| 87 7:5 |aaa| IS_REFERENCED_BY |
| '''); |
| } |
| // bbb |
| { |
| var field = findElement2.field('bbb'); |
| var getter = field.getter2!; |
| var setter = field.setter2!; |
| assertElementIndexText(field, r''' |
| 51 4:20 |bbb| IS_WRITTEN_BY qualified |
| '''); |
| assertElementIndexText(getter, r''' |
| 106 8:11 |bbb| IS_REFERENCED_BY |
| '''); |
| assertElementIndexText(setter, r''' |
| 116 9:5 |bbb| IS_REFERENCED_BY |
| '''); |
| } |
| } |
| |
| test_isReferencedBy_FieldElement_class_synthetic_hasGetter() async { |
| await _indexTestUnit(''' |
| class A { |
| A() : f = 42; |
| int get f => 0; |
| } |
| '''); |
| var element = findElement2.field('f'); |
| assertElementIndexText(element, r''' |
| 18 2:9 |f| IS_WRITTEN_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_FieldElement_class_synthetic_hasGetterSetter() async { |
| await _indexTestUnit(''' |
| class A { |
| A() : f = 42; |
| int get f => 0; |
| set f(_) {} |
| } |
| '''); |
| var element = findElement2.field('f'); |
| assertElementIndexText(element, r''' |
| 18 2:9 |f| IS_WRITTEN_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_FieldElement_class_synthetic_hasSetter() async { |
| await _indexTestUnit(''' |
| class A { |
| A() : f = 42; |
| set f(_) {} |
| } |
| '''); |
| var element = findElement2.field('f'); |
| assertElementIndexText(element, r''' |
| 18 2:9 |f| IS_WRITTEN_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_FieldElement_dotShorthand() async { |
| await _indexTestUnit(''' |
| class A { |
| static A field = A(); |
| } |
| void f() { |
| A a = .field; // 1 |
| } |
| '''); |
| var element = findElement2.field('field').getter2!; |
| assertElementIndexText(element, r''' |
| 56 5:10 |field| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_FieldElement_enum() async { |
| await _indexTestUnit(''' |
| enum E { |
| v; |
| int? field; // a compile-time error |
| E({this.field}); |
| void foo() { |
| field = 2; // nq |
| field; // nq |
| } |
| } |
| void f(E e) { |
| e.field = 3; // q |
| e.field; // q |
| E(field: 4); |
| } |
| '''); |
| var field = findElement2.field('field'); |
| var getter = field.getter2!; |
| var setter = field.setter2!; |
| |
| assertElementIndexText(field, r''' |
| 62 4:11 |field| IS_WRITTEN_BY qualified |
| '''); |
| |
| assertElementIndexText(getter, r''' |
| 111 7:5 |field| IS_REFERENCED_BY |
| 168 12:5 |field| IS_REFERENCED_BY qualified |
| '''); |
| |
| assertElementIndexText(setter, r''' |
| 90 6:5 |field| IS_REFERENCED_BY |
| 148 11:5 |field| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_FieldElement_enum_index() async { |
| await _indexTestUnit(''' |
| enum MyEnum { |
| A, B, C |
| } |
| void f() { |
| print(MyEnum.values); |
| print(MyEnum.A.index); |
| print(MyEnum.A); |
| print(MyEnum.B); |
| } |
| '''); |
| |
| assertElementIndexText(findElement2.getter('values'), r''' |
| 52 5:16 |values| IS_REFERENCED_BY qualified |
| '''); |
| |
| var index = typeProvider.enumElement2!.getGetter('index')!; |
| assertElementIndexText(index, r''' |
| 78 6:18 |index| IS_REFERENCED_BY qualified |
| '''); |
| |
| assertElementIndexText(findElement2.getter('A'), r''' |
| 76 6:16 |A| IS_REFERENCED_BY qualified |
| 101 7:16 |A| IS_REFERENCED_BY qualified |
| '''); |
| |
| assertElementIndexText(findElement2.getter('B'), r''' |
| 120 8:16 |B| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_FieldElement_enum_synthetic_hasGetter() async { |
| await _indexTestUnit(''' |
| enum E { |
| v; |
| E() : f = 42; |
| int get f => 0; |
| } |
| '''); |
| var element = findElement2.field('f'); |
| assertElementIndexText(element, r''' |
| 22 3:9 |f| IS_WRITTEN_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_FieldElement_enum_synthetic_hasGetterSetter() async { |
| await _indexTestUnit(''' |
| enum E { |
| v; |
| E() : f = 42; |
| int get f => 0; |
| set f(_) {} |
| } |
| '''); |
| var element = findElement2.field('f'); |
| assertElementIndexText(element, r''' |
| 22 3:9 |f| IS_WRITTEN_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_FieldElement_enum_synthetic_hasSetter() async { |
| await _indexTestUnit(''' |
| enum E { |
| v; |
| E() : f = 42; |
| set f(_) {} |
| } |
| '''); |
| var element = findElement2.field('f'); |
| assertElementIndexText(element, r''' |
| 22 3:9 |f| IS_WRITTEN_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_FieldElement_extensionType() async { |
| await _indexTestUnit(''' |
| extension type A(int it) { |
| static int field = 0; |
| void f() { |
| field = 0; |
| field; |
| } |
| } |
| void f() { |
| A.field = 0; |
| A.field; |
| } |
| '''); |
| var field = findElement2.field('field'); |
| var getter = field.getter2!; |
| var setter = field.setter2!; |
| |
| assertElementIndexText(getter, r''' |
| 83 5:5 |field| IS_REFERENCED_BY |
| 126 10:5 |field| IS_REFERENCED_BY qualified |
| '''); |
| |
| assertElementIndexText(setter, r''' |
| 68 4:5 |field| IS_REFERENCED_BY |
| 111 9:5 |field| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_FunctionElement() async { |
| await _indexTestUnit(''' |
| foo() {} |
| void f() { |
| print(foo); |
| print(foo()); |
| } |
| '''); |
| var element = findElement2.topFunction('foo'); |
| assertElementIndexText(element, r''' |
| 28 3:9 |foo| IS_REFERENCED_BY |
| 42 4:9 |foo| IS_INVOKED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_FunctionElement_with_LibraryElement() async { |
| newFile('$testPackageLibPath/foo.dart', r''' |
| bar() {} |
| '''); |
| await _indexTestUnit(''' |
| import "foo.dart"; |
| void f() { |
| bar(); |
| } |
| '''); |
| |
| var importFind = findElement2.importFind('package:test/foo.dart'); |
| var importedFragment = importFind.importedLibrary.firstFragment; |
| importedFragment as LibraryFragmentImpl; |
| assertLibraryFragmentIndexText(importedFragment, r''' |
| 7 1:8 |"foo.dart"| |
| '''); |
| |
| var bar = importFind.topFunction('bar'); |
| assertElementIndexText(bar, r''' |
| 32 3:3 |bar| IS_INVOKED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_FunctionTypeAliasElement() async { |
| await _indexTestUnit(''' |
| typedef A(); |
| void f(A p) { |
| } |
| '''); |
| var element = findElement2.typeAlias('A'); |
| assertElementIndexText(element, r''' |
| 20 2:8 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_getter_withPrefix() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A { |
| static int get f => 0; |
| } |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' as p; |
| |
| int f() => p.A.f; |
| |
| class B extends p.A {} |
| '''); |
| var element = findElement2.class_('B').supertype!.element3; |
| assertElementIndexText(element, r''' |
| 38 3:14 |A| IS_REFERENCED_BY qualified |
| 50 5:7 |B| IS_ANCESTOR_OF |
| 62 5:19 |A| IS_EXTENDED_BY qualified |
| 62 5:19 |A| IS_REFERENCED_BY qualified |
| Prefixes: p |
| '''); |
| } |
| |
| /// There was a bug in the AST structure, when single [Comment] was cloned and |
| /// assigned to both [FieldDeclaration] and [VariableDeclaration]. |
| /// |
| /// This caused duplicate indexing. |
| /// Here we test that the problem is fixed one way or another. |
| test_isReferencedBy_identifierInComment() async { |
| await _indexTestUnit(''' |
| class A {} |
| /// [A] text |
| var myVariable = null; |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 16 2:6 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_MethodElement_class() async { |
| await _indexTestUnit(''' |
| class A { |
| method() {} |
| void m() { |
| print(this.method); // q |
| print(method); // nq |
| } |
| }'''); |
| var element = findElement2.method('method'); |
| assertElementIndexText(element, r''' |
| 52 4:16 |method| IS_REFERENCED_BY qualified |
| 76 5:11 |method| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_MethodElement_dotShorthand() async { |
| await _indexTestUnit(''' |
| class A { |
| static A method() => A(); |
| } |
| void f() { |
| A a = .method(); // 1 |
| } |
| '''); |
| var element = findElement2.method('method'); |
| assertElementIndexText(element, r''' |
| 60 5:10 |method| IS_INVOKED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_MethodElement_enum() async { |
| await _indexTestUnit(''' |
| enum E { |
| v; |
| void foo() {} |
| void bar() { |
| this.foo; // q1 |
| foo; // nq |
| } |
| } |
| void f(E e) { |
| e.foo; // q2 |
| } |
| '''); |
| var element = findElement2.method('foo'); |
| assertElementIndexText(element, r''' |
| 54 5:10 |foo| IS_REFERENCED_BY qualified |
| 69 6:5 |foo| IS_REFERENCED_BY |
| 104 10:5 |foo| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_methodInvocation_withPrefix() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A { |
| static void m() {} |
| } |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' as p; |
| |
| void f() => p.A.m(); |
| |
| class B extends p.A {} |
| '''); |
| var element = findElement2.class_('B').supertype!.element3; |
| assertElementIndexText(element, r''' |
| 39 3:15 |A| IS_REFERENCED_BY qualified |
| 53 5:7 |B| IS_ANCESTOR_OF |
| 65 5:19 |A| IS_EXTENDED_BY qualified |
| 65 5:19 |A| IS_REFERENCED_BY qualified |
| Prefixes: p |
| '''); |
| } |
| |
| test_isReferencedBy_MultiplyDefinedElement() async { |
| newFile('$testPackageLibPath/a1.dart', 'class A {}'); |
| newFile('$testPackageLibPath/a2.dart', 'class A {}'); |
| await _indexTestUnit(''' |
| import 'a1.dart'; |
| import 'a2.dart'; |
| A v = null; |
| '''); |
| } |
| |
| test_isReferencedBy_NeverElement() async { |
| await _indexTestUnit(''' |
| Never f() { |
| }'''); |
| expect(index.usedElementOffsets, isEmpty); |
| } |
| |
| test_isReferencedBy_ParameterElement() async { |
| await _indexTestUnit(''' |
| foo({var p}) {} |
| void f() { |
| foo(p: 1); |
| } |
| '''); |
| var element = findElement2.parameter('p'); |
| assertElementIndexText(element, r''' |
| 33 3:7 |p| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ParameterElement_genericFunctionType() async { |
| await _indexTestUnit(''' |
| typedef F = void Function({int? p}); |
| |
| void g(F f) { |
| f(p: 0); |
| } |
| '''); |
| // We should not crash because of reference to "p" - a named parameter |
| // of a generic function type. |
| } |
| |
| test_isReferencedBy_ParameterElement_genericFunctionType_call() async { |
| await _indexTestUnit(''' |
| typedef F<T> = void Function({T? test}); |
| |
| void g(F<int> f) { |
| f.call(test: 0); |
| } |
| '''); |
| // No exceptions. |
| } |
| |
| test_isReferencedBy_ParameterElement_multiplyDefined_generic() async { |
| newFile('/test/lib/a.dart', r''' |
| void foo<T>({T? a}) {} |
| '''); |
| newFile('/test/lib/b.dart', r''' |
| void foo<T>({T? a}) {} |
| '''); |
| await _indexTestUnit(r""" |
| import 'a.dart'; |
| import 'b.dart'; |
| |
| void f() { |
| foo(a: 0); |
| } |
| """); |
| // No exceptions. |
| } |
| |
| test_isReferencedBy_ParameterElement_ofConstructor_super_named() async { |
| await _indexTestUnit(''' |
| class A { |
| A({required int a}); |
| } |
| class B extends A { |
| B({required super.a}); // ref |
| } |
| '''); |
| var element = findElement2.unnamedConstructor('A').parameter('a'); |
| assertElementIndexText(element, r''' |
| 75 5:21 |a| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ParameterElement_ofConstructor_super_positional() async { |
| await _indexTestUnit(''' |
| class A { |
| A(int a); |
| } |
| class B extends A { |
| B(super.a); // ref |
| } |
| '''); |
| var element = findElement2.unnamedConstructor('A').parameter('a'); |
| assertElementIndexText(element, r''' |
| 54 5:11 |a| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ParameterElement_optionalNamed_ofConstructor_genericClass() async { |
| await _indexTestUnit(''' |
| class A<T> { |
| A({T? test}); |
| } |
| |
| void f() { |
| A(test: 0); |
| } |
| '''); |
| var element = findElement2.parameter('test'); |
| assertElementIndexText(element, r''' |
| 47 6:5 |test| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ParameterElement_optionalNamed_ofMethod_genericClass() async { |
| await _indexTestUnit(''' |
| class A<T> { |
| void foo({T? test}) {} |
| } |
| |
| void f(A<int> a) { |
| a.foo(test: 0); |
| } |
| '''); |
| var element = findElement2.parameter('test'); |
| assertElementIndexText(element, r''' |
| 68 6:9 |test| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ParameterElement_optionalNamed_ofTopFunction() async { |
| await _indexTestUnit(''' |
| void foo({int? test}) {} |
| |
| void() { |
| foo(test: 0); |
| } |
| '''); |
| var element = findElement2.parameter('test'); |
| assertElementIndexText(element, r''' |
| 41 4:7 |test| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ParameterElement_optionalNamed_ofTopFunction_anywhere() async { |
| await _indexTestUnit(''' |
| void foo(int a, int b, {int? test}) {} |
| |
| void() { |
| foo(1, test: 0, 2); |
| } |
| '''); |
| var element = findElement2.parameter('test'); |
| assertElementIndexText(element, r''' |
| 58 4:10 |test| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ParameterElement_optionalPositional() async { |
| await _indexTestUnit(''' |
| foo([p]) { |
| p; // 1 |
| } |
| void f() { |
| foo(1); // 2 |
| } |
| '''); |
| var element = findElement2.parameter('p'); |
| assertElementIndexText(element, r''' |
| 40 5:7 || IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_ParameterElement_requiredNamed_ofTopFunction() async { |
| await _indexTestUnit(''' |
| void foo({required int test}) {} |
| |
| void() { |
| foo(test: 0); |
| } |
| '''); |
| var element = findElement2.parameter('test'); |
| assertElementIndexText(element, r''' |
| 49 4:7 |test| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_PropertyAccessor_ofNamedExtension_instance() async { |
| await _indexTestUnit(''' |
| extension E on int { |
| int get foo => 0; |
| void set foo(int _) {} |
| } |
| |
| void f() { |
| 0.foo; |
| 0.foo = 0; |
| } |
| '''); |
| var getter = findElement2.getter('foo'); |
| var setter = findElement2.setter('foo'); |
| |
| assertElementIndexText(getter, r''' |
| 84 7:5 |foo| IS_REFERENCED_BY qualified |
| '''); |
| |
| assertElementIndexText(setter, r''' |
| 93 8:5 |foo| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_PropertyAccessor_ofNamedExtension_static() async { |
| await _indexTestUnit(''' |
| extension E on int { |
| static int get foo => 0; |
| static void set foo(int _) {} |
| } |
| |
| void f() { |
| E.foo; |
| E.foo = 0; |
| } |
| '''); |
| var getter = findElement2.getter('foo'); |
| var setter = findElement2.setter('foo'); |
| |
| assertElementIndexText(getter, r''' |
| 98 7:5 |foo| IS_REFERENCED_BY qualified |
| '''); |
| |
| assertElementIndexText(setter, r''' |
| 107 8:5 |foo| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_PropertyAccessor_ofUnnamedExtension_instance() async { |
| await _indexTestUnit(''' |
| extension on int { |
| int get foo => 0; // int getter |
| void set foo(int _) {} // int setter |
| } |
| |
| extension on double { |
| int get foo => 0; // double getter |
| void set foo(int _) {} // double setter |
| } |
| |
| void f() { |
| 0.foo; // int getter ref |
| 0.foo = 0; // int setter ref |
| (1.2).foo; // double getter ref |
| (1.2).foo = 0; // double setter ref |
| } |
| '''); |
| |
| var intGetter = findNode.methodDeclaration('0; // int getter'); |
| var intSetter = findNode.methodDeclaration('{} // int setter'); |
| assertElementIndexText(intGetter.declaredFragment!.element, r''' |
| 214 12:5 |foo| IS_REFERENCED_BY qualified |
| '''); |
| assertElementIndexText(intSetter.declaredFragment!.element, r''' |
| 241 13:5 |foo| IS_REFERENCED_BY qualified |
| '''); |
| |
| var doubleGetter = findNode.methodDeclaration('0; // double getter'); |
| var doubleSetter = findNode.methodDeclaration('{} // double setter'); |
| assertElementIndexText(doubleGetter.declaredFragment!.element, r''' |
| 276 14:9 |foo| IS_REFERENCED_BY qualified |
| '''); |
| assertElementIndexText(doubleSetter.declaredFragment!.element, r''' |
| 310 15:9 |foo| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_setter_withPrefix() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A { |
| static int f = 0; |
| } |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' as p; |
| |
| void f(int i) => p.A.f = i; |
| |
| class B extends p.A {} |
| '''); |
| var element = findElement2.class_('B').supertype!.element3; |
| assertElementIndexText(element, r''' |
| 44 3:20 |A| IS_REFERENCED_BY qualified |
| 60 5:7 |B| IS_ANCESTOR_OF |
| 72 5:19 |A| IS_EXTENDED_BY qualified |
| 72 5:19 |A| IS_REFERENCED_BY qualified |
| Prefixes: p |
| '''); |
| } |
| |
| test_isReferencedBy_simpleIdentifier_withAndWithoutPrefix() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart'; |
| import 'lib.dart' as p; |
| |
| var t = A; |
| |
| class B extends p.A {} |
| '''); |
| var element = findElement2.class_('B').supertype!.element3; |
| assertElementIndexText(element, r''' |
| 52 4:9 |A| IS_REFERENCED_BY |
| 62 6:7 |B| IS_ANCESTOR_OF |
| 74 6:19 |A| IS_EXTENDED_BY qualified |
| 74 6:19 |A| IS_REFERENCED_BY qualified |
| Prefixes: (unprefixed),p |
| '''); |
| } |
| |
| test_isReferencedBy_simpleIdentifier_withPrefix() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' as p; |
| |
| var t = p.A; |
| |
| class B extends p.A {} |
| '''); |
| var element = findElement2.class_('B').supertype!.element3; |
| assertElementIndexText(element, r''' |
| 35 3:11 |A| IS_REFERENCED_BY qualified |
| 45 5:7 |B| IS_ANCESTOR_OF |
| 57 5:19 |A| IS_EXTENDED_BY qualified |
| 57 5:19 |A| IS_REFERENCED_BY qualified |
| Prefixes: p |
| '''); |
| } |
| |
| test_isReferencedBy_synthetic_leastUpperBound() async { |
| await _indexTestUnit(''' |
| int f1({int p}) => 1; |
| int f2({int p}) => 2; |
| void g(bool b) { |
| var f = b ? f1 : f2; |
| f(p: 0); |
| }'''); |
| // We should not crash because of reference to "p" - a named parameter |
| // of a synthetic LUB FunctionElement created for "f". |
| } |
| |
| test_isReferencedBy_TopLevelVariableElement() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| library lib; |
| var V; |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' show V; // imp |
| import 'lib.dart' as pref; |
| void f() { |
| pref.V = 5; // q |
| print(pref.V); // q |
| V = 5; // nq |
| print(V); // nq |
| }'''); |
| var variable = importFindLib().topVar('V'); |
| |
| assertElementIndexText(variable, r''' |
| 23 1:24 |V| IS_REFERENCED_BY qualified |
| '''); |
| |
| assertElementIndexText(variable.getter2!, r''' |
| 103 5:14 |V| IS_REFERENCED_BY qualified |
| 135 7:9 |V| IS_REFERENCED_BY |
| Prefixes: pref,(unprefixed) |
| '''); |
| |
| assertElementIndexText(variable.setter2!, r''' |
| 78 4:8 |V| IS_REFERENCED_BY qualified |
| 114 6:3 |V| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_TopLevelVariableElement_synthetic_hasGetterSetter() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| int get V => 0; |
| void set V(_) {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' show V; |
| '''); |
| var element = importFindLib().topVar('V'); |
| assertElementIndexText(element, r''' |
| 23 1:24 |V| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_TopLevelVariableElement_synthetic_hasSetter() async { |
| newFile('$testPackageLibPath/lib.dart', ''' |
| void set V(_) {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart' show V; |
| '''); |
| var element = importFindLib().topVar('V'); |
| assertElementIndexText(element, r''' |
| 23 1:24 |V| IS_REFERENCED_BY qualified |
| '''); |
| } |
| |
| test_isReferencedBy_TypeAliasElement() async { |
| await _indexTestUnit(''' |
| class A<T> { |
| static int field = 0; |
| static void method() {} |
| } |
| |
| typedef B = A<int>; |
| |
| void f(B p) { |
| B v; |
| B(); // 2 |
| B.field = 1; |
| B.field; // 3 |
| B.method(); // 4 |
| } |
| '''); |
| var element = findElement2.typeAlias('B'); |
| assertElementIndexText(element, r''' |
| 94 8:8 |B| IS_REFERENCED_BY |
| 103 9:3 |B| IS_REFERENCED_BY |
| 110 10:3 |B| IS_REFERENCED_BY |
| 122 11:3 |B| IS_REFERENCED_BY |
| 137 12:3 |B| IS_REFERENCED_BY |
| 153 13:3 |B| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isReferencedBy_typeInVariableList() async { |
| await _indexTestUnit(''' |
| class A {} |
| A myVariable = null; |
| '''); |
| var element = findElement2.class_('A'); |
| assertElementIndexText(element, r''' |
| 11 2:1 |A| IS_REFERENCED_BY |
| '''); |
| } |
| |
| test_isWrittenBy_FieldElement() async { |
| await _indexTestUnit(''' |
| class A { |
| int field; |
| A.foo({this.field}); |
| A.bar() : field = 5; |
| } |
| '''); |
| var element = findElement2.field('field'); |
| assertElementIndexText(element, r''' |
| 37 3:15 |field| IS_WRITTEN_BY qualified |
| 58 4:13 |field| IS_WRITTEN_BY qualified |
| '''); |
| } |
| |
| test_subtypes_classDeclaration() async { |
| String libP = 'package:test/lib.dart;package:test/lib.dart'; |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A {} |
| class B {} |
| class C {} |
| class D {} |
| class E {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart'; |
| |
| class X extends A { |
| X(); |
| X.namedConstructor(); |
| |
| int field1, field2; |
| int get getter1 => null; |
| void set setter1(_) {} |
| void method1() {} |
| |
| static int staticField; |
| static void staticMethod() {} |
| } |
| |
| class Y extends Object with B, C { |
| void methodY() {} |
| } |
| |
| class Z implements E, D { |
| void methodZ() {} |
| } |
| '''); |
| |
| expect(index.supertypes, hasLength(6)); |
| expect(index.subtypes, hasLength(6)); |
| |
| _assertSubtype(0, 'dart:core;dart:core;Object', 'Y', ['methodY']); |
| _assertSubtype(1, '$libP;A', 'X', [ |
| 'field1', |
| 'field2', |
| 'getter1', |
| 'method1', |
| 'setter1', |
| ]); |
| _assertSubtype(2, '$libP;B', 'Y', ['methodY']); |
| _assertSubtype(3, '$libP;C', 'Y', ['methodY']); |
| _assertSubtype(4, '$libP;D', 'Z', ['methodZ']); |
| _assertSubtype(5, '$libP;E', 'Z', ['methodZ']); |
| } |
| |
| test_subtypes_classTypeAlias() async { |
| String libP = 'package:test/lib.dart;package:test/lib.dart'; |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A {} |
| class B {} |
| class C {} |
| class D {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart'; |
| |
| class X = A with B, C; |
| class Y = A with B implements C, D; |
| '''); |
| |
| expect(index.supertypes, hasLength(7)); |
| expect(index.subtypes, hasLength(7)); |
| |
| _assertSubtype(0, '$libP;A', 'X', []); |
| _assertSubtype(1, '$libP;A', 'Y', []); |
| _assertSubtype(2, '$libP;B', 'X', []); |
| _assertSubtype(3, '$libP;B', 'Y', []); |
| _assertSubtype(4, '$libP;C', 'X', []); |
| _assertSubtype(5, '$libP;C', 'Y', []); |
| _assertSubtype(6, '$libP;D', 'Y', []); |
| } |
| |
| test_subtypes_dynamic() async { |
| await _indexTestUnit(''' |
| class X extends dynamic { |
| void foo() {} |
| } |
| '''); |
| |
| expect(index.supertypes, isEmpty); |
| expect(index.subtypes, isEmpty); |
| } |
| |
| test_subtypes_enum_implements() async { |
| String libP = 'package:test/test.dart;package:test/test.dart'; |
| await _indexTestUnit(''' |
| class A {} |
| |
| enum E implements A { |
| v; |
| void foo() {} |
| } |
| '''); |
| |
| expect(index.subtypes, hasLength(1)); |
| _assertSubtype(0, '$libP;A', 'E', ['foo']); |
| } |
| |
| test_subtypes_enum_with() async { |
| String libP = 'package:test/test.dart;package:test/test.dart'; |
| await _indexTestUnit(''' |
| mixin M {} |
| |
| enum E with M { |
| v; |
| void foo() {} |
| } |
| '''); |
| |
| expect(index.subtypes, hasLength(1)); |
| _assertSubtype(0, '$libP;M', 'E', ['foo']); |
| } |
| |
| test_subtypes_extensionType_class() async { |
| String libP = 'package:test/lib.dart;package:test/lib.dart'; |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A { |
| void method1() {} |
| void method2() {} |
| } |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart'; |
| |
| extension type X(A it) implements A { |
| void method1() {} |
| void method3() {} |
| } |
| '''); |
| |
| expect(index.supertypes, hasLength(1)); |
| expect(index.subtypes, hasLength(1)); |
| |
| _assertSubtype(0, '$libP;A', 'X', ['method1', 'method3']); |
| } |
| |
| test_subtypes_extensionType_extensionType() async { |
| String libP = 'package:test/lib.dart;package:test/lib.dart'; |
| newFile('$testPackageLibPath/lib.dart', ''' |
| extension type A(int it) { |
| void method1() {} |
| void method2() {} |
| } |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart'; |
| |
| extension type X(int it) implements A { |
| void method1() {} |
| void method3() {} |
| } |
| '''); |
| |
| expect(index.supertypes, hasLength(1)); |
| expect(index.subtypes, hasLength(1)); |
| |
| _assertSubtype(0, '$libP;A', 'X', ['method1', 'method3']); |
| } |
| |
| test_subtypes_mixinDeclaration() async { |
| String libP = 'package:test/lib.dart;package:test/lib.dart'; |
| newFile('$testPackageLibPath/lib.dart', ''' |
| class A {} |
| class B {} |
| class C {} |
| class D {} |
| class E {} |
| '''); |
| await _indexTestUnit(''' |
| import 'lib.dart'; |
| |
| mixin X on A implements B, C {} |
| mixin Y on A, B implements C; |
| '''); |
| |
| expect(index.supertypes, hasLength(6)); |
| expect(index.subtypes, hasLength(6)); |
| |
| _assertSubtype(0, '$libP;A', 'X', []); |
| _assertSubtype(1, '$libP;A', 'Y', []); |
| _assertSubtype(2, '$libP;B', 'X', []); |
| _assertSubtype(3, '$libP;B', 'Y', []); |
| _assertSubtype(4, '$libP;C', 'X', []); |
| _assertSubtype(5, '$libP;C', 'Y', []); |
| } |
| |
| test_usedName_inLibraryIdentifier() async { |
| await _indexTestUnit(''' |
| library aaa.bbb.ccc; |
| class C { |
| var bbb; |
| } |
| void f(p) { |
| p.bbb = 1; |
| } |
| '''); |
| assertThatName('bbb') |
| ..isNotUsed('bbb.ccc', IndexRelationKind.IS_READ_BY) |
| ..isUsedQ('bbb = 1;', IndexRelationKind.IS_WRITTEN_BY); |
| } |
| |
| test_usedName_qualified_resolved() async { |
| await _indexTestUnit(''' |
| class C { |
| var x; |
| } |
| void f(C c) { |
| c.x; // 1 |
| c.x = 1; |
| c.x += 2; |
| c.x(); |
| } |
| '''); |
| assertThatName('x') |
| ..isNotUsedQ('x; // 1', IndexRelationKind.IS_READ_BY) |
| ..isNotUsedQ('x = 1;', IndexRelationKind.IS_WRITTEN_BY) |
| ..isNotUsedQ('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY) |
| ..isNotUsedQ('x();', IndexRelationKind.IS_INVOKED_BY); |
| } |
| |
| test_usedName_qualified_unresolved() async { |
| await _indexTestUnit(''' |
| void f(p) { |
| p.x; |
| p.x = 1; |
| p.x += 2; |
| p.x(); |
| } |
| '''); |
| assertThatName('x') |
| ..isUsedQ('x;', IndexRelationKind.IS_READ_BY) |
| ..isUsedQ('x = 1;', IndexRelationKind.IS_WRITTEN_BY) |
| ..isUsedQ('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY) |
| ..isUsedQ('x();', IndexRelationKind.IS_INVOKED_BY); |
| } |
| |
| test_usedName_unqualified_resolved() async { |
| await _indexTestUnit(''' |
| class C { |
| var x; |
| m() { |
| x; // 1 |
| x = 1; |
| x += 2; |
| x(); |
| } |
| } |
| '''); |
| assertThatName('x') |
| ..isNotUsedQ('x; // 1', IndexRelationKind.IS_READ_BY) |
| ..isNotUsedQ('x = 1;', IndexRelationKind.IS_WRITTEN_BY) |
| ..isNotUsedQ('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY) |
| ..isNotUsedQ('x();', IndexRelationKind.IS_INVOKED_BY); |
| } |
| |
| test_usedName_unqualified_unresolved() async { |
| await _indexTestUnit(''' |
| void f() { |
| x; |
| x = 1; |
| x += 2; |
| x(); |
| } |
| '''); |
| assertThatName('x') |
| ..isUsed('x;', IndexRelationKind.IS_READ_BY) |
| ..isUsed('x = 1;', IndexRelationKind.IS_WRITTEN_BY) |
| ..isUsed('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY) |
| ..isUsed('x();', IndexRelationKind.IS_INVOKED_BY); |
| } |
| |
| String _getLibraryFragmentReferenceText(LibraryFragmentImpl target) { |
| var lineInfo = result.lineInfo; |
| var targetId = index.getLibraryFragmentId(target); |
| |
| expect( |
| index.libFragmentRefTargets.length, |
| index.libFragmentRefUriOffsets.length, |
| ); |
| |
| expect( |
| index.libFragmentRefTargets.length, |
| index.libFragmentRefUriLengths.length, |
| ); |
| |
| var buffer = StringBuffer(); |
| for (var i = 0; i < index.libFragmentRefTargets.length; i++) { |
| if (index.libFragmentRefTargets[i] == targetId) { |
| var offset = index.libFragmentRefUriOffsets[i]; |
| var length = index.libFragmentRefUriLengths[i]; |
| var location = lineInfo.getLocation(offset); |
| var snippet = result.content.substring(offset, offset + length); |
| buffer.write(offset); |
| buffer.write(' '); |
| buffer.write(location.lineNumber); |
| buffer.write(':'); |
| buffer.write(location.columnNumber); |
| buffer.write(' '); |
| buffer.write('|$snippet|'); |
| buffer.writeln(); |
| } |
| } |
| return buffer.toString(); |
| } |
| |
| String _getRelationsText(Element element) { |
| var lineInfo = result.lineInfo; |
| var elementId = _findElementId(element); |
| |
| var relations = <_Relation>[]; |
| for (var i = 0; i < index.usedElementOffsets.length; i++) { |
| if (index.usedElements[i] == elementId) { |
| relations.add( |
| _Relation( |
| kind: index.usedElementKinds[i], |
| offset: index.usedElementOffsets[i], |
| length: index.usedElementLengths[i], |
| isQualified: index.usedElementIsQualifiedFlags[i], |
| ), |
| ); |
| } |
| } |
| |
| var sortedRelations = relations.sorted((a, b) { |
| var byOffset = a.offset - b.offset; |
| if (byOffset != 0) { |
| return byOffset; |
| } |
| return a.kind.name.compareTo(b.kind.name); |
| }); |
| |
| // Verify that there are no duplicate relations. |
| var lastOffset = -1; |
| var lastLength = -1; |
| IndexRelationKind? lastKind; |
| for (var relation in sortedRelations) { |
| if (relation.offset == lastOffset && |
| relation.length == lastLength && |
| relation.kind == lastKind) { |
| fail('Duplicate relation: $relation'); |
| } |
| lastOffset = relation.offset; |
| lastLength = relation.length; |
| lastKind = relation.kind; |
| } |
| |
| var buffer = StringBuffer(); |
| for (var relation in sortedRelations) { |
| var offset = relation.offset; |
| var length = relation.length; |
| var location = lineInfo.getLocation(offset); |
| var snippet = result.content.substring(offset, offset + length); |
| buffer.write(offset); |
| buffer.write(' '); |
| buffer.write(location.lineNumber); |
| buffer.write(':'); |
| buffer.write(location.columnNumber); |
| buffer.write(' '); |
| buffer.write('|$snippet|'); |
| buffer.write(' '); |
| buffer.write(relation.kind.name); |
| if (relation.isQualified) { |
| buffer.write(' qualified'); |
| } |
| buffer.writeln(); |
| } |
| |
| var prefixString = index.elementImportPrefixes[elementId]; |
| // If the only access is unprefixed, omit the line |
| if (prefixString.isNotEmpty) { |
| // Otherwise, use some marker text for unprefixed so it's clearer in the |
| // output than an empty string. |
| var prefixes = prefixString |
| .split(',') |
| .map((prefix) => prefix.isEmpty ? '(unprefixed)' : prefix) |
| .join(','); |
| |
| buffer.writeln('Prefixes: $prefixes'); |
| } |
| |
| return buffer.toString(); |
| } |
| } |
| |
| mixin _IndexMixin on PubPackageResolutionTest { |
| late AnalysisDriverUnitIndex index; |
| |
| _NameIndexAssert assertThatName(String name) { |
| return _NameIndexAssert(this, name); |
| } |
| |
| /// Return [ImportFindElement] for 'package:test/lib.dart' import. |
| ImportFindElement importFindLib() { |
| return findElement2.importFind( |
| 'package:test/lib.dart', |
| mustBeUnique: false, |
| ); |
| } |
| |
| void _assertSubtype( |
| int i, |
| String superEncoded, |
| String subName, |
| List<String> members, |
| ) { |
| expect(index.strings[index.supertypes[i]], superEncoded); |
| var subtype = index.subtypes[i]; |
| expect(index.strings[subtype.name], subName); |
| expect(_decodeStringList(subtype.members), members); |
| } |
| |
| void _assertUsedName( |
| String name, |
| IndexRelationKind kind, |
| ExpectedLocation expectedLocation, |
| bool isNot, |
| ) { |
| int nameId = index.getStringId(name); |
| for (int i = 0; i < index.usedNames.length; i++) { |
| if (index.usedNames[i] == nameId && |
| index.usedNameKinds[i] == kind && |
| index.usedNameOffsets[i] == expectedLocation.offset && |
| index.usedNameIsQualifiedFlags[i] == expectedLocation.isQualified) { |
| if (isNot) { |
| _failWithIndexDump('Unexpected $name $kind at $expectedLocation'); |
| } |
| return; |
| } |
| } |
| if (isNot) { |
| return; |
| } |
| _failWithIndexDump('Not found $name $kind at $expectedLocation'); |
| } |
| |
| List<String> _decodeStringList(List<int> stringIds) { |
| return stringIds.map((i) => index.strings[i]).toList(); |
| } |
| |
| ExpectedLocation _expectedLocation( |
| String search, |
| bool isQualified, { |
| int? length, |
| }) { |
| int offset = findNode.offset(search); |
| length ??= findNode.simple(search).length; |
| return ExpectedLocation(offset, length, isQualified); |
| } |
| |
| void _failWithIndexDump(String msg) { |
| var buffer = StringBuffer(); |
| for (int i = 0; i < index.usedElementOffsets.length; i++) { |
| buffer.write(' id = '); |
| buffer.write(index.usedElements[i]); |
| buffer.write(' kind = '); |
| buffer.write(index.usedElementKinds[i]); |
| buffer.write(' offset = '); |
| buffer.write(index.usedElementOffsets[i]); |
| buffer.write(' length = '); |
| buffer.write(index.usedElementLengths[i]); |
| buffer.write(' isQualified = '); |
| buffer.writeln(index.usedElementIsQualifiedFlags[i]); |
| } |
| fail('$msg in\n${buffer.toString()}'); |
| } |
| |
| /// Return the [element] identifier in [index] or fail. |
| int _findElementId(Element element) { |
| var unitId = _getUnitId(element); |
| |
| // Prepare the element that was put into the index. |
| IndexElementInfo info = IndexElementInfo(element); |
| element = info.element; |
| |
| // Prepare element's name components. |
| var components = ElementNameComponents(element); |
| var unitMemberId = index.getStringId(components.unitMemberName); |
| var classMemberId = index.getStringId(components.classMemberName); |
| var parameterId = index.getStringId(components.parameterName); |
| |
| // Find the element's id. |
| for ( |
| int elementId = 0; |
| elementId < index.elementUnits.length; |
| elementId++ |
| ) { |
| if (index.elementUnits[elementId] == unitId && |
| index.elementNameUnitMemberIds[elementId] == unitMemberId && |
| index.elementNameClassMemberIds[elementId] == classMemberId && |
| index.elementNameParameterIds[elementId] == parameterId && |
| index.elementKinds[elementId] == info.kind) { |
| return elementId; |
| } |
| } |
| _failWithIndexDump('Element $element is not referenced'); |
| return 0; |
| } |
| |
| int _getUnitId(Element element) { |
| var unitElement = getUnitElement(element); |
| return index.getLibraryFragmentId(unitElement); |
| } |
| |
| Future<void> _indexTestUnit(String code) async { |
| await resolveTestCode(code); |
| |
| var indexBuilder = indexUnit(result.unit); |
| var indexBytes = indexBuilder.toBuffer(); |
| index = AnalysisDriverUnitIndex.fromBuffer(indexBytes); |
| } |
| } |
| |
| class _NameIndexAssert { |
| final _IndexMixin test; |
| final String name; |
| |
| _NameIndexAssert(this.test, this.name); |
| |
| void isNotUsed(String search, IndexRelationKind kind) { |
| test._assertUsedName( |
| name, |
| kind, |
| test._expectedLocation(search, false), |
| true, |
| ); |
| } |
| |
| void isNotUsedQ(String search, IndexRelationKind kind) { |
| test._assertUsedName( |
| name, |
| kind, |
| test._expectedLocation(search, true), |
| true, |
| ); |
| } |
| |
| void isUsed(String search, IndexRelationKind kind) { |
| test._assertUsedName( |
| name, |
| kind, |
| test._expectedLocation(search, false), |
| false, |
| ); |
| } |
| |
| void isUsedQ(String search, IndexRelationKind kind) { |
| test._assertUsedName( |
| name, |
| kind, |
| test._expectedLocation(search, true), |
| false, |
| ); |
| } |
| } |
| |
| class _Relation { |
| final IndexRelationKind kind; |
| final int offset; |
| final int length; |
| final bool isQualified; |
| |
| _Relation({ |
| required this.kind, |
| required this.offset, |
| required this.length, |
| required this.isQualified, |
| }); |
| |
| @override |
| String toString() { |
| return '_Relation{kind: $kind, offset: $offset, length: $length, ' |
| 'isQualified: $isQualified})'; |
| } |
| } |