Search for element declarations in discovered available files.
R=brianwilkerson@google.com
Change-Id: Idb8d4528aa1edffe60db63067e3d42fd89058b6b
Reviewed-on: https://dart-review.googlesource.com/57700
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/lib/src/search/search_domain.dart b/pkg/analysis_server/lib/src/search/search_domain.dart
index d3ffa60..ab94d11 100644
--- a/pkg/analysis_server/lib/src/search/search_domain.dart
+++ b/pkg/analysis_server/lib/src/search/search_domain.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
+import 'dart:collection';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/src/analysis_server.dart';
@@ -144,7 +145,7 @@
}
}
- var files = <String>[];
+ var files = new LinkedHashSet<String>();
var declarations = <search.Declaration>[];
protocol.ElementKind getElementKind(search.DeclarationKind kind) {
@@ -209,7 +210,7 @@
}).toList();
server.sendResponse(new protocol.SearchGetElementDeclarationsResult(
- elementDeclarations, files)
+ elementDeclarations, files.toList())
.toResponse(request.id));
}
diff --git a/pkg/analysis_server/test/search/declarations_test.dart b/pkg/analysis_server/test/search/declarations_test.dart
index 71bf567..ab58b70 100644
--- a/pkg/analysis_server/test/search/declarations_test.dart
+++ b/pkg/analysis_server/test/search/declarations_test.dart
@@ -85,15 +85,15 @@
''').path;
// Limit to exactly one file.
- await _getDeclarations(pattern: r'[A-D]', maxResults: 2);
+ await _getDeclarations(pattern: r'^[A-D]$', maxResults: 2);
expect(declarationsResult.declarations, hasLength(2));
// Limit in the middle of the second file.
- await _getDeclarations(pattern: r'[A-D]', maxResults: 3);
+ await _getDeclarations(pattern: r'^[A-D]$', maxResults: 3);
expect(declarationsResult.declarations, hasLength(3));
// No limit.
- await _getDeclarations(pattern: r'[A-D]');
+ await _getDeclarations(pattern: r'^[A-D]$');
expect(declarationsResult.declarations, hasLength(4));
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 23139b8..e4640fb 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -599,6 +599,15 @@
_createKernelDriver();
}
+ /**
+ * Return a [Future] that completes when discovery of all files that are
+ * potentially available is done, so that they are included in [knownFiles].
+ */
+ Future<void> discoverAvailableFiles() {
+ _discoverAvailableFiles();
+ return _discoverAvailableFilesTask.completer.future;
+ }
+
@override
void dispose() {
_scheduler.remove(this);
@@ -2259,6 +2268,7 @@
static const int _MS_WORK_INTERVAL = 5;
final AnalysisDriver driver;
+ final Completer<void> completer = new Completer<void>();
bool isCompleted = false;
@@ -2309,6 +2319,7 @@
isCompleted = true;
folderIterator = null;
files = null;
+ completer.complete();
}
void _appendFilesRecursively(Folder folder) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index a54df1f..1307034 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
+import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
@@ -113,11 +114,9 @@
* declarations.
*
* The path of each file with at least one declaration is added to [files].
- * The list is for searched, there might be duplicates, but this is OK,
- * we just want reduce amount of data, not to make it absolute minimum.
*/
Future<List<Declaration>> declarations(
- RegExp regExp, int maxResults, List<String> files,
+ RegExp regExp, int maxResults, LinkedHashSet<String> files,
{String onlyForFile}) async {
List<Declaration> declarations = <Declaration>[];
@@ -139,11 +138,19 @@
}
}
+ for (String path in _driver.addedFiles) {
+ _driver.fsState.getFileForPath(path);
+ }
+ await _driver.discoverAvailableFiles();
+
try {
- for (String path in _driver.addedFiles) {
+ for (String path in _driver.knownFiles) {
if (onlyForFile != null && path != onlyForFile) {
continue;
}
+ if (files.contains(path)) {
+ continue;
+ }
FileState file = _driver.fsState.getFileForPath(path);
int fileIndex;
@@ -166,6 +173,7 @@
fileIndex = files.length;
files.add(file.path);
}
+
var location = file.lineInfo.getLocation(offset);
declarations.add(new Declaration(
fileIndex,
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index cb583d2..d3cfbf9 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -1107,6 +1107,35 @@
expect(session2, isNot(session1));
}
+ test_discoverAvailableFiles() async {
+ var t = _p('/test/lib/test.dart');
+ var a1 = _p('/aaa/lib/a1.dart');
+ var a2 = _p('/aaa/lib/src/a2.dart');
+ var b = _p('/bbb/lib/b.dart');
+ var c = _p('/ccc/lib/c.dart');
+
+ provider.newFile(t, 'class T {}');
+ provider.newFile(a1, 'class A1 {}');
+ provider.newFile(a2, 'class A2 {}');
+ provider.newFile(b, 'class B {}');
+ provider.newFile(c, 'class C {}');
+
+ driver.addFile(t);
+ // Don't add a1.dart, a2.dart, or b.dart - they should be discovered.
+ // And c.dart is not in .packages, so should not be discovered.
+
+ await driver.discoverAvailableFiles();
+
+ expect(driver.knownFiles, contains(t));
+ expect(driver.knownFiles, contains(a1));
+ expect(driver.knownFiles, contains(a2));
+ expect(driver.knownFiles, contains(b));
+ expect(driver.knownFiles, isNot(contains(c)));
+
+ // We call wait for discovery more than once.
+ await driver.discoverAvailableFiles();
+ }
+
test_errors_uriDoesNotExist_export() async {
addTestFile(r'''
export 'foo.dart';
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index 52cadae..45c3fbd 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
+import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart' hide Declaration;
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
@@ -109,7 +110,7 @@
void m() {}
}
''');
- var files = <String>[];
+ var files = new LinkedHashSet<String>();
List<Declaration> declarations =
await driver.search.declarations(null, null, files);
_assertHasDeclaration(declarations, 'C', DeclarationKind.CLASS,
@@ -128,13 +129,52 @@
offset: 83, codeOffset: 78, codeLength: 11, className: 'C');
}
+ test_declarations_discoverAvailable() async {
+ var t = _p('/test/lib/t.dart');
+ var a = _p('/aaa/lib/a.dart');
+ var b = _p('/bbb/lib/b.dart');
+ var c = _p('/ccc/lib/c.dart');
+
+ provider.newFile(t, 'class T {}');
+ provider.newFile(a, 'class A {}');
+ provider.newFile(b, 'class B {}');
+ provider.newFile(c, 'class C {}');
+
+ driver.addFile(t);
+
+ var files = new LinkedHashSet<String>();
+ var declarations = await driver.search.declarations(null, null, files);
+ _assertHasDeclaration(declarations, 'T', DeclarationKind.CLASS);
+ _assertHasDeclaration(declarations, 'A', DeclarationKind.CLASS);
+ _assertHasDeclaration(declarations, 'B', DeclarationKind.CLASS);
+ _assertNoDeclaration(declarations, 'C');
+ }
+
+ test_declarations_duplicateFile() async {
+ var a = _p('/test/lib/a.dart');
+ var b = _p('/test/lib/b.dart');
+
+ provider.newFile(a, 'class A {}');
+ provider.newFile(b, 'class B {}');
+
+ driver.addFile(a);
+ driver.addFile(b);
+
+ var files = new LinkedHashSet<String>();
+ files.add(b);
+
+ var declarations = await driver.search.declarations(null, null, files);
+ _assertHasDeclaration(declarations, 'A', DeclarationKind.CLASS);
+ _assertNoDeclaration(declarations, 'B');
+ }
+
test_declarations_enum() async {
await _resolveTestUnit('''
enum E {
a, bb, ccc
}
''');
- var files = <String>[];
+ var files = new LinkedHashSet<String>();
List<Declaration> declarations =
await driver.search.declarations(null, null, files);
_assertHasDeclaration(declarations, 'E', DeclarationKind.ENUM,
@@ -153,7 +193,7 @@
class B {}
class C {}
''');
- var files = <String>[];
+ var files = new LinkedHashSet<String>();
List<Declaration> declarations =
await driver.search.declarations(null, 2, files);
expect(declarations, hasLength(2));
@@ -168,7 +208,7 @@
driver.addFile(a);
driver.addFile(b);
- var files = <String>[];
+ var files = new LinkedHashSet<String>();
List<Declaration> declarations =
await driver.search.declarations(null, null, files, onlyForFile: b);
@@ -188,7 +228,7 @@
typedef F(int a);
typedef T F2<T, U>(U a);
''');
- var files = <String>[];
+ var files = new LinkedHashSet<String>();
List<Declaration> declarations =
await driver.search.declarations(null, null, files);
@@ -228,7 +268,7 @@
void f3(bool Function(int a, String b) c) {}
void f4(bool Function(int, String) a) {}
''');
- var files = <String>[];
+ var files = new LinkedHashSet<String>();
List<Declaration> declarations =
await driver.search.declarations(null, null, files);
@@ -259,7 +299,7 @@
void m3<U1, U2>(Map<Map<T2, U2>, Map<U1, T>> a) {}
}
''');
- var files = <String>[];
+ var files = new LinkedHashSet<String>();
List<Declaration> declarations =
await driver.search.declarations(null, null, files);
@@ -288,7 +328,7 @@
class C {}
class D {}
''');
- var files = <String>[];
+ var files = new LinkedHashSet<String>();
List<Declaration> declarations =
await driver.search.declarations(new RegExp(r'[A-C]'), null, files);
_assertHasDeclaration(declarations, 'A', DeclarationKind.CLASS);
@@ -306,7 +346,7 @@
typedef void tf1();
typedef tf2<T> = int Function<S>(T tp, S sp);
''');
- var files = <String>[];
+ var files = new LinkedHashSet<String>();
List<Declaration> declarations =
await driver.search.declarations(null, null, files);
_assertHasDeclaration(declarations, 'g', DeclarationKind.GETTER,