Implement changeFile() and recompute available libraries and declarations.
Some renames in tests.
R=brianwilkerson@google.com
Change-Id: Ia54752c816bbc62f99a200d62658b6f4dfb26480
Reviewed-on: https://dart-review.googlesource.com/c/91381
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index 268c8dd..fd417fc 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -339,6 +339,9 @@
final _changesController = _StreamController<LibraryChange>();
+ /// The list of changed file paths.
+ final List<String> _changedPaths = [];
+
/// The list of files scheduled for processing. It may include parts and
/// libraries, but parts are ignored when we detect them.
final List<_ScheduledFile> _scheduledFiles = [];
@@ -350,7 +353,9 @@
/// Return `true` if there is scheduled work to do, as a result of adding
/// new contexts, or changes to files.
- bool get hasWork => _scheduledFiles.isNotEmpty;
+ bool get hasWork {
+ return _changedPaths.isNotEmpty || _scheduledFiles.isNotEmpty;
+ }
/// Add the [analysisContext], so that its libraries are reported via the
/// [changes] stream, and return the [DeclarationsContext] that can be used
@@ -370,7 +375,7 @@
return declarationsContext;
}
- /// The file with the given [path] was changed - updated or added.
+ /// The file with the given [path] was changed - added, updated, or removed.
///
/// The [path] must be absolute and normalized.
///
@@ -378,7 +383,7 @@
/// be invoked to send updates to [changes] that reflect changes to the
/// library of the file, and other libraries that export it.
void changeFile(String path) {
- // TODO(scheglov) implement
+ _changedPaths.add(path);
}
/// Do a single piece of work.
@@ -387,28 +392,34 @@
/// This would mean that all previous changes have been processed, and
/// updates scheduled to be delivered via the [changes] stream.
void doWork() {
- if (_scheduledFiles.isEmpty) return;
-
- var scheduledFile = _scheduledFiles.removeLast();
- var file = _getFileByPath(scheduledFile.context, scheduledFile.path);
-
- if (!file.isLibrary) return;
-
- if (file.exportedDeclarations == null) {
- new _LibraryWalker().walkLibrary(file);
- assert(file.exportedDeclarations != null);
+ if (_changedPaths.isNotEmpty) {
+ var path = _changedPaths.removeLast();
+ _performChangeFile(path);
+ return;
}
- var library = Library._(
- file.id,
- file.path,
- file.uri,
- file.exportedDeclarations,
- );
- _idToLibrary[file.id] = library;
- _changesController.add(
- LibraryChange._([library], []),
- );
+ if (_scheduledFiles.isNotEmpty) {
+ var scheduledFile = _scheduledFiles.removeLast();
+ var file = _getFileByPath(scheduledFile.context, scheduledFile.path);
+
+ if (!file.isLibrary) return;
+
+ if (file.exportedDeclarations == null) {
+ new _LibraryWalker().walkLibrary(file);
+ assert(file.exportedDeclarations != null);
+ }
+
+ var library = Library._(
+ file.id,
+ file.path,
+ file.uri,
+ file.exportedDeclarations,
+ );
+ _idToLibrary[file.id] = library;
+ _changesController.add(
+ LibraryChange._([library], []),
+ );
+ }
}
/// The [analysisContext] is being disposed, it does not need declarations.
@@ -420,23 +431,23 @@
});
}
- /// The file with the given [path] was removed.
- ///
- /// The [path] must be absolute and normalized.
- ///
- /// Usually causes [hasWork] to return `true`, so that [doWork] should
- /// be invoked to send updates to [changes] that reflect removing of the
- /// file, its defining library, other libraries that export it.
- void removeFile(String path) {
- // TODO(scheglov) implement
- }
-
void _addFile(DeclarationsContext context, String path) {
if (path.endsWith('.dart')) {
_scheduledFiles.add(_ScheduledFile(context, path));
}
}
+ /// Compute exported declarations for the given [libraries].
+ void _computeExportedDeclarations(Set<_File> libraries) {
+ var walker = new _LibraryWalker();
+ for (var library in libraries) {
+ if (library.isLibrary && library.exportedDeclarations == null) {
+ walker.walkLibrary(library);
+ assert(library.exportedDeclarations != null);
+ }
+ }
+ }
+
_File _getFileByPath(DeclarationsContext context, String path) {
var file = _pathToFile[path];
if (file == null) {
@@ -464,6 +475,64 @@
}
return file;
}
+
+ /// Recursively invalidate exported declarations of the given [library]
+ /// and libraries that export it.
+ void _invalidateExportedDeclarations(Set<_File> libraries, _File library) {
+ if (libraries.add(library)) {
+ library.exportedDeclarations = null;
+ for (var exporter in library.directExporters) {
+ _invalidateExportedDeclarations(libraries, exporter);
+ }
+ }
+ }
+
+ void _performChangeFile(String path) {
+ DeclarationsContext containingContext;
+ for (var context in _contexts.values) {
+ var uri = context._restoreUri(path);
+ if (uri != null) {
+ containingContext = context;
+ break;
+ }
+ }
+ if (containingContext == null) return;
+
+ var file = _getFileByPath(containingContext, path);
+ if (file == null) return;
+
+ var isLibrary = file.isLibrary;
+ var library = isLibrary ? file : file.library;
+
+ if (isLibrary) {
+ file.refresh(containingContext);
+ } else {
+ file.refresh(containingContext);
+ library.refresh(containingContext);
+ }
+
+ var invalidatedLibraries = Set<_File>();
+ _invalidateExportedDeclarations(invalidatedLibraries, library);
+ _computeExportedDeclarations(invalidatedLibraries);
+
+ var changedLibraries = <Library>[];
+ var removedLibraries = <int>[];
+ for (var library in invalidatedLibraries) {
+ if (library.exists) {
+ changedLibraries.add(Library._(
+ library.id,
+ library.path,
+ library.uri,
+ library.exportedDeclarations,
+ ));
+ } else {
+ removedLibraries.add(library.id);
+ }
+ }
+ _changesController.add(
+ LibraryChange._(changedLibraries, removedLibraries),
+ );
+ }
}
class Libraries {
@@ -552,10 +621,17 @@
final String path;
final Uri uri;
+ bool exists = false;
bool isLibrary = false;
List<_Export> exports = [];
List<_Part> parts = [];
+ /// If this file is a part, the containing library.
+ _File library;
+
+ /// If this file is a library, libraries that export it.
+ List<_File> directExporters = [];
+
List<Declaration> fileDeclarations = [];
List<Declaration> libraryDeclarations = [];
List<Declaration> exportedDeclarations;
@@ -568,8 +644,10 @@
int modificationStamp;
try {
modificationStamp = resource.modificationStamp;
+ exists = true;
} catch (e) {
modificationStamp = -1;
+ exists = false;
}
// When a file changes, its modification stamp changes.
@@ -624,6 +702,15 @@
exports.removeWhere((e) => e.file == null);
parts.removeWhere((e) => e.file == null);
+ // Set back pointers.
+ for (var export in exports) {
+ export.file.directExporters.add(this);
+ }
+ for (var part in parts) {
+ part.file.library = this;
+ part.file.isLibrary = false;
+ }
+
// Compute library declarations.
if (isLibrary) {
libraryDeclarations = <Declaration>[];
diff --git a/pkg/analyzer/test/src/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index 83d627d..8d2834a 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -100,6 +100,384 @@
_createTracker();
}
+ test_changeFile_added_exported() async {
+ var a = convertPath('/home/test/lib/a.dart');
+ var b = convertPath('/home/test/lib/b.dart');
+ var c = convertPath('/home/test/lib/c.dart');
+ var d = convertPath('/home/test/lib/d.dart');
+
+ newFile(a, content: r'''
+export 'b.dart';
+class A {}
+''');
+ newFile(b, content: r'''
+export 'c.dart';
+class B {}
+''');
+ newFile(d, content: r'''
+class D {}
+''');
+ tracker.addContext(testAnalysisContext);
+
+ await _doAllTrackerWork();
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/b.dart', declarations: [
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ ]);
+ _assertHasNoLibrary('package:test/c.dart');
+ _assertHasLibrary('package:test/d.dart', declarations: [
+ _ExpectedDeclaration('D', DeclarationKind.CLASS),
+ ]);
+
+ newFile(c, content: r'''
+class C {}
+''');
+ tracker.changeFile(c);
+ await _doAllTrackerWork();
+
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/b.dart', declarations: [
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/c.dart', declarations: [
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/d.dart', declarations: [
+ _ExpectedDeclaration('D', DeclarationKind.CLASS),
+ ]);
+ }
+
+ test_changeFile_added_library() async {
+ var a = convertPath('/home/test/lib/a.dart');
+ var b = convertPath('/home/test/lib/b.dart');
+
+ newFile(a, content: r'''
+class A {}
+''');
+ tracker.addContext(testAnalysisContext);
+
+ await _doAllTrackerWork();
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ ]);
+ _assertHasNoLibrary('package:test/b.dart');
+
+ newFile(b, content: r'''
+class B {}
+''');
+ tracker.changeFile(b);
+ await _doAllTrackerWork();
+
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/b.dart', declarations: [
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ ]);
+ }
+
+ test_changeFile_added_part() async {
+ var a = convertPath('/home/test/lib/a.dart');
+ var b = convertPath('/home/test/lib/b.dart');
+ var c = convertPath('/home/test/lib/c.dart');
+
+ newFile(a, content: r'''
+part 'b.dart';
+class A {}
+''');
+ newFile(c, content: r'''
+class C {}
+''');
+ tracker.addContext(testAnalysisContext);
+
+ await _doAllTrackerWork();
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ ]);
+ _assertHasNoLibrary('package:test/b.dart');
+ _assertHasLibrary('package:test/c.dart', declarations: [
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+
+ newFile(b, content: r'''
+part of 'a.dart';
+class B {}
+''');
+ tracker.changeFile(b);
+ await _doAllTrackerWork();
+
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ ]);
+ _assertHasNoLibrary('package:test/b.dart');
+ _assertHasLibrary('package:test/c.dart', declarations: [
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+ }
+
+ test_changeFile_deleted_exported() async {
+ var a = convertPath('/home/test/lib/a.dart');
+ var b = convertPath('/home/test/lib/b.dart');
+ var c = convertPath('/home/test/lib/c.dart');
+ var d = convertPath('/home/test/lib/d.dart');
+
+ newFile(a, content: r'''
+export 'b.dart';
+class A {}
+''');
+ newFile(b, content: r'''
+export 'c.dart';
+class B {}
+''');
+ newFile(c, content: r'''
+class C {}
+''');
+ newFile(d, content: r'''
+class D {}
+''');
+ tracker.addContext(testAnalysisContext);
+
+ await _doAllTrackerWork();
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/b.dart', declarations: [
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/c.dart', declarations: [
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/d.dart', declarations: [
+ _ExpectedDeclaration('D', DeclarationKind.CLASS),
+ ]);
+
+ deleteFile(c);
+ tracker.changeFile(c);
+ await _doAllTrackerWork();
+
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/b.dart', declarations: [
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ ]);
+ _assertHasNoLibrary('package:test/c.dart');
+ _assertHasLibrary('package:test/d.dart', declarations: [
+ _ExpectedDeclaration('D', DeclarationKind.CLASS),
+ ]);
+ }
+
+ test_changeFile_deleted_library() async {
+ var a = convertPath('/home/test/lib/a.dart');
+ var b = convertPath('/home/test/lib/b.dart');
+
+ newFile(a, content: '');
+ newFile(b, content: '');
+ tracker.addContext(testAnalysisContext);
+
+ await _doAllTrackerWork();
+ _assertHasLibrary('package:test/a.dart');
+ _assertHasLibrary('package:test/b.dart');
+
+ deleteFile(a);
+ tracker.changeFile(a);
+ await _doAllTrackerWork();
+
+ _assertHasNoLibrary('package:test/a.dart');
+ _assertHasLibrary('package:test/b.dart');
+ }
+
+ test_changeFile_deleted_part() async {
+ var a = convertPath('/home/test/lib/a.dart');
+ var b = convertPath('/home/test/lib/b.dart');
+ var c = convertPath('/home/test/lib/c.dart');
+
+ newFile(a, content: r'''
+part 'b.dart';
+class A {}
+''');
+ newFile(b, content: r'''
+part of 'a.dart';
+class B {}
+''');
+ newFile(c, content: r'''
+class C {}
+''');
+ tracker.addContext(testAnalysisContext);
+
+ await _doAllTrackerWork();
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/c.dart', declarations: [
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+
+ deleteFile(b);
+ tracker.changeFile(b);
+ await _doAllTrackerWork();
+
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/c.dart', declarations: [
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+ }
+
+ test_changeFile_updated_exported() async {
+ var a = convertPath('/home/test/lib/a.dart');
+ var b = convertPath('/home/test/lib/b.dart');
+ var c = convertPath('/home/test/lib/c.dart');
+ var d = convertPath('/home/test/lib/d.dart');
+
+ newFile(a, content: r'''
+export 'b.dart';
+class A {}
+''');
+ newFile(b, content: r'''
+export 'c.dart';
+class B {}
+''');
+ newFile(c, content: r'''
+class C {}
+''');
+ newFile(d, content: r'''
+class D {}
+''');
+ tracker.addContext(testAnalysisContext);
+
+ await _doAllTrackerWork();
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/b.dart', declarations: [
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/c.dart', declarations: [
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/d.dart', declarations: [
+ _ExpectedDeclaration('D', DeclarationKind.CLASS),
+ ]);
+
+ newFile(c, content: r'''
+class C2 {}
+''');
+ tracker.changeFile(c);
+ await _doAllTrackerWork();
+
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ _ExpectedDeclaration('C2', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/b.dart', declarations: [
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ _ExpectedDeclaration('C2', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/c.dart', declarations: [
+ _ExpectedDeclaration('C2', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/d.dart', declarations: [
+ _ExpectedDeclaration('D', DeclarationKind.CLASS),
+ ]);
+ }
+
+ test_changeFile_updated_library() async {
+ var a = convertPath('/home/test/lib/a.dart');
+ var b = convertPath('/home/test/lib/b.dart');
+
+ newFile(a, content: r'''
+class A {}
+''');
+ newFile(b, content: r'''
+class B {}
+''');
+ tracker.addContext(testAnalysisContext);
+
+ await _doAllTrackerWork();
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/b.dart', declarations: [
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ ]);
+
+ newFile(a, content: r'''
+class A2 {}
+''');
+ tracker.changeFile(a);
+ await _doAllTrackerWork();
+
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A2', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/b.dart', declarations: [
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ ]);
+ }
+
+ test_changeFile_updated_part() async {
+ var a = convertPath('/home/test/lib/a.dart');
+ var b = convertPath('/home/test/lib/b.dart');
+ var c = convertPath('/home/test/lib/c.dart');
+
+ newFile(a, content: r'''
+part 'b.dart';
+class A {}
+''');
+ newFile(b, content: r'''
+part of 'a.dart';
+class B {}
+''');
+ newFile(c, content: r'''
+class C {}
+''');
+ tracker.addContext(testAnalysisContext);
+
+ await _doAllTrackerWork();
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ _ExpectedDeclaration('B', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/c.dart', declarations: [
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+
+ newFile(b, content: r'''
+part of 'a.dart';
+class B2 {}
+''');
+ tracker.changeFile(b);
+ await _doAllTrackerWork();
+
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration('A', DeclarationKind.CLASS),
+ _ExpectedDeclaration('B2', DeclarationKind.CLASS),
+ ]);
+ _assertHasLibrary('package:test/c.dart', declarations: [
+ _ExpectedDeclaration('C', DeclarationKind.CLASS),
+ ]);
+ }
+
test_export() async {
newFile('/home/test/lib/a.dart', content: r'''
class A {}
@@ -112,11 +490,11 @@
tracker.addContext(testAnalysisContext);
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/test.dart', declarations: [
_ExpectedDeclaration.class_('A'),
_ExpectedDeclaration.class_('B'),
_ExpectedDeclaration.class_('C'),
- ], uriStr: 'package:test/test.dart');
+ ]);
}
test_export_combinators_hide() async {
@@ -132,11 +510,11 @@
tracker.addContext(testAnalysisContext);
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/test.dart', declarations: [
_ExpectedDeclaration.class_('A'),
_ExpectedDeclaration.class_('C'),
_ExpectedDeclaration.class_('D'),
- ], uriStr: 'package:test/test.dart');
+ ]);
}
test_export_combinators_show() async {
@@ -152,10 +530,10 @@
tracker.addContext(testAnalysisContext);
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/test.dart', declarations: [
_ExpectedDeclaration.class_('B'),
_ExpectedDeclaration.class_('D'),
- ], uriStr: 'package:test/test.dart');
+ ]);
}
test_export_cycle() async {
@@ -175,21 +553,21 @@
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/a.dart', declarations: [
_ExpectedDeclaration.class_('A'),
_ExpectedDeclaration.class_('B'),
- ], uriStr: 'package:test/a.dart');
+ ]);
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/b.dart', declarations: [
_ExpectedDeclaration.class_('A'),
_ExpectedDeclaration.class_('B'),
- ], uriStr: 'package:test/b.dart');
+ ]);
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/test.dart', declarations: [
_ExpectedDeclaration.class_('A'),
_ExpectedDeclaration.class_('B'),
_ExpectedDeclaration.class_('C'),
- ], uriStr: 'package:test/test.dart');
+ ]);
}
test_export_missing() async {
@@ -200,9 +578,9 @@
tracker.addContext(testAnalysisContext);
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/test.dart', declarations: [
_ExpectedDeclaration.class_('C'),
- ], uriStr: 'package:test/test.dart');
+ ]);
}
test_export_sequence() async {
@@ -221,20 +599,20 @@
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/a.dart', declarations: [
_ExpectedDeclaration.class_('A'),
- ], uriStr: 'package:test/a.dart');
+ ]);
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/b.dart', declarations: [
_ExpectedDeclaration.class_('A'),
_ExpectedDeclaration.class_('B'),
- ], uriStr: 'package:test/b.dart');
+ ]);
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/test.dart', declarations: [
_ExpectedDeclaration.class_('A'),
_ExpectedDeclaration.class_('B'),
_ExpectedDeclaration.class_('C'),
- ], uriStr: 'package:test/test.dart');
+ ]);
}
test_export_shadowedByLocal() async {
@@ -250,10 +628,10 @@
tracker.addContext(testAnalysisContext);
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/test.dart', declarations: [
_ExpectedDeclaration.class_('A'),
_ExpectedDeclaration.mixin('B'),
- ], uriStr: 'package:test/test.dart');
+ ]);
}
test_getLibraries_bazel() async {
@@ -306,25 +684,31 @@
});
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:aaa/a.dart', declarations: [
_ExpectedDeclaration.class_('A'),
- ], uriStr: 'package:aaa/a.dart');
- _assertNoLibrary('package:aaa/src/a2.dart');
+ ]);
+ _assertHasNoLibrary('package:aaa/src/a2.dart');
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:bbb/b.dart', declarations: [
_ExpectedDeclaration.class_('B'),
- ], uriStr: 'package:bbb/b.dart');
- _assertNoLibrary('package:bbb/src/b2.dart');
+ ]);
+ _assertHasNoLibrary('package:bbb/src/b2.dart');
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:material_button/button.dart', declarations: [
_ExpectedDeclaration.class_('MaterialButton'),
- ], uriStr: 'package:material_button/button.dart');
- _assertLibraryDeclarations([
- _ExpectedDeclaration.class_('MaterialButtonTest'),
- ], uriStr: toUri('/home/material_button/test/button_test.dart').toString());
- _assertLibraryDeclarations([
- _ExpectedDeclaration.class_('MaterialButtonPO'),
- ], uriStr: 'package:material_button_testing/material_button_po.dart');
+ ]);
+ _assertHasLibrary(
+ toUri('/home/material_button/test/button_test.dart').toString(),
+ declarations: [
+ _ExpectedDeclaration.class_('MaterialButtonTest'),
+ ],
+ );
+ _assertHasLibrary(
+ 'package:material_button_testing/material_button_po.dart',
+ declarations: [
+ _ExpectedDeclaration.class_('MaterialButtonPO'),
+ ],
+ );
{
var path = convertPath('/home/material_button/lib/_.dart');
@@ -432,31 +816,31 @@
var context = tracker.addContext(testAnalysisContext);
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:aaa/a.dart', declarations: [
_ExpectedDeclaration.class_('A'),
- ], uriStr: 'package:aaa/a.dart');
- _assertNoLibrary('package:aaa/src/a2.dart');
+ ]);
+ _assertHasNoLibrary('package:aaa/src/a2.dart');
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:bbb/b.dart', declarations: [
_ExpectedDeclaration.class_('B'),
- ], uriStr: 'package:bbb/b.dart');
- _assertNoLibrary('package:bbb/src/b2.dart');
+ ]);
+ _assertHasNoLibrary('package:bbb/src/b2.dart');
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:ccc/c.dart', declarations: [
_ExpectedDeclaration.class_('C'),
- ], uriStr: 'package:ccc/c.dart');
- _assertNoLibrary('package:ccc/src/c2.dart');
+ ]);
+ _assertHasNoLibrary('package:ccc/src/c2.dart');
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/t.dart', declarations: [
_ExpectedDeclaration.class_('T'),
- ], uriStr: 'package:test/t.dart');
- _assertLibraryDeclarations([
+ ]);
+ _assertHasLibrary('package:test/src/t2.dart', declarations: [
_ExpectedDeclaration.class_('T2'),
- ], uriStr: 'package:test/src/t2.dart');
+ ]);
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:basic/s.dart', declarations: [
_ExpectedDeclaration.class_('S'),
- ], uriStr: 'package:basic/s.dart');
+ ]);
{
var path = convertPath('/home/test/lib/_.dart');
@@ -593,23 +977,26 @@
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:aaa/a.dart', declarations: [
_ExpectedDeclaration.class_('A1'),
_ExpectedDeclaration.class_('A2'),
- ], uriStr: 'package:aaa/a.dart');
- _assertNoLibrary('package:aaa/src/a2.dart');
- _assertLibraryDeclarations([
+ ]);
+ _assertHasNoLibrary('package:aaa/src/a2.dart');
+ _assertHasLibrary('package:bbb/b.dart', declarations: [
_ExpectedDeclaration.class_('B'),
- ], uriStr: 'package:bbb/b.dart');
- _assertLibraryDeclarations([
+ ]);
+ _assertHasLibrary('package:test/t.dart', declarations: [
_ExpectedDeclaration.class_('T'),
- ], uriStr: 'package:test/t.dart');
- _assertLibraryDeclarations([
+ ]);
+ _assertHasLibrary('package:test/src/t2.dart', declarations: [
_ExpectedDeclaration.class_('T2'),
- ], uriStr: 'package:test/src/t2.dart');
- _assertLibraryDeclarations([
- _ExpectedDeclaration.class_('T3'),
- ], uriStr: toUri('/home/test/test/t3.dart').toString());
+ ]);
+ _assertHasLibrary(
+ toUri('/home/test/test/t3.dart').toString(),
+ declarations: [
+ _ExpectedDeclaration.class_('T3'),
+ ],
+ );
// `lib/` is configured to see `package:aaa`.
{
@@ -682,10 +1069,10 @@
});
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary(aUri, declarations: [
_ExpectedDeclaration.class_('A'),
- ], uriStr: aUri);
- _assertNoLibrary(bUri);
+ ]);
+ _assertHasNoLibrary(bUri);
// The package can see package:aaa, but not package:bbb
{
@@ -703,12 +1090,12 @@
});
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary(aUri, declarations: [
_ExpectedDeclaration.class_('A'),
- ], uriStr: aUri);
- _assertLibraryDeclarations([
+ ]);
+ _assertHasLibrary(bUri, declarations: [
_ExpectedDeclaration.class_('B'),
- ], uriStr: bUri);
+ ]);
// The package can see package:bbb, but not package:aaa
{
@@ -735,7 +1122,7 @@
tracker.addContext(testAnalysisContext);
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/test.dart', declarations: [
_ExpectedDeclaration.class_('MyClass'),
_ExpectedDeclaration.classTypeAlias('MyClassTypeAlias'),
_ExpectedDeclaration.enum_('MyEnum'),
@@ -744,7 +1131,7 @@
_ExpectedDeclaration.mixin('MyMixin'),
_ExpectedDeclaration.variable('myVariable1'),
_ExpectedDeclaration.variable('myVariable2'),
- ], uriStr: 'package:test/test.dart');
+ ]);
}
test_parts() async {
@@ -764,11 +1151,11 @@
tracker.addContext(testAnalysisContext);
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/test.dart', declarations: [
_ExpectedDeclaration.class_('A'),
_ExpectedDeclaration.class_('B'),
_ExpectedDeclaration.class_('C'),
- ], uriStr: 'package:test/test.dart');
+ ]);
}
test_publicOnly() async {
@@ -785,10 +1172,10 @@
tracker.addContext(testAnalysisContext);
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/test.dart', declarations: [
_ExpectedDeclaration.class_('A'),
_ExpectedDeclaration.class_('B'),
- ], uriStr: 'package:test/test.dart');
+ ]);
}
test_readByteStore() async {
@@ -813,11 +1200,11 @@
tracker.addContext(testAnalysisContext);
await _doAllTrackerWork();
- _assertLibraryDeclarations([
+ _assertHasLibrary('package:test/test.dart', declarations: [
_ExpectedDeclaration.class_('A'),
_ExpectedDeclaration.class_('B'),
_ExpectedDeclaration.class_('C'),
- ], uriStr: 'package:test/test.dart');
+ ]);
}
test_removeContext_afterAddContext() async {
@@ -840,22 +1227,7 @@
expect(uriToLibrary, isEmpty);
}
- void _assertLibraryDeclarations(
- List<_ExpectedDeclaration> expectedDeclarations,
- {String uriStr}) {
- var library = uriToLibrary[uriStr];
- expect(library, isNotNull);
- expect(library.declarations, hasLength(expectedDeclarations.length));
- for (var expected in expectedDeclarations) {
- _asyncHasDeclaration(library, expected);
- }
- }
-
- void _assertNoLibrary(String uriStr) {
- expect(uriToLibrary, isNot(contains(uriStr)));
- }
-
- void _asyncHasDeclaration(Library library, _ExpectedDeclaration expected) {
+ void _assertHasDeclaration(Library library, _ExpectedDeclaration expected) {
expect(
library.declarations,
contains(predicate((Declaration d) {
@@ -865,11 +1237,32 @@
);
}
+ /// Assert that the current state has the library with the given [uri].
+ ///
+ /// If [declarations] provided, also checks that the library has exactly
+ /// these declarations.
+ void _assertHasLibrary(String uri,
+ {List<_ExpectedDeclaration> declarations}) {
+ var library = uriToLibrary[uri];
+ expect(library, isNotNull);
+ if (declarations != null) {
+ expect(library.declarations, hasLength(declarations.length));
+ for (var expected in declarations) {
+ _assertHasDeclaration(library, expected);
+ }
+ }
+ }
+
+ void _assertHasNoLibrary(String uri) {
+ expect(uriToLibrary, isNot(contains(uri)));
+ }
+
void _createTracker() {
uriToLibrary.clear();
tracker = DeclarationsTracker(byteStore, resourceProvider);
tracker.changes.listen((change) {
+ changes.add(change);
for (var library in change.changed) {
var uriStr = library.uri.toString();
idToLibrary[library.id] = library;