Implement SearchEngine.searchTopLevelDeclarations() for the new driver.

R=brianwilkerson@google.com
BUG=

Review-Url: https://codereview.chromium.org/2572603003 .
This commit is contained in:
Konstantin Shcheglov 2016-12-13 12:11:22 -08:00
parent 5ad638c9d3
commit 142473b8cb
4 changed files with 134 additions and 27 deletions

View file

@ -66,8 +66,24 @@ class SearchEngineImpl2 implements SearchEngine {
@override
Future<List<SearchMatch>> searchTopLevelDeclarations(String pattern) async {
// TODO(scheglov) implement
return [];
List<SearchMatch> allDeclarations = [];
RegExp regExp = new RegExp(pattern);
for (AnalysisDriver driver in _drivers) {
List<Element> elements = await driver.search.topLevelElements(regExp);
for (Element element in elements) {
allDeclarations.add(new _SearchMatch(
element.source.fullName,
element.librarySource,
element.source,
element.library,
element,
true,
true,
MatchKind.DECLARATION,
new SourceRange(element.nameOffset, element.nameLength)));
}
}
return allDeclarations;
}
Future<List<SearchResult>> _searchDirectSubtypes(ClassElement type) async {

View file

@ -2,6 +2,8 @@
// 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 'dart:async';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/services/search/search_engine_internal2.dart';
import 'package:analyzer/dart/element/element.dart';
@ -138,6 +140,51 @@ T b;
matches, contains(predicate((SearchMatch m) => m.element.name == 'b')));
}
test_searchTopLevelDeclarations() async {
var a = _p('/test/a.dart');
var b = _p('/test/b.dart');
provider.newFile(
a,
'''
class A {}
int a;
''');
provider.newFile(
b,
'''
class B {}
get b => 42;
''');
var driver1 = _newDriver();
var driver2 = _newDriver();
driver1.addFile(a);
driver2.addFile(b);
while (scheduler.isAnalyzing) {
await new Future.delayed(new Duration(milliseconds: 1));
}
var searchEngine = new SearchEngineImpl2([driver1, driver2]);
List<SearchMatch> matches =
await searchEngine.searchTopLevelDeclarations('.*');
expect(matches, hasLength(4));
void assertHasElement(String name) {
expect(
matches,
contains(predicate((SearchMatch m) =>
m.kind == MatchKind.DECLARATION && m.element.name == name)));
}
assertHasElement('A');
assertHasElement('a');
assertHasElement('B');
assertHasElement('b');
}
AnalysisDriver _newDriver() => new AnalysisDriver(
scheduler,
logger,

View file

@ -91,6 +91,31 @@ class Search {
return results;
}
/**
* Returns top-level elements with names matching the given [regExp].
*/
Future<List<Element>> topLevelElements(RegExp regExp) async {
List<Element> elements = <Element>[];
void addElement(Element element) {
if (!element.isSynthetic && regExp.hasMatch(element.displayName)) {
elements.add(element);
}
}
for (FileState file in _driver.fsState.knownFiles) {
CompilationUnitElement unitElement =
await _driver.getUnitElement(file.path);
unitElement.accessors.forEach(addElement);
unitElement.enums.forEach(addElement);
unitElement.functions.forEach(addElement);
unitElement.functionTypeAliases.forEach(addElement);
unitElement.topLevelVariables.forEach(addElement);
unitElement.types.forEach(addElement);
}
return elements;
}
Future<Null> _addResults(List<SearchResult> results, Element element,
Map<IndexRelationKind, SearchResultKind> relationToResultKind) async {
// Prepare the element name.

View file

@ -528,6 +528,31 @@ main(A<int> a) {
await _verifyReferences(method, expected);
}
test_searchReferences_ParameterElement_named() async {
await _resolveTestUnit('''
foo({p}) {
p = 1;
p += 2;
print(p);
p();
}
main() {
foo(p: 42);
}
''');
ParameterElement element = _findElement('p');
Element fooElement = _findElement('foo');
Element mainElement = _findElement('main');
var expected = [
_expectId(fooElement, SearchResultKind.WRITE, 'p = 1;'),
_expectId(fooElement, SearchResultKind.READ_WRITE, 'p += 2;'),
_expectId(fooElement, SearchResultKind.READ, 'p);'),
_expectId(fooElement, SearchResultKind.INVOCATION, 'p();'),
_expectIdQ(mainElement, SearchResultKind.REFERENCE, 'p: 42')
];
await _verifyReferences(element, expected);
}
test_searchReferences_ParameterElement_ofConstructor() async {
await _resolveTestUnit('''
class C {
@ -627,31 +652,6 @@ main() {
await _verifyReferences(element, expected);
}
test_searchReferences_ParameterElement_named() async {
await _resolveTestUnit('''
foo({p}) {
p = 1;
p += 2;
print(p);
p();
}
main() {
foo(p: 42);
}
''');
ParameterElement element = _findElement('p');
Element fooElement = _findElement('foo');
Element mainElement = _findElement('main');
var expected = [
_expectId(fooElement, SearchResultKind.WRITE, 'p = 1;'),
_expectId(fooElement, SearchResultKind.READ_WRITE, 'p += 2;'),
_expectId(fooElement, SearchResultKind.READ, 'p);'),
_expectId(fooElement, SearchResultKind.INVOCATION, 'p();'),
_expectIdQ(mainElement, SearchResultKind.REFERENCE, 'p: 42')
];
await _verifyReferences(element, expected);
}
test_searchReferences_PrefixElement() async {
String partCode = r'''
part of my_lib;
@ -924,6 +924,25 @@ class C implements T {} // C
await _verifyReferences(element, expected);
}
test_topLevelElements() async {
await _resolveTestUnit('''
class A {} // A
class B = Object with A;
typedef C();
D() {}
var E = null;
class NoMatchABCDE {}
''');
Element a = _findElement('A');
Element b = _findElement('B');
Element c = _findElement('C');
Element d = _findElement('D');
Element e = _findElement('E');
RegExp regExp = new RegExp(r'^[A-E]$');
expect(await driver.search.topLevelElements(regExp),
unorderedEquals([a, b, c, d, e]));
}
ExpectedResult _expectId(
Element enclosingElement, SearchResultKind kind, String search,
{int length, bool isResolved: true, bool isQualified: false}) {