blob: b5087b609d9cfe3266e1e943c522f55e1b1dda64 [file] [log] [blame]
// 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/reflective_tests.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:typed_mock/typed_mock.dart';
import 'package:unittest/unittest.dart';
import 'abstract_single_unit.dart';
main() {
groupSep = ' | ';
group('DartUnitContributor', () {
runReflectiveTests(DartUnitContributorTest);
});
}
/**
* Returns `true` if the [actual] location the same properties as [expected].
*/
bool _equalsLocation(Location actual, ExpectedLocation expected) {
return _equalsLocationProperties(
actual,
expected.element,
expected.offset,
expected.length);
}
/**
* Returns `true` if the [actual] location the expected properties.
*/
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));
}
@ReflectiveTestCase()
class DartUnitContributorTest extends AbstractSingleUnitTest {
IndexStore store = new MockIndexStore();
List<RecordedRelation> recordedRelations = <RecordedRelation>[];
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_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_QUALIFIED,
_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_TopLevelVariableElement() {
addSource('/lib.dart', '''
library lib;
var V;
''');
_indexTestUnit('''
import 'lib.dart' show V; // imp
''');
// prepare elements
var libElement = testLibraryElement.imports[0].importedLibrary;
var libUnit = libElement.definingCompilationUnit;
TopLevelVariableElement fieldElement = libUnit.topLevelVariables[0];
// verify
_assertRecordedRelation(
fieldElement,
IndexConstants.IS_REFERENCED_BY_QUALIFIED,
_expectedLocation(testUnitElement, 'V; // imp'));
}
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);
}
/**
* 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);
}
void _indexTestUnit(String code) {
resolveTestUnit(code);
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)';
}
}