Chromium Code Reviews| Index: pkg/analysis_services/test/index/dart_index_contributor_test.dart |
| diff --git a/pkg/analysis_services/test/index/dart_index_contributor_test.dart b/pkg/analysis_services/test/index/dart_index_contributor_test.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..9dacb5a8ad0b14f3762a5ce54b873d357ada956a |
| --- /dev/null |
| +++ b/pkg/analysis_services/test/index/dart_index_contributor_test.dart |
| @@ -0,0 +1,1654 @@ |
| +// 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.services.src.index.dart_index_contributor; |
| + |
| +import 'package:analysis_services/index/index.dart'; |
| +import 'package:analysis_services/index/index_store.dart'; |
| +import 'package:analysis_services/src/index/index_contributor.dart'; |
| +import 'package:analysis_testing/abstract_context.dart'; |
| +import 'package:analysis_testing/reflective_tests.dart'; |
| +import 'package:analyzer/src/generated/ast.dart'; |
| +import 'package:analyzer/src/generated/element.dart'; |
| +import 'package:analyzer/src/generated/error.dart'; |
| +import 'package:analyzer/src/generated/java_engine.dart'; |
| +import 'package:analyzer/src/generated/source.dart'; |
| +import 'package:typed_mock/typed_mock.dart'; |
| +import 'package:unittest/unittest.dart'; |
| + |
| + |
| +main() { |
| + groupSep = ' | '; |
| + group('DartUnitContributor', () { |
| + runReflectiveTests(DartUnitContributorTest); |
| + }); |
| +} |
| + |
| + |
| +/** |
| + * Returns `true` if [actual] location the same properties as [expected]. |
|
Brian Wilkerson
2014/07/08 20:07:58
"if [actual] location the" --> "if the [actual] lo
scheglov
2014/07/08 20:54:52
Done.
|
| + */ |
| +bool _equalsLocation(Location actual, ExpectedLocation expected) { |
| + return _equalsLocationProperties(actual, expected.element, expected.offset, |
| + expected.length); |
| +} |
| + |
| + |
| +/** |
| + * Returns `true` if [actual] location the expected properties. |
|
Brian Wilkerson
2014/07/08 20:07:58
"if [actual] location the" --> "if the [actual] lo
scheglov
2014/07/08 20:54:52
Done.
|
| + */ |
| +bool _equalsLocationProperties(Location actual, Element expectedElement, |
| + int expectedOffset, int expectedLength) { |
| + return expectedElement == actual.element && expectedOffset == actual.offset && |
| + expectedLength == actual.length; |
| +} |
| + |
| + |
| +bool _equalsRecordedRelation(RecordedRelation recordedRelation, |
| + Element expectedElement, Relationship expectedRelationship, |
| + ExpectedLocation expectedLocation) { |
| + return expectedElement == recordedRelation.element && expectedRelationship == |
| + recordedRelation.relationship && (expectedLocation == null || _equalsLocation( |
| + recordedRelation.location, expectedLocation)); |
| +} |
| + |
| + |
| +int _getLeadingIdentifierLength(String search) { |
| + int length = 0; |
| + while (length < search.length) { |
| + int c = search.codeUnitAt(length); |
| + if (c >= 'a'.codeUnitAt(0) && c <= 'z'.codeUnitAt(0)) { |
| + length++; |
| + continue; |
| + } |
| + if (c >= 'A'.codeUnitAt(0) && c <= 'Z'.codeUnitAt(0)) { |
| + length++; |
| + continue; |
| + } |
| + if (c >= '0'.codeUnitAt(0) && c <= '9'.codeUnitAt(0)) { |
| + length++; |
| + continue; |
| + } |
| + break; |
| + } |
| + return length; |
| +} |
| + |
| +@ReflectiveTestCase() |
| +class DartUnitContributorTest extends AbstractContextTest { |
| + IndexStore store = new MockIndexStore(); |
| + List<RecordedRelation> recordedRelations = <RecordedRelation>[]; |
| + |
| + bool verifyNoTestUnitErrors = true; |
| + |
| + String testCode; |
| + Source testSource; |
| + CompilationUnit testUnit; |
| + CompilationUnitElement testUnitElement; |
| + LibraryElement testLibraryElement; |
| + |
| + void setUp() { |
| + super.setUp(); |
| + when(store.aboutToIndexDart(context, anyObject)).thenReturn(true); |
| + when(store.recordRelationship(anyObject, anyObject, anyObject)).thenInvoke( |
| + (Element element, Relationship relationship, Location location) { |
| + recordedRelations.add(new RecordedRelation(element, relationship, |
| + location)); |
| + }); |
| + } |
| + |
| + void test_FieldElement_noAssignedType_notLHS() { |
| + _indexTestUnit(''' |
| +class A { |
| + var myField; |
| + main() { |
| + print(myField); |
| + } |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + FieldElement fieldElement = _findElement("myField"); |
| + PropertyAccessorElement getterElement = fieldElement.getter; |
| + // verify |
| + _assertRecordedRelation(getterElement, |
| + IndexConstants.IS_REFERENCED_BY_UNQUALIFIED, _expectedLocation(mainElement, |
| + 'myField);')); |
| + } |
| + |
| + void test_definesClass() { |
| + _indexTestUnit('class A {}'); |
| + // prepare elements |
| + ClassElement classElement = _findElement("A"); |
| + // verify |
| + _assertDefinesTopLevelElement(IndexConstants.DEFINES_CLASS, |
| + _expectedLocation(classElement, 'A {}')); |
| + } |
| + |
| + void test_definesClassAlias() { |
| + _indexTestUnit(''' |
| +class Mix {} |
| +class MyClass = Object with Mix;'''); |
| + // prepare elements |
| + Element classElement = _findElement("MyClass"); |
| + // verify |
| + _assertDefinesTopLevelElement(IndexConstants.DEFINES_CLASS_ALIAS, |
| + _expectedLocation(classElement, 'MyClass =')); |
| + } |
| + |
| + void test_definesFunction() { |
| + _indexTestUnit('myFunction() {}'); |
| + // prepare elements |
| + FunctionElement functionElement = _findElement("myFunction"); |
| + // verify |
| + _assertDefinesTopLevelElement(IndexConstants.DEFINES_FUNCTION, |
| + _expectedLocation(functionElement, 'myFunction() {}')); |
| + } |
| + |
| + void test_definesFunctionType() { |
| + _indexTestUnit('typedef MyFunction(int p);'); |
| + // prepare elements |
| + FunctionTypeAliasElement typeAliasElement = _findElement("MyFunction"); |
| + // verify |
| + _assertDefinesTopLevelElement(IndexConstants.DEFINES_FUNCTION_TYPE, |
| + _expectedLocation(typeAliasElement, 'MyFunction(int p);')); |
| + } |
| + |
| + |
| + void test_definesVariable() { |
| + _indexTestUnit('var myVar = 42;'); |
| + // prepare elements |
| + VariableElement varElement = _findElement("myVar"); |
| + // verify |
| + _assertDefinesTopLevelElement(IndexConstants.DEFINES_VARIABLE, |
| + _expectedLocation(varElement, 'myVar = 42;')); |
| + } |
| + |
| + void test_forIn() { |
| + _indexTestUnit(''' |
| +main() { |
| + for (var v in []) { |
| + } |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + VariableElement variableElement = _findElement("v"); |
| + // verify |
| + _assertNoRecordedRelation(variableElement, IndexConstants.IS_READ_BY, |
| + _expectedLocation(mainElement, 'v in []')); |
| + } |
| + |
| + void test_isDefinedBy_ConstructorElement() { |
| + _indexTestUnit(''' |
| +class A { |
| + A() {} |
| + A.foo() {} |
| +}'''); |
| + // prepare elements |
| + ClassElement classA = _findElement("A"); |
| + ConstructorElement consA = _findNodeElementAtString("A()", (node) => node is |
| + ConstructorDeclaration); |
| + ConstructorElement consA_foo = _findNodeElementAtString("A.foo()", (node) => |
| + node is ConstructorDeclaration); |
| + // verify |
| + _assertRecordedRelation(consA, IndexConstants.IS_DEFINED_BY, |
| + _expectedLocation(classA, '() {}')); |
| + _assertRecordedRelation(consA_foo, IndexConstants.IS_DEFINED_BY, |
| + _expectedLocation(classA, '.foo() {}', '.foo'.length)); |
| + } |
| + |
| +// void test_createElementLocation() { |
| +// ElementLocation elementLocation = mock(ElementLocation); |
| +// Element element = IndexContributorHelper.mockElement(Element, |
| +// elementLocation, 42, "myName"); |
| +// Location location = IndexContributor.createLocation(element); |
| +// IndexContributorHelper.assertLocation(location, element, 42, "myName"); |
| +// } |
| +// |
| +// void test_createElementLocation_null() { |
| +// JUnitTestCase.assertSame(null, IndexContributor.createLocation(null)); |
| +// } |
| + |
| + void test_isDefinedBy_NameElement_method() { |
| + _indexTestUnit(''' |
| +class A { |
| + m() {} |
| +}'''); |
| + // prepare elements |
| + Element methodElement = _findElement("m"); |
| + Element nameElement = new NameElement("m"); |
| + // verify |
| + _assertRecordedRelation(nameElement, IndexConstants.IS_DEFINED_BY, |
| + _expectedLocation(methodElement, 'm() {}')); |
| + } |
| + |
| + |
| + void test_isDefinedBy_NameElement_operator() { |
| + _indexTestUnit(''' |
| +class A { |
| + operator +(o) {} |
| +}'''); |
| + // prepare elements |
| + Element methodElement = _findElement("+"); |
| + Element nameElement = new NameElement("+"); |
| + // verify |
| + _assertRecordedRelation(nameElement, IndexConstants.IS_DEFINED_BY, |
| + _expectedLocation(methodElement, '+(o) {}', 1)); |
| + } |
| + |
| + void test_isExtendedBy_ClassDeclaration() { |
| + _indexTestUnit(''' |
| +class A {} // 1 |
| +class B extends A {} // 2 |
| +'''); |
| + // prepare elements |
| + ClassElement classElementA = _findElement("A"); |
| + ClassElement classElementB = _findElement("B"); |
| + // verify |
| + _assertRecordedRelation(classElementA, IndexConstants.IS_EXTENDED_BY, |
| + _expectedLocation(classElementB, 'A {} // 2')); |
| + } |
| + |
| + void test_isExtendedBy_ClassDeclaration_Object() { |
| + _indexTestUnit(''' |
| +class A {} // 1 |
| +'''); |
| + // prepare elements |
| + ClassElement classElementA = _findElement("A"); |
| + ClassElement classElementObject = classElementA.supertype.element; |
| + // verify |
| + _assertRecordedRelation(classElementObject, IndexConstants.IS_EXTENDED_BY, |
| + _expectedLocation(classElementA, 'A {}', 0)); |
| + } |
| + |
| + void test_isExtendedBy_ClassTypeAlias() { |
| + _indexTestUnit(''' |
| +class A {} // 1 |
| +class B {} // 2 |
| +class C = A with B; // 3 |
| +'''); |
| + // prepare elements |
| + ClassElement classElementA = _findElement("A"); |
| + ClassElement classElementC = _findElement("C"); |
| + // verify |
| + _assertRecordedRelation(classElementA, IndexConstants.IS_EXTENDED_BY, |
| + _expectedLocation(classElementC, 'A with')); |
| + } |
| + |
| + void test_isImplementedBy_ClassDeclaration() { |
| + _indexTestUnit(''' |
| +class A {} // 1 |
| +class B implements A {} // 2 |
| +'''); |
| + // prepare elements |
| + ClassElement classElementA = _findElement("A"); |
| + ClassElement classElementB = _findElement("B"); |
| + // verify |
| + _assertRecordedRelation(classElementA, IndexConstants.IS_IMPLEMENTED_BY, |
| + _expectedLocation(classElementB, 'A {} // 2')); |
| + } |
| + |
| + void test_isImplementedBy_ClassTypeAlias() { |
| + _indexTestUnit(''' |
| +class A {} // 1 |
| +class B {} // 2 |
| +class C = Object with A implements B; // 3 |
| +'''); |
| + // prepare elements |
| + ClassElement classElementB = _findElement("B"); |
| + ClassElement classElementC = _findElement("C"); |
| + // verify |
| + _assertRecordedRelation(classElementB, IndexConstants.IS_IMPLEMENTED_BY, |
| + _expectedLocation(classElementC, 'B; // 3')); |
| + } |
| + |
| + |
| + void test_isInvokedByQualified_FieldElement() { |
| + _indexTestUnit(''' |
| +class A { |
| + var field; |
| + main() { |
| + this.field(); |
| + } |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + FieldElement fieldElement = _findElement("field"); |
| + PropertyAccessorElement getterElement = fieldElement.getter; |
| + // verify |
| + _assertRecordedRelation(getterElement, |
| + IndexConstants.IS_INVOKED_BY_QUALIFIED, _expectedLocation(mainElement, |
| + 'field();')); |
| + } |
| + |
| + |
| + void test_isInvokedByQualified_MethodElement() { |
| + _indexTestUnit(''' |
| +class A { |
| + foo() {} |
| + main() { |
| + this.foo(); |
| + } |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + Element methodElement = _findElement("foo"); |
| + // verify |
| + var location = _expectedLocation(mainElement, 'foo();'); |
| + _assertRecordedRelation(methodElement, |
| + IndexConstants.IS_INVOKED_BY_QUALIFIED, location); |
| + _assertNoRecordedRelation(methodElement, |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED, location); |
| + } |
| + |
| + void test_isInvokedByQualified_MethodElement_propagatedType() { |
| + _indexTestUnit(''' |
| +class A { |
| + foo() {} |
| +} |
| +main() { |
| + var a = new A(); |
| + a.foo(); |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + Element methodElement = _findElement("foo"); |
| + // verify |
| + _assertRecordedRelation(methodElement, |
| + IndexConstants.IS_INVOKED_BY_QUALIFIED, _expectedLocation(mainElement, |
| + 'foo();')); |
| + } |
| + |
| + void test_isInvokedByUnqualified_MethodElement() { |
| + _indexTestUnit(''' |
| +class A { |
| + foo() {} |
| + main() { |
| + foo(); |
| + } |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + Element methodElement = _findElement("foo"); |
| + // verify |
| + _assertRecordedRelation(methodElement, |
| + IndexConstants.IS_INVOKED_BY_UNQUALIFIED, _expectedLocation(mainElement, |
| + 'foo();')); |
| + } |
| + |
| + void test_isInvokedBy_FunctionElement() { |
| + _indexTestUnit(''' |
| +foo() {} |
| +main() { |
| + foo(); |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + FunctionElement functionElement = _findElement("foo"); |
| + // verify |
| + _assertRecordedRelation(functionElement, IndexConstants.IS_INVOKED_BY, |
| + _expectedLocation(mainElement, 'foo();')); |
| + } |
| + |
| + void test_isInvokedBy_LocalVariableElement() { |
| + _indexTestUnit(''' |
| +main() { |
| + var v; |
| + v(); |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + Element element = _findElement("v"); |
| + // verify |
| + _assertRecordedRelation(element, IndexConstants.IS_INVOKED_BY, |
| + _expectedLocation(mainElement, 'v();')); |
| + } |
| + |
| + void test_isInvokedBy_ParameterElement() { |
| + _indexTestUnit(''' |
| +main(p()) { |
| + p(); |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + Element element = _findElement("p"); |
| + // verify |
| + _assertRecordedRelation(element, IndexConstants.IS_INVOKED_BY, |
| + _expectedLocation(mainElement, 'p();')); |
| + } |
| + |
| + void test_isMixedInBy_ClassDeclaration() { |
| + _indexTestUnit(''' |
| +class A {} // 1 |
| +class B extends Object with A {} // 2 |
| +'''); |
| + // prepare elements |
| + ClassElement classElementA = _findElement("A"); |
| + ClassElement classElementB = _findElement("B"); |
| + // verify |
| + _assertRecordedRelation(classElementA, IndexConstants.IS_MIXED_IN_BY, |
| + _expectedLocation(classElementB, 'A {} // 2')); |
| + } |
| + |
| + void test_isMixedInBy_ClassTypeAlias() { |
| + _indexTestUnit(''' |
| +class A {} // 1 |
| +class B = Object with A; // 2 |
| +'''); |
| + // prepare elements |
| + ClassElement classElementA = _findElement("A"); |
| + ClassElement classElementB = _findElement("B"); |
| + // verify |
| + _assertRecordedRelation(classElementA, IndexConstants.IS_MIXED_IN_BY, |
| + _expectedLocation(classElementB, 'A; // 2')); |
| + } |
| + |
| + void test_isReadBy_ParameterElement() { |
| + _indexTestUnit(''' |
| +main(var p) { |
| + print(p); |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + Element parameterElement = _findElement("p"); |
| + // verify |
| + _assertRecordedRelation(parameterElement, IndexConstants.IS_READ_BY, |
| + _expectedLocation(mainElement, 'p);')); |
| + } |
| + |
| + void test_isReadBy_VariableElement() { |
| + _indexTestUnit(''' |
| +main() { |
| + var v = 0; |
| + print(v); |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + Element variableElement = _findElement("v"); |
| + // verify |
| + _assertRecordedRelation(variableElement, IndexConstants.IS_READ_BY, |
| + _expectedLocation(mainElement, 'v);')); |
| + } |
| + |
| + void test_isReadWrittenBy_ParameterElement() { |
| + _indexTestUnit(''' |
| +main(int p) { |
| + p += 1; |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + Element parameterElement = _findElement("p"); |
| + // verify |
| + _assertRecordedRelation(parameterElement, IndexConstants.IS_READ_WRITTEN_BY, |
| + _expectedLocation(mainElement, 'p += 1')); |
| + } |
| + |
| + void test_isReadWrittenBy_VariableElement() { |
| + _indexTestUnit(''' |
| +main() { |
| + var v = 0; |
| + v += 1; |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + Element variableElement = _findElement("v"); |
| + // verify |
| + _assertRecordedRelation(variableElement, IndexConstants.IS_READ_WRITTEN_BY, |
| + _expectedLocation(mainElement, 'v += 1')); |
| + } |
| + |
| + void test_isReferencedByQualifiedResolved_NameElement_field() { |
| + _indexTestUnit(''' |
| +class A { |
| + int field; |
| +} |
| +main(A a) { |
| + print(a.field); |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement('main'); |
| + Element nameElement = new NameElement('field'); |
| + // verify |
| + _assertRecordedRelation(nameElement, |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED, _expectedLocation( |
| + mainElement, 'field);')); |
| + } |
| + |
| + void test_isReferencedByQualifiedResolved_NameElement_method() { |
| + _indexTestUnit(''' |
| +class A { |
| + method() {} |
| +} |
| +main(A a) { |
| + a.method(); |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement('main'); |
| + Element nameElement = new NameElement('method'); |
| + // verify |
| + _assertRecordedRelation(nameElement, |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED, _expectedLocation( |
| + mainElement, 'method();')); |
| + } |
| + |
| + void test_isReferencedByQualifiedResolved_NameElement_operator() { |
| + _indexTestUnit(''' |
| +class A { |
| + operator +(o) {} |
| + operator -(o) {} |
| + operator ~() {} |
| + operator ==(o) {} |
| +} |
| +main(A a) { |
| + a + 5; |
| + a += 5; |
| + a == 5; |
| + ++a; |
| + --a; |
| + ~a; |
| + a++; |
| + a--; |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement('main'); |
| + // binary |
| + _assertRecordedRelation(new NameElement('+'), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED, _expectedLocation( |
| + mainElement, '+ 5', '+'.length)); |
| + _assertRecordedRelation(new NameElement('+'), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED, _expectedLocation( |
| + mainElement, '+= 5', '+='.length)); |
| + _assertRecordedRelation(new NameElement('=='), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED, _expectedLocation( |
| + mainElement, '== 5', '=='.length)); |
| + // prefix |
| + _assertRecordedRelation(new NameElement('+'), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED, _expectedLocation( |
| + mainElement, '++a', '++'.length)); |
| + _assertRecordedRelation(new NameElement('-'), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED, _expectedLocation( |
| + mainElement, '--a', '--'.length)); |
| + _assertRecordedRelation(new NameElement('~'), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED, _expectedLocation( |
| + mainElement, '~a', '~'.length)); |
| + // postfix |
| + _assertRecordedRelation(new NameElement('+'), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED, _expectedLocation( |
| + mainElement, '++;', '++'.length)); |
| + _assertRecordedRelation(new NameElement('-'), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED, _expectedLocation( |
| + mainElement, '--;', '--'.length)); |
| + } |
| + |
| + void test_isReferencedByQualifiedUnresolved_NameElement_field() { |
| + _indexTestUnit(''' |
| +class A { |
| + int field; |
| +} |
| +main(var a) { |
| + print(a.field); |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement('main'); |
| + FieldElement fieldElement = _findElement('field'); |
| + Element nameElement = new NameElement('field'); |
| + // verify |
| + _assertRecordedRelation(nameElement, IndexConstants.IS_DEFINED_BY, |
| + _expectedLocation(fieldElement, 'field;')); |
| + _assertRecordedRelation(nameElement, |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED, _expectedLocation( |
| + mainElement, 'field);')); |
| + } |
| + |
| + void test_isReferencedByQualifiedUnresolved_NameElement_method() { |
| + _indexTestUnit(''' |
| +class A { |
| + method() {} |
| +} |
| +main(var a) { |
| + a.method(); |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement('main'); |
| + MethodElement methodElement = _findElement('method'); |
| + Element nameElement = new NameElement('method'); |
| + // verify |
| + _assertRecordedRelation(nameElement, IndexConstants.IS_DEFINED_BY, |
| + _expectedLocation(methodElement, 'method() {}')); |
| + _assertRecordedRelation(nameElement, |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED, _expectedLocation( |
| + mainElement, 'method();')); |
| + } |
| + |
| + void test_isReferencedByQualifiedUnresolved_NameElement_operator() { |
| + _indexTestUnit(''' |
| +class A { |
| + operator +(o) {} |
| + operator -(o) {} |
| + operator ~() {} |
| + operator ==(o) {} |
| +} |
| +main(a) { |
| + a + 5; |
| + a += 5; |
| + a == 5; |
| + ++a; |
| + --a; |
| + ~a; |
| + a++; |
| + a--; |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement('main'); |
| + // binary |
| + _assertRecordedRelation(new NameElement('+'), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED, _expectedLocation( |
| + mainElement, '+ 5', '+'.length)); |
| + _assertRecordedRelation(new NameElement('+'), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED, _expectedLocation( |
| + mainElement, '+= 5', '+='.length)); |
| + _assertRecordedRelation(new NameElement('=='), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED, _expectedLocation( |
| + mainElement, '== 5', '=='.length)); |
| + // prefix |
| + _assertRecordedRelation(new NameElement('+'), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED, _expectedLocation( |
| + mainElement, '++a', '++'.length)); |
| + _assertRecordedRelation(new NameElement('-'), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED, _expectedLocation( |
| + mainElement, '--a', '--'.length)); |
| + _assertRecordedRelation(new NameElement('~'), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED, _expectedLocation( |
| + mainElement, '~a', '~'.length)); |
| + // postfix |
| + _assertRecordedRelation(new NameElement('+'), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED, _expectedLocation( |
| + mainElement, '++;', '++'.length)); |
| + _assertRecordedRelation(new NameElement('-'), |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED, _expectedLocation( |
| + mainElement, '--;', '--'.length)); |
| + } |
| + |
| + void test_isReferencedByQualified_ConstructorElement() { |
| + _indexTestUnit(''' |
| +class A implements B { |
| + A() {} |
| + A.foo() {} |
| +} |
| +class B extends A { |
| + B() : super(); // marker-1 |
| + B.foo() : super.foo(); // marker-2 |
| + factory B.bar() = A.foo; // marker-3 |
| +} |
| +main() { |
| + new A(); // marker-main-1 |
| + new A.foo(); // marker-main-2 |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement('main'); |
| + var isConstructor = (node) => node is ConstructorDeclaration; |
| + ConstructorElement consA = _findNodeElementAtString("A()", isConstructor); |
| + ConstructorElement consA_foo = _findNodeElementAtString("A.foo()", |
| + isConstructor); |
| + ConstructorElement consB = _findNodeElementAtString("B()", isConstructor); |
| + ConstructorElement consB_foo = _findNodeElementAtString("B.foo()", |
| + isConstructor); |
| + ConstructorElement consB_bar = _findNodeElementAtString("B.bar()", |
| + isConstructor); |
| + // A() |
| + _assertRecordedRelation(consA, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(consB, '(); // marker-1', 0)); |
| + _assertRecordedRelation(consA, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, '(); // marker-main-1', 0)); |
| + // A.foo() |
| + _assertRecordedRelation(consA_foo, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(consB_foo, '.foo(); // marker-2', '.foo'.length)); |
| + _assertRecordedRelation(consA_foo, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(consB_bar, '.foo; // marker-3', '.foo'.length)); |
| + _assertRecordedRelation(consA_foo, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, '.foo(); // marker-main-2', '.foo'.length)); |
| + } |
| + |
| + void test_isReferencedByQualified_ConstructorElement_classTypeAlias() { |
| + _indexTestUnit(''' |
| +class M {} |
| +class A implements B { |
| + A() {} |
| + A.named() {} |
| +} |
| +class B = A with M; |
| +main() { |
| + new B(); // marker-main-1 |
| + new B.named(); // marker-main-2 |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement('main'); |
| + var isConstructor = (node) => node is ConstructorDeclaration; |
| + ConstructorElement consA = _findNodeElementAtString("A()", isConstructor); |
| + ConstructorElement consA_named = _findNodeElementAtString("A.named()", |
| + isConstructor); |
| + // verify |
| + _assertRecordedRelation(consA, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, '(); // marker-main-1', 0)); |
| + _assertRecordedRelation(consA_named, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, '.named(); // marker-main-2', '.named'.length)); |
| + } |
| + |
| + void test_isReferencedByQualified_FieldElement() { |
| + _indexTestUnit(''' |
| +class A { |
| + static var field; |
| +} |
| +main() { |
| + A.field = 1; |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement('main'); |
| + FieldElement fieldElement = _findElement('field'); |
| + PropertyAccessorElement setterElement = fieldElement.setter; |
| + // verify |
| + _assertRecordedRelation(setterElement, |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED, _expectedLocation(mainElement, |
| + 'field = 1')); |
| + } |
| + |
| + void test_isReferencedByQualified_MethodElement() { |
| + _indexTestUnit(''' |
| +class A { |
| + foo() {} |
| + main() { |
| + print(this.foo); |
| + } |
| +} |
| +'''); |
| + // prepare elements |
| + Element fooElement = _findElement('foo'); |
| + Element mainElement = _findElement('main'); |
| + // verify |
| + _assertRecordedRelation(fooElement, |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED, _expectedLocation(mainElement, |
| + 'foo);')); |
| + } |
| + |
| + void test_isReferencedByQualified_MethodElement_operator_binary() { |
| + _indexTestUnit(''' |
| +class A { |
| + operator +(other) => this; |
| +} |
| +main(A a) { |
| + print(a + 1); |
| + a += 2; |
| + ++a; |
| + a++; |
| +} |
| +'''); |
| + // prepare elements |
| + Element element = _findElement('+'); |
| + Element mainElement = _findElement('main'); |
| + // verify |
| + _assertRecordedRelation(element, IndexConstants.IS_INVOKED_BY_QUALIFIED, |
| + _expectedLocation(mainElement, '+ 1', "+".length)); |
| + _assertRecordedRelation(element, IndexConstants.IS_INVOKED_BY_QUALIFIED, |
| + _expectedLocation(mainElement, '+= 2', "+=".length)); |
| + _assertRecordedRelation(element, IndexConstants.IS_INVOKED_BY_QUALIFIED, |
| + _expectedLocation(mainElement, '++a;', "++".length)); |
| + _assertRecordedRelation(element, IndexConstants.IS_INVOKED_BY_QUALIFIED, |
| + _expectedLocation(mainElement, '++;', "++".length)); |
| + } |
| + |
| + void test_isReferencedByQualified_MethodElement_operator_index() { |
| + _indexTestUnit(''' |
| +class A { |
| + operator [](i) => null; |
| + operator []=(i, v) {} |
| +} |
| +main(A a) { |
| + print(a[0]); |
| + a[1] = 42; |
| +} |
| +'''); |
| + // prepare elements |
| + MethodElement readElement = _findElement("[]"); |
| + MethodElement writeElement = _findElement("[]="); |
| + Element mainElement = _findElement('main'); |
| + // verify |
| + _assertRecordedRelation(readElement, IndexConstants.IS_INVOKED_BY_QUALIFIED, |
| + _expectedLocation(mainElement, '[0]', "[".length)); |
| + _assertRecordedRelation(writeElement, |
| + IndexConstants.IS_INVOKED_BY_QUALIFIED, _expectedLocation(mainElement, '[1] =', |
| + "[".length)); |
| + } |
| + |
| + void test_isReferencedByQualified_MethodElement_operator_prefix() { |
| + _indexTestUnit(''' |
| +class A { |
| + A operator ~() => this; |
| +} |
| +main(A a) { |
| + print(~a); |
| +} |
| +'''); |
| + // prepare elements |
| + MethodElement element = _findElement("~"); |
| + Element mainElement = _findElement('main'); |
| + // verify |
| + _assertRecordedRelation(element, IndexConstants.IS_INVOKED_BY_QUALIFIED, |
| + _expectedLocation(mainElement, '~a', "~".length)); |
| + } |
| + |
| + void test_isReferencedByQualified_PropertyAccessorElement_method_getter() { |
| + _indexTestUnit(''' |
| +class A { |
| + get foo => 42; |
| + main() { |
| + print(this.foo); |
| + } |
| +} |
| +'''); |
| + // prepare elements |
| + PropertyAccessorElement element = _findNodeElementAtString('foo =>'); |
| + Element mainElement = _findElement('main'); |
| + // verify |
| + _assertRecordedRelation(element, IndexConstants.IS_REFERENCED_BY_QUALIFIED, |
| + _expectedLocation(mainElement, 'foo);')); |
| + _assertNoRecordedRelation(element, IndexConstants.IS_REFERENCED_BY, null); |
| + } |
| + |
| + void test_isReferencedByQualified_PropertyAccessorElement_method_setter() { |
| + _indexTestUnit(''' |
| +class A { |
| + set foo(x) {} |
| + main() { |
| + this.foo = 42; |
| + } |
| +} |
| +'''); |
| + // prepare elements |
| + PropertyAccessorElement element = _findNodeElementAtString('foo(x)'); |
| + Element mainElement = _findElement('main'); |
| + // verify |
| + _assertRecordedRelation(element, IndexConstants.IS_REFERENCED_BY_QUALIFIED, |
| + _expectedLocation(mainElement, 'foo = 42;')); |
| + _assertNoRecordedRelation(element, IndexConstants.IS_REFERENCED_BY, null); |
| + } |
| + |
| + void test_isReferencedByQualified_PropertyAccessorElement_topLevelField() { |
| + addSource('/lib.dart', ''' |
| +library lib; |
| +var myVar; |
| +'''); |
| + _indexTestUnit(''' |
| +import 'lib.dart' as pref; |
| +main() { |
| + pref.myVar = 1; |
| + print(pref.myVar); |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement('main'); |
| + ImportElement importElement = testLibraryElement.imports[0]; |
| + CompilationUnitElement impUnit = |
| + importElement.importedLibrary.definingCompilationUnit; |
| + TopLevelVariableElement myVar = impUnit.topLevelVariables[0]; |
| + PropertyAccessorElement getter = myVar.getter; |
| + PropertyAccessorElement setter = myVar.setter; |
| + // verify |
| + _assertRecordedRelation(setter, IndexConstants.IS_REFERENCED_BY_QUALIFIED, |
| + _expectedLocation(mainElement, 'myVar = 1')); |
| + _assertRecordedRelation(getter, IndexConstants.IS_REFERENCED_BY_QUALIFIED, |
| + _expectedLocation(mainElement, 'myVar);')); |
| + } |
| + |
| + void test_isReferencedByUnqualified_FieldElement() { |
| + _indexTestUnit(''' |
| +class A { |
| + var field; |
| + main() { |
| + field = 5; |
| + print(field); |
| + } |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + FieldElement fieldElement = _findElement("field"); |
| + PropertyAccessorElement getter = fieldElement.getter; |
| + PropertyAccessorElement setter = fieldElement.setter; |
| + // verify |
| + _assertRecordedRelation(setter, IndexConstants.IS_REFERENCED_BY_UNQUALIFIED, |
| + _expectedLocation(mainElement, 'field = 5')); |
| + _assertRecordedRelation(getter, IndexConstants.IS_REFERENCED_BY_UNQUALIFIED, |
| + _expectedLocation(mainElement, 'field);')); |
| + } |
| + |
| + void test_isReferencedByUnqualified_MethodElement() { |
| + _indexTestUnit(''' |
| +class A { |
| + method() {} |
| + main() { |
| + print(method); |
| + } |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + MethodElement methodElement = _findElement("method"); |
| + // verify |
| + _assertRecordedRelation(methodElement, |
| + IndexConstants.IS_REFERENCED_BY_UNQUALIFIED, _expectedLocation(mainElement, |
| + 'method);')); |
| + _assertNoRecordedRelation(methodElement, IndexConstants.IS_REFERENCED_BY, |
| + null); |
| + } |
| + |
| + void test_isReferencedByUnqualified_TopLevelVariableElement() { |
| + _indexTestUnit(''' |
| +var topVariable; |
| +main() { |
| + topVariable = 5; |
| + print(topVariable); |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + TopLevelVariableElement variableElement = _findElement("topVariable"); |
| + // verify |
| + _assertRecordedRelation(variableElement.setter, |
| + IndexConstants.IS_REFERENCED_BY_UNQUALIFIED, _expectedLocation(mainElement, |
| + 'topVariable = 5')); |
| + _assertRecordedRelation(variableElement.getter, |
| + IndexConstants.IS_REFERENCED_BY_UNQUALIFIED, _expectedLocation(mainElement, |
| + 'topVariable);')); |
| + } |
| + |
| + void test_isReferencedBy_ClassElement() { |
| + _indexTestUnit(''' |
| +class A { |
| + static var field; |
| +} |
| +main(A p) { |
| + A v; |
| + new A(); // 2 |
| + A.field = 1; |
| + print(A.field); // 3 |
| +} |
| +'''); |
| + // prepare elements |
| + ClassElement aElement = _findElement("A"); |
| + Element mainElement = _findElement("main"); |
| + ParameterElement pElement = _findElement("p"); |
| + VariableElement vElement = _findElement("v"); |
| + // verify |
| + _assertRecordedRelation(aElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(pElement, 'A p) {')); |
| + _assertRecordedRelation(aElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(vElement, 'A v;')); |
| + _assertRecordedRelation(aElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'A(); // 2')); |
| + _assertRecordedRelation(aElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'A.field = 1;')); |
| + _assertRecordedRelation(aElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'A.field); // 3')); |
| + } |
| + |
| + void test_isReferencedBy_ClassTypeAlias() { |
| + _indexTestUnit(''' |
| +class A {} |
| +class B = Object with A; |
| +main(B p) { |
| + B v; |
| +} |
| +'''); |
| + // prepare elements |
| + ClassElement bElement = _findElement("B"); |
| + ParameterElement pElement = _findElement("p"); |
| + VariableElement vElement = _findElement("v"); |
| + // verify |
| + _assertRecordedRelation(bElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(pElement, 'B p) {')); |
| + _assertRecordedRelation(bElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(vElement, 'B v;')); |
| + } |
| + |
| + void test_isReferencedBy_CompilationUnitElement() { |
| + addSource('/my_unit.dart', 'part of my_lib;'); |
| + _indexTestUnit(''' |
| +library my_lib; |
| +part 'my_unit.dart'; |
| +'''); |
| + // prepare elements |
| + CompilationUnitElement myUnitElement = testLibraryElement.parts[0]; |
| + // verify |
| + _assertRecordedRelation(myUnitElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(testUnitElement, "'my_unit.dart';", "'my_unit.dart'".length)); |
| + } |
| + |
| + void test_isReferencedBy_ConstructorFieldInitializer() { |
| + _indexTestUnit(''' |
| +class A { |
| + int field; |
| + A() : field = 5; |
| +} |
| +'''); |
| + // prepare elements |
| + ConstructorElement constructorElement = _findNodeElementAtString("A()", |
| + (node) => node is ConstructorDeclaration); |
| + FieldElement fieldElement = _findElement("field"); |
| + // verify |
| + _assertRecordedRelation(fieldElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(constructorElement, 'field = 5')); |
| + } |
| + |
| + void test_isReferencedBy_FieldFormalParameterElement() { |
| + _indexTestUnit(''' |
| +class A { |
| + int field; |
| + A(this.field); |
| +} |
| +'''); |
| + // prepare elements |
| + FieldElement fieldElement = _findElement("field"); |
| + Element fieldParameterElement = _findNodeElementAtString("field);"); |
| + // verify |
| + _assertRecordedRelation(fieldElement, |
| + IndexConstants.IS_REFERENCED_BY_QUALIFIED, _expectedLocation( |
| + fieldParameterElement, 'field);')); |
| + } |
| + |
| + void test_isReferencedBy_FunctionElement() { |
| + _indexTestUnit(''' |
| +foo() {} |
| +main() { |
| + print(foo); |
| + print(foo()); |
| +} |
| +'''); |
| + // prepare elements |
| + FunctionElement element = _findElement("foo"); |
| + Element mainElement = _findElement("main"); |
| + // "referenced" here |
| + _assertRecordedRelation(element, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'foo);')); |
| + // only "invoked", but not "referenced" |
| + { |
| + _assertRecordedRelation(element, IndexConstants.IS_INVOKED_BY, |
| + _expectedLocation(mainElement, 'foo());')); |
| + _assertNoRecordedRelation(element, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'foo());')); |
| + } |
| + } |
| + |
| + void test_isReferencedBy_FunctionTypeAliasElement() { |
| + _indexTestUnit(''' |
| +typedef A(); |
| +main(A p) { |
| +} |
| +'''); |
| + // prepare elements |
| + Element aElement = _findElement('A'); |
| + Element pElement = _findElement('p'); |
| + // verify |
| + _assertRecordedRelation(aElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(pElement, 'A p) {')); |
| + } |
| + |
| + void test_isReferencedBy_ImportElement_noPrefix() { |
| + addSource('/lib.dart', ''' |
| +library lib; |
| +var myVar; |
| +myFunction() {} |
| +myToHide() {} |
| +'''); |
| + _indexTestUnit(''' |
| +import 'lib.dart' show myVar, myFunction hide myToHide; |
| +main() { |
| + myVar = 1; |
| + myFunction(); |
| + print(0); |
| +} |
| +'''); |
| + // prepare elements |
| + ImportElement importElement = testLibraryElement.imports[0]; |
| + Element mainElement = _findElement('main'); |
| + // verify |
| + _assertRecordedRelation(importElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'myVar = 1;', 0)); |
| + _assertRecordedRelation(importElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'myFunction();', 0)); |
| + _assertNoRecordedRelation(importElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'print(0);', 0)); |
| + // no references from import combinators |
| + _assertNoRecordedRelation(importElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(testUnitElement, 'myVar, ', 0)); |
| + _assertNoRecordedRelation(importElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(testUnitElement, 'myFunction hide', 0)); |
| + _assertNoRecordedRelation(importElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(testUnitElement, 'myToHide;', 0)); |
| + } |
| + |
| + void test_isReferencedBy_ImportElement_withPrefix() { |
| + addSource('/libA.dart', ''' |
| +library libA; |
| +var myVar; |
| +'''); |
| + addSource('/libB.dart', ''' |
| +library libB; |
| +class MyClass {} |
| +'''); |
| + _indexTestUnit(''' |
| +import 'libA.dart' as pref; |
| +import 'libB.dart' as pref; |
| +main() { |
| + pref.myVar = 1; |
| + new pref.MyClass(); |
| +} |
| +'''); |
| + // prepare elements |
| + ImportElement importElementA = testLibraryElement.imports[0]; |
| + ImportElement importElementB = testLibraryElement.imports[1]; |
| + Element mainElement = _findElement('main'); |
| + // verify |
| + _assertRecordedRelation(importElementA, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'pref.myVar = 1;', 'pref.'.length)); |
| + _assertRecordedRelation(importElementB, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'pref.MyClass();', 'pref.'.length)); |
| + } |
| + |
| + void test_isReferencedBy_ImportElement_withPrefix_combinators() { |
| + addSource('/lib.dart', ''' |
| +library lib; |
| +class A {} |
| +class B {} |
| +'''); |
| + _indexTestUnit(''' |
| +import 'lib.dart' as pref show A; |
| +import 'lib.dart' as pref show B; |
| +import 'lib.dart'; |
| +import 'lib.dart' as otherPrefix; |
| +main() { |
| + new pref.A(); |
| + new pref.B(); |
| +} |
| +'''); |
| + // prepare elements |
| + ImportElement importElementA = testLibraryElement.imports[0]; |
| + ImportElement importElementB = testLibraryElement.imports[1]; |
| + Element mainElement = _findElement('main'); |
| + // verify |
| + _assertRecordedRelation(importElementA, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'pref.A();', 'pref.'.length)); |
| + _assertRecordedRelation(importElementB, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'pref.B();', 'pref.'.length)); |
| + } |
| + |
| + void test_isReferencedBy_ImportElement_withPrefix_invocation() { |
| + addSource('/lib.dart', ''' |
| +library lib; |
| +myFunc() {} |
| +'''); |
| + _indexTestUnit(''' |
| +import 'lib.dart' as pref; |
| +main() { |
| + pref.myFunc(); |
| +} |
| +'''); |
| + // prepare elements |
| + ImportElement importElement = testLibraryElement.imports[0]; |
| + Element mainElement = _findElement('main'); |
| + // verify |
| + _assertRecordedRelation(importElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'pref.myFunc();', 'pref.'.length)); |
| + } |
| + |
| + void test_isReferencedBy_ImportElement_withPrefix_oneCandidate() { |
| + addSource('/lib.dart', ''' |
| +library lib; |
| +class A {} |
| +class B {} |
| +'''); |
| + _indexTestUnit(''' |
| +import 'lib.dart' as pref show A; |
| +main() { |
| + new pref.A(); |
| +} |
| +'''); |
| + // prepare elements |
| + ImportElement importElement = testLibraryElement.imports[0]; |
| + Element mainElement = _findElement('main'); |
| + // verify |
| + _assertRecordedRelation(importElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'pref.A();', 'pref.'.length)); |
| + } |
| + |
| + void test_isReferencedBy_ImportElement_withPrefix_unresolvedElement() { |
| + verifyNoTestUnitErrors = false; |
| + addSource('/lib.dart', ''' |
| +library lib; |
| +'''); |
| + _indexTestUnit(''' |
| +import 'lib.dart' as pref; |
| +main() { |
| + pref.myVar = 1; |
| +} |
| +'''); |
| + } |
| + |
| + void test_isReferencedBy_ImportElement_withPrefix_wrongInvocation() { |
| + verifyNoTestUnitErrors = false; |
| + _indexTestUnit(''' |
| +import 'dart:math' as m; |
| +main() { |
| + m(); |
| +}'''); |
| + } |
| + |
| + void test_isReferencedBy_ImportElement_withPrefix_wrongPrefixedIdentifier() { |
| + verifyNoTestUnitErrors = false; |
| + _indexTestUnit(''' |
| +import 'dart:math' as m; |
| +main() { |
| + x.m; |
| +} |
| +'''); |
| + } |
| + |
| + void test_isReferencedBy_LabelElement() { |
| + _indexTestUnit(''' |
| +main() { |
| + L: while (true) { |
| + break L; |
| + } |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement('main'); |
| + Element element = _findElement('L'); |
| + // verify |
| + _assertRecordedRelation(element, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'L;')); |
| + } |
| + |
| + void test_isReferencedBy_LibraryElement_export() { |
| + addSource('/lib.dart', ''' |
| +library lib; |
| +'''); |
| + _indexTestUnit(''' |
| +export 'lib.dart'; |
| +'''); |
| + // prepare elements |
| + LibraryElement libElement = testLibraryElement.exportedLibraries[0]; |
| + CompilationUnitElement libUnitElement = libElement.definingCompilationUnit; |
| + // verify |
| + _assertRecordedRelation(libUnitElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(testUnitElement, "'lib.dart'", "'lib.dart'".length)); |
| + } |
| + |
| + void test_isReferencedBy_LibraryElement_import() { |
| + addSource('/lib.dart', ''' |
| +library lib; |
| +'''); |
| + _indexTestUnit(''' |
| +import 'lib.dart'; |
| +'''); |
| + // prepare elements |
| + LibraryElement libElement = testLibraryElement.imports[0].importedLibrary; |
| + CompilationUnitElement libUnitElement = libElement.definingCompilationUnit; |
| + // verify |
| + _assertRecordedRelation(libUnitElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(testUnitElement, "'lib.dart'", "'lib.dart'".length)); |
| + } |
| + |
| + void test_isReferencedBy_ParameterElement() { |
| + _indexTestUnit(''' |
| +foo({var p}) {} |
| +main() { |
| + foo(p: 1); |
| +} |
| +'''); |
| + // prepare elements |
| + Element mainElement = _findElement('main'); |
| + Element element = _findElement('p'); |
| + // verify |
| + _assertRecordedRelation(element, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(mainElement, 'p: 1')); |
| + } |
| + |
| + void test_isReferencedBy_TypeParameterElement() { |
| + _indexTestUnit(''' |
| +class A<T> { |
| + T f; |
| + foo(T p) { |
| + T v; |
| + } |
| +} |
| +'''); |
| + // prepare elements |
| + Element typeParameterElement = _findElement('T'); |
| + Element fieldElement = _findElement('f'); |
| + Element parameterElement = _findElement('p'); |
| + Element variableElement = _findElement('v'); |
| + // verify |
| + _assertRecordedRelation(typeParameterElement, |
| + IndexConstants.IS_REFERENCED_BY, _expectedLocation(fieldElement, 'T f')); |
| + _assertRecordedRelation(typeParameterElement, |
| + IndexConstants.IS_REFERENCED_BY, _expectedLocation(parameterElement, 'T p')); |
| + _assertRecordedRelation(typeParameterElement, |
| + IndexConstants.IS_REFERENCED_BY, _expectedLocation(variableElement, 'T v')); |
| + } |
| + |
| + /** |
| + * 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. |
| + */ |
| + void test_isReferencedBy_identifierInComment() { |
| + _indexTestUnit(''' |
| +class A {} |
| +/// [A] text |
| +var myVariable = null; |
| +'''); |
| + // prepare elements |
| + Element aElement = _findElement('A'); |
| + Element variableElement = _findElement('myVariable'); |
| + // verify |
| + _assertRecordedRelation(aElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(testUnitElement, 'A] text')); |
| + _assertNoRecordedRelation(aElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(variableElement, 'A] text')); |
| + } |
| + |
| + void test_isReferencedBy_libraryName() { |
| + Source libSource = addSource('/lib.dart', ''' |
| +library lib; |
| +part 'test.dart'; |
| +'''); |
| + testCode = 'part of lib;'; |
| + testSource = addSource('/test.dart', testCode); |
| + testUnit = resolveDartUnit(testSource, libSource); |
| + testUnitElement = testUnit.element; |
| + testLibraryElement = testUnitElement.library; |
| + indexDartUnit(store, context, testUnit); |
| + // verify |
| + _assertRecordedRelation(testLibraryElement, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(testUnitElement, "lib;")); |
| + } |
| + |
| + void test_isReferencedBy_typeInVariableList() { |
| + _indexTestUnit(''' |
| +class A {} |
| +A myVariable = null; |
| +'''); |
| + // prepare elements |
| + Element classElementA = _findElement('A'); |
| + Element variableElement = _findElement('myVariable'); |
| + // verify |
| + _assertRecordedRelation(classElementA, IndexConstants.IS_REFERENCED_BY, |
| + _expectedLocation(variableElement, 'A myVariable')); |
| + } |
| + |
| + void test_isWrittenBy_ParameterElement() { |
| + _indexTestUnit(''' |
| +main(var p) { |
| + p = 1; |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + ParameterElement pElement = _findElement("p"); |
| + // verify |
| + _assertRecordedRelation(pElement, IndexConstants.IS_WRITTEN_BY, |
| + _expectedLocation(mainElement, 'p = 1')); |
| + } |
| + |
| + void test_isWrittenBy_VariableElement() { |
| + _indexTestUnit(''' |
| +main() { |
| + var v = 0; |
| + v = 1; |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + LocalVariableElement vElement = _findElement("v"); |
| + // verify |
| + _assertRecordedRelation(vElement, IndexConstants.IS_WRITTEN_BY, |
| + _expectedLocation(mainElement, 'v = 1')); |
| + } |
| + |
| + void test_nameIsInvokedBy() { |
| + _indexTestUnit(''' |
| +class A { |
| + test(x) {} |
| +} |
| +main(A a, p) { |
| + a.test(1); |
| + p.test(2); |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + Element nameElement = new NameElement('test'); |
| + // verify |
| + _assertRecordedRelation(nameElement, |
| + IndexConstants.NAME_IS_INVOKED_BY_RESOLVED, _expectedLocation(mainElement, |
| + 'test(1)')); |
| + _assertRecordedRelation(nameElement, |
| + IndexConstants.NAME_IS_INVOKED_BY_UNRESOLVED, _expectedLocation(mainElement, |
| + 'test(2)')); |
| + _assertNoRecordedRelation(nameElement, |
| + IndexConstants.NAME_IS_READ_BY_UNRESOLVED, _expectedLocation(mainElement, |
| + 'test(2)')); |
| + } |
| + |
| + void test_nameIsReadBy() { |
| + _indexTestUnit(''' |
| +class A { |
| + var test; |
| +} |
| +main(A a, p) { |
| + print(a.test); // a |
| + print(p.test); // p |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + Element nameElement = new NameElement('test'); |
| + // verify |
| + _assertRecordedRelation(nameElement, |
| + IndexConstants.NAME_IS_READ_BY_RESOLVED, _expectedLocation(mainElement, |
| + 'test); // a')); |
| + _assertRecordedRelation(nameElement, |
| + IndexConstants.NAME_IS_READ_BY_UNRESOLVED, _expectedLocation(mainElement, |
| + 'test); // p')); |
| + } |
| + |
| + void test_nameIsReadWrittenBy() { |
| + _indexTestUnit(''' |
| +class A { |
| + var test; |
| +} |
| +main(A a, p) { |
| + a.test += 1; |
| + p.test += 2; |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + Element nameElement = new NameElement('test'); |
| + // verify |
| + _assertRecordedRelation(nameElement, |
| + IndexConstants.NAME_IS_READ_WRITTEN_BY_RESOLVED, _expectedLocation(mainElement, |
| + 'test += 1')); |
| + _assertRecordedRelation(nameElement, |
| + IndexConstants.NAME_IS_READ_WRITTEN_BY_UNRESOLVED, _expectedLocation( |
| + mainElement, 'test += 2')); |
| + } |
| + |
| + void test_nameIsWrittenBy() { |
| + _indexTestUnit(''' |
| +class A { |
| + var test; |
| +} |
| +main(A a, p) { |
| + a.test = 1; |
| + p.test = 2; |
| +}'''); |
| + // prepare elements |
| + Element mainElement = _findElement("main"); |
| + Element nameElement = new NameElement('test'); |
| + // verify |
| + _assertRecordedRelation(nameElement, |
| + IndexConstants.NAME_IS_WRITTEN_BY_RESOLVED, _expectedLocation(mainElement, |
| + 'test = 1')); |
| + _assertRecordedRelation(nameElement, |
| + IndexConstants.NAME_IS_WRITTEN_BY_UNRESOLVED, _expectedLocation(mainElement, |
| + 'test = 2')); |
| + } |
| + |
| + void test_nullUnit() { |
| + indexDartUnit(store, context, null); |
| + } |
| + |
| + void test_nullUnitElement() { |
| + CompilationUnit unit = new CompilationUnit(null, null, [], [], null); |
| + indexDartUnit(store, context, unit); |
| + } |
| + |
| + void _assertDefinesTopLevelElement(Relationship relationship, |
| + ExpectedLocation expectedLocation) { |
| + _assertRecordedRelation(testLibraryElement, relationship, expectedLocation); |
| + _assertRecordedRelation(UniverseElement.INSTANCE, relationship, |
| + expectedLocation); |
| + } |
| + |
| + void _assertNoErrorsInSource() { |
| + List<AnalysisError> errors = context.getErrors(testSource).errors; |
| + expect(errors, isEmpty); |
| + } |
| + |
| + /** |
| + * Asserts that [recordedRelations] has no item with the specified properties. |
| + */ |
| + void _assertNoRecordedRelation(Element element, Relationship relationship, |
| + ExpectedLocation location) { |
| + for (RecordedRelation recordedRelation in recordedRelations) { |
| + if (_equalsRecordedRelation(recordedRelation, element, relationship, |
| + location)) { |
| + fail('not expected: ${recordedRelation} in\n' + recordedRelations.join( |
| + '\n')); |
| + } |
| + } |
| + } |
| + |
| + /** |
| + * Asserts that [recordedRelations] has an item with the expected properties. |
| + */ |
| + Location _assertRecordedRelation(Element expectedElement, |
| + Relationship expectedRelationship, ExpectedLocation expectedLocation) { |
| + for (RecordedRelation recordedRelation in recordedRelations) { |
| + if (_equalsRecordedRelation(recordedRelation, expectedElement, |
| + expectedRelationship, expectedLocation)) { |
| + return recordedRelation.location; |
| + } |
| + } |
| + fail("not found\n$expectedElement $expectedRelationship " |
| + "in $expectedLocation in\n" + recordedRelations.join('\n')); |
| + return null; |
| + } |
| + |
| + ExpectedLocation _expectedLocation(Element element, String search, [int length |
| + = -1]) { |
| + int offset = _findOffset(search); |
| + if (length == -1) { |
| + length = _getLeadingIdentifierLength(search); |
| + } |
| + return new ExpectedLocation(element, offset, length); |
| + } |
| + |
| + Element _findElement(String name, [ElementKind kind]) { |
| + return findChildElement(testUnitElement, name, kind); |
| + } |
| + |
| + AstNode _findNodeAtOffset(int offset, [Predicate<AstNode> predicate]) { |
| + AstNode result = new NodeLocator.con1(offset).searchWithin(testUnit); |
| + if (result != null && predicate != null) { |
| + result = result.getAncestor(predicate); |
| + } |
| + return result; |
| + } |
| + |
| + AstNode _findNodeAtString(String search, [Predicate<AstNode> predicate]) { |
| + int offset = _findOffset(search); |
| + return _findNodeAtOffset(offset, predicate); |
| + } |
| + |
| + Element _findNodeElementAtString(String search, |
| + [Predicate<AstNode> predicate]) { |
| + AstNode node = _findNodeAtString(search, predicate); |
| + if (node == null) { |
| + return null; |
| + } |
| + return ElementLocator.locate(node); |
| + } |
| + |
| + int _findOffset(String search) { |
| + int offset = testCode.indexOf(search); |
| + expect(offset, isNonNegative, reason: "Not found '$search' in\n$testCode"); |
| + return offset; |
| + } |
| + |
| + void _indexTestUnit(String code) { |
| + testCode = code; |
| + testSource = addSource('/test.dart', code); |
| + testUnit = resolveLibraryUnit(testSource); |
| + if (verifyNoTestUnitErrors) { |
| + _assertNoErrorsInSource(); |
| + } |
| + testUnitElement = testUnit.element; |
| + testLibraryElement = testUnitElement.library; |
| + indexDartUnit(store, context, testUnit); |
| + } |
| +} |
| + |
| +class ExpectedLocation { |
| + Element element; |
| + int offset; |
| + int length; |
| + |
| + ExpectedLocation(this.element, this.offset, this.length); |
| + |
| + @override |
| + String toString() { |
| + return 'ExpectedLocation(element=$element; offset=$offset; length=$length)'; |
| + } |
| +} |
| + |
| +class MockIndexStore extends TypedMock implements IndexStore { |
| + noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
| +} |
| + |
| + |
| +/** |
| + * Information about a relation recorded into {@link IndexStore}. |
| + */ |
| +class RecordedRelation { |
| + final Element element; |
| + final Relationship relationship; |
| + final Location location; |
| + |
| + RecordedRelation(this.element, this.relationship, this.location); |
| + |
| + @override |
| + String toString() { |
| + return 'RecordedRelation(element=$element; relationship=$relationship; ' |
| + 'location=$location)'; |
| + } |
| +} |