Improve search for constructors and import elements.

R=brianwilkerson@google.com
BUG=

Review URL: https://codereview.chromium.org/1778363003 .
This commit is contained in:
Konstantin Shcheglov
2016-03-10 14:57:42 -08:00
parent ea7929d2fb
commit 4e8e1e2e04
4 changed files with 116 additions and 26 deletions
@@ -141,8 +141,10 @@ class SearchEngineImpl2 implements SearchEngine {
PropertyAccessorElement getter = field.getter;
PropertyAccessorElement setter = field.setter;
// field itself
await _addMatches(matches, field, IndexRelationKind.IS_REFERENCED_BY,
MatchKind.REFERENCE);
if (!field.isSynthetic) {
await _addMatches(matches, field, IndexRelationKind.IS_REFERENCED_BY,
MatchKind.REFERENCE);
}
// getter
if (getter != null) {
await _addMatches(
@@ -287,6 +289,12 @@ class _ImportElementReferencesVisitor extends RecursiveAstVisitor {
.toSet();
}
@override
visitExportDirective(ExportDirective node) {}
@override
visitImportDirective(ImportDirective node) {}
@override
visitSimpleIdentifier(SimpleIdentifier node) {
if (node.inDeclarationContext()) {
@@ -257,6 +257,36 @@ class A {
await _verifyReferences(element, expected);
}
test_searchReferences_FieldElement_synthetic() async {
_indexTestUnit('''
class A {
get field => null;
set field(x) {}
main() {
// getter
print(field); // ref-nq
print(this.field); // ref-q
field(); // inv-nq
this.field(); // inv-q
// setter
field = 2; // ref-nq;
this.field = 3; // ref-q;
}
}
''');
FieldElement element = findElement('field', ElementKind.FIELD);
Element main = findElement('main');
var expected = [
_expectId(main, MatchKind.READ, 'field); // ref-nq'),
_expectIdQ(main, MatchKind.READ, 'field); // ref-q'),
_expectId(main, MatchKind.INVOCATION, 'field(); // inv-nq'),
_expectIdQ(main, MatchKind.INVOCATION, 'field(); // inv-q'),
_expectId(main, MatchKind.WRITE, 'field = 2; // ref-nq'),
_expectIdQ(main, MatchKind.WRITE, 'field = 3; // ref-q'),
];
await _verifyReferences(element, expected);
}
test_searchReferences_FunctionElement() async {
_indexTestUnit('''
test() {}
@@ -311,7 +341,8 @@ main() {
test_searchReferences_ImportElement_noPrefix() async {
_indexTestUnit('''
import 'dart:math';
import 'dart:math' show max, PI, Random hide min;
export 'dart:math' show max, PI, Random hide min;
main() {
print(PI);
print(new Random());
@@ -334,7 +365,8 @@ Random bar() => null;
test_searchReferences_ImportElement_withPrefix() async {
_indexTestUnit('''
import 'dart:math' as math;
import 'dart:math' as math show max, PI, Random hide min;
export 'dart:math' show max, PI, Random hide min;
main() {
print(math.PI);
print(new math.Random());
@@ -712,11 +744,6 @@ class NoMatchABCDE {}
return _expectId(element, kind, search, isQualified: true, length: length);
}
// ExpectedMatch _expectIdU(Element element, MatchKind kind, String search) {
// return _expectId(element, kind, search,
// isQualified: true, isResolved: false);
// }
void _indexTestUnit(String code) {
resolveTestUnit(code);
index.indexUnit(testUnit);
@@ -726,6 +753,7 @@ class NoMatchABCDE {}
Element element, List<ExpectedMatch> expectedMatches) async {
List<SearchMatch> matches = await searchEngine.searchReferences(element);
_assertMatches(matches, expectedMatches);
expect(matches, hasLength(expectedMatches.length));
}
static void _assertMatches(
+1 -1
View File
@@ -574,7 +574,7 @@ class _IndexContributor extends GeneralizingAstVisitor {
recordRelationOffset(
element, IndexRelationKind.IS_REFERENCED_BY, offset, 0, true);
}
super.visitSuperConstructorInvocation(node);
node.argumentList?.accept(this);
}
@override
@@ -41,7 +41,8 @@ class PackageIndexAssemblerTest extends AbstractSingleUnitTest {
UnitIndex unitIndex;
_ElementIndexAssert assertThat(Element element) {
return new _ElementIndexAssert(this, element);
List<_Relation> relations = _getElementRelations(element);
return new _ElementIndexAssert(this, element, relations);
}
_NameIndexAssert assertThatName(String name) {
@@ -560,10 +561,12 @@ main() {
ConstructorElement constA_foo = classA.constructors[1];
// A()
assertThat(constA)
..hasRelationCount(2)
..isReferencedAt('(); // 1', true, length: 0)
..isReferencedAt('(); // 4', true, length: 0);
// A.foo()
assertThat(constA_foo)
..hasRelationCount(3)
..isReferencedAt('.foo(); // 2', true, length: 4)
..isReferencedAt('.foo; // 3', true, length: 4)
..isReferencedAt('.foo(); // 5', true, length: 4);
@@ -856,16 +859,14 @@ main(C c) {
*/
void _assertHasRelation(
Element element,
List<_Relation> relations,
IndexRelationKind expectedRelationKind,
ExpectedLocation expectedLocation) {
int elementId = _findElementId(element);
for (int i = 0; i < unitIndex.usedElementOffsets.length; i++) {
if (unitIndex.usedElements[i] == elementId &&
unitIndex.usedElementKinds[i] == expectedRelationKind &&
unitIndex.usedElementOffsets[i] == expectedLocation.offset &&
unitIndex.usedElementLengths[i] == expectedLocation.length &&
unitIndex.usedElementIsQualifiedFlags[i] ==
expectedLocation.isQualified) {
for (var relation in relations) {
if (relation.kind == expectedRelationKind &&
relation.offset == expectedLocation.offset &&
relation.length == expectedLocation.length &&
relation.isQualified == expectedLocation.isQualified) {
return;
}
}
@@ -926,6 +927,24 @@ main(C c) {
return 0;
}
/**
* Return all relations with [element] in [unitIndex].
*/
List<_Relation> _getElementRelations(Element element) {
int elementId = _findElementId(element);
List<_Relation> relations = <_Relation>[];
for (int i = 0; i < unitIndex.usedElementOffsets.length; i++) {
if (unitIndex.usedElements[i] == elementId) {
relations.add(new _Relation(
unitIndex.usedElementKinds[i],
unitIndex.usedElementOffsets[i],
unitIndex.usedElementLengths[i],
unitIndex.usedElementIsQualifiedFlags[i]));
}
}
return relations;
}
int _getStringId(String str) {
int id = packageIndex.strings.indexOf(str);
expect(id, isNonNegative);
@@ -972,36 +991,56 @@ main(C c) {
class _ElementIndexAssert {
final PackageIndexAssemblerTest test;
final Element element;
final List<_Relation> relations;
_ElementIndexAssert(this.test, this.element);
_ElementIndexAssert(this.test, this.element, this.relations);
void hasRelationCount(int expectedCount) {
expect(relations, hasLength(expectedCount));
}
void isAncestorOf(String search, {int length}) {
test._assertHasRelation(element, IndexRelationKind.IS_ANCESTOR_OF,
test._assertHasRelation(
element,
relations,
IndexRelationKind.IS_ANCESTOR_OF,
test._expectedLocation(search, false, length: length));
}
void isExtendedAt(String search, bool isQualified, {int length}) {
test._assertHasRelation(element, IndexRelationKind.IS_EXTENDED_BY,
test._assertHasRelation(
element,
relations,
IndexRelationKind.IS_EXTENDED_BY,
test._expectedLocation(search, isQualified, length: length));
}
void isImplementedAt(String search, bool isQualified, {int length}) {
test._assertHasRelation(element, IndexRelationKind.IS_IMPLEMENTED_BY,
test._assertHasRelation(
element,
relations,
IndexRelationKind.IS_IMPLEMENTED_BY,
test._expectedLocation(search, isQualified, length: length));
}
void isInvokedAt(String search, bool isQualified, {int length}) {
test._assertHasRelation(element, IndexRelationKind.IS_INVOKED_BY,
test._assertHasRelation(element, relations, IndexRelationKind.IS_INVOKED_BY,
test._expectedLocation(search, isQualified, length: length));
}
void isMixedInAt(String search, bool isQualified, {int length}) {
test._assertHasRelation(element, IndexRelationKind.IS_MIXED_IN_BY,
test._assertHasRelation(
element,
relations,
IndexRelationKind.IS_MIXED_IN_BY,
test._expectedLocation(search, isQualified, length: length));
}
void isReferencedAt(String search, bool isQualified, {int length}) {
test._assertHasRelation(element, IndexRelationKind.IS_REFERENCED_BY,
test._assertHasRelation(
element,
relations,
IndexRelationKind.IS_REFERENCED_BY,
test._expectedLocation(search, isQualified, length: length));
}
}
@@ -1032,3 +1071,18 @@ class _NameIndexAssert {
test._expectedLocation(search, true, length: length), false);
}
}
class _Relation {
final IndexRelationKind kind;
final int offset;
final int length;
final bool isQualified;
_Relation(this.kind, this.offset, this.length, this.isQualified);
@override
String toString() {
return '_Relation{kind: $kind, offset: $offset, length: $length, '
'isQualified: $isQualified}';
}
}