blob: 5a9abb0e66c8927ff8efe05361c3a40dd88b62cc [file] [log] [blame]
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/services/index2/index2.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:unittest/unittest.dart';
import '../../abstract_single_unit.dart';
import '../../utils.dart';
main() {
initializeTestEnvironment();
defineReflectiveTests(Index2Test);
}
@reflectiveTest
class Index2Test extends AbstractSingleUnitTest {
Index2 index = createMemoryIndex2();
/**
* Return the [Location] with given properties, or fail.
*/
Location findLocation(List<Location> locations, String libraryUri,
String unitUri, int offset, int length) {
for (Location location in locations) {
if (location.libraryUri == libraryUri &&
location.unitUri == unitUri &&
location.offset == offset &&
location.length == length) {
return location;
}
}
fail('No at $offset with length $length in\n${locations.join('\n')}');
return null;
}
/**
* Return the [Location] with given properties, or fail.
*/
Location findLocationSource(
List<Location> locations, Source source, String search,
{int length}) {
String code = source.contents.data;
int offset = code.indexOf(search);
expect(offset, isNonNegative, reason: 'Not found "$search" in\n$code');
length ??= getLeadingIdentifierLength(search);
String uri = source.uri.toString();
return findLocation(locations, uri, uri, offset, length);
}
/**
* Return the [Location] with given properties, or fail.
*/
Location findLocationTest(List<Location> locations, String search,
{int length}) {
int offset = findOffset(search);
length ??= getLeadingIdentifierLength(search);
String testUri = testSource.uri.toString();
return findLocation(locations, testUri, testUri, offset, length);
}
void setUp() {
super.setUp();
}
void tearDown() {
super.tearDown();
index = null;
}
test_getDefinedNames_classMember() async {
_indexTestUnit('''
class A {
test() {}
}
class B {
int test = 1;
main() {
int test = 2;
}
}
''');
ClassElement classA = findElement('A');
ClassElement classB = findElement('B');
List<Location> locations = await index.getDefinedNames(
new RegExp(r'^test$'), IndexNameKind.classMember);
expect(locations, hasLength(2));
_assertHasDefinedName(locations, classA.methods[0]);
_assertHasDefinedName(locations, classB.fields[0]);
}
test_getDefinedNames_topLevel() async {
_indexTestUnit('''
class A {} // A
class B = Object with A;
typedef C();
D() {}
var E = null;
class NoMatchABCDE {}
''');
Element topA = findElement('A');
Element topB = findElement('B');
Element topC = findElement('C');
Element topD = findElement('D');
Element topE = findElement('E');
List<Location> locations = await index.getDefinedNames(
new RegExp(r'^[A-E]$'), IndexNameKind.topLevel);
expect(locations, hasLength(5));
_assertHasDefinedName(locations, topA);
_assertHasDefinedName(locations, topB);
_assertHasDefinedName(locations, topC);
_assertHasDefinedName(locations, topD);
_assertHasDefinedName(locations, topE);
}
test_getRelations_isExtendedBy() async {
_indexTestUnit(r'''
class A {}
class B extends A {} // B
''');
Source source2 = _indexUnit(
'/test2.dart',
r'''
import 'test.dart';
class C extends A {} // C
''');
ClassElement elementA = testUnitElement.getType('A');
List<Location> locations =
await index.getRelations(elementA, IndexRelationKind.IS_EXTENDED_BY);
findLocationTest(locations, 'A {} // B');
findLocationSource(locations, source2, 'A {} // C');
}
test_getRelations_isReferencedBy() async {
_indexTestUnit(r'''
main(int a, int b) {
}
''');
ClassElement intElement = context.typeProvider.intType.element;
List<Location> locations = await index.getRelations(
intElement, IndexRelationKind.IS_REFERENCED_BY);
findLocationTest(locations, 'int a');
findLocationTest(locations, 'int b');
}
test_getUnresolvedMemberReferences() async {
_indexTestUnit('''
class A {
var test; // A
mainA() {
test(); // a-inv-r-nq
test = 1; // a-ref-r-nq
test += 2; // a-ref-r-nq
print(test); // a-ref-r-nq
}
}
main(A a, p) {
a.test(); // a-inv-r-q
a.test = 1; // a-ref-r-q
a.test += 2; // a-ref-r-q
print(a.test); // a-ref-r-q
p.test(); // p-inv-ur-q
p.test = 1; // p-ref-ur-q
p.test += 2; // p-ref-ur-q
print(p.test); // p-ref-ur-q
print(p.test2); // not requested
}
''');
List<Location> locations =
await index.getUnresolvedMemberReferences('test');
expect(locations, hasLength(4));
findLocationTest(locations, 'test(); // p-inv-ur-q');
findLocationTest(locations, 'test = 1; // p-ref-ur-q');
findLocationTest(locations, 'test += 2; // p-ref-ur-q');
findLocationTest(locations, 'test); // p-ref-ur-q');
}
/**
* Assert that the given list of [locations] has a [Location] corresponding
* to the [element].
*/
void _assertHasDefinedName(List<Location> locations, Element element) {
String libraryUri = element.library.source.uri.toString();
String unitUri = element.source.uri.toString();
for (Location location in locations) {
if (location.libraryUri == libraryUri &&
location.unitUri == unitUri &&
location.offset == element.nameOffset &&
location.length == element.nameLength) {
return;
}
}
fail('No declaration of $element at ${element.nameOffset} in\n'
'${locations.join('\n')}');
}
void _indexTestUnit(String code) {
resolveTestUnit(code);
index.indexUnit(testUnit);
}
Source _indexUnit(String path, String code) {
Source source = addSource(path, code);
CompilationUnit unit = resolveLibraryUnit(source);
index.indexUnit(unit);
return source;
}
}