mirror of
https://github.com/dart-lang/sdk
synced 2024-10-07 14:20:02 +00:00
Issue 47804. Recompute invlaidated libraries after processing all changed files.
The issue has the discussion. Bug: https://github.com/dart-lang/sdk/issues/47804 Change-Id: I301fe8fe44b0e8e7e3b413df0363fabc44061c7d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/221564 Reviewed-by: Samuel Rawlins <srawlins@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
44b93338d9
commit
6091533c6e
|
@ -504,6 +504,10 @@ class DeclarationsTracker {
|
||||||
/// The list of changed file paths.
|
/// The list of changed file paths.
|
||||||
final List<String> _changedPaths = [];
|
final List<String> _changedPaths = [];
|
||||||
|
|
||||||
|
/// While processing [_changedPaths] we accumulate libraries here.
|
||||||
|
/// Then we process all of them at once, and reset to the empty set.
|
||||||
|
Set<_File> _invalidatedLibraries = {};
|
||||||
|
|
||||||
/// The list of files scheduled for processing. It may include parts and
|
/// The list of files scheduled for processing. It may include parts and
|
||||||
/// libraries, but parts are ignored when we detect them.
|
/// libraries, but parts are ignored when we detect them.
|
||||||
final List<_ScheduledFile> _scheduledFiles = [];
|
final List<_ScheduledFile> _scheduledFiles = [];
|
||||||
|
@ -529,7 +533,9 @@ class DeclarationsTracker {
|
||||||
_whenKnownFilesPulled = now;
|
_whenKnownFilesPulled = now;
|
||||||
pullKnownFiles();
|
pullKnownFiles();
|
||||||
}
|
}
|
||||||
return _changedPaths.isNotEmpty || _scheduledFiles.isNotEmpty;
|
return _changedPaths.isNotEmpty ||
|
||||||
|
_invalidatedLibraries.isNotEmpty ||
|
||||||
|
_scheduledFiles.isNotEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add the [analysisContext], so that its libraries are reported via the
|
/// Add the [analysisContext], so that its libraries are reported via the
|
||||||
|
@ -595,6 +601,13 @@ class DeclarationsTracker {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There are no more changes as far as we know.
|
||||||
|
// So, recompute exported declarations for all invalidated libraries.
|
||||||
|
if (_invalidatedLibraries.isNotEmpty) {
|
||||||
|
_processInvalidatedLibraries(_invalidatedLibraries);
|
||||||
|
_invalidatedLibraries = {};
|
||||||
|
}
|
||||||
|
|
||||||
if (_scheduledFiles.isNotEmpty) {
|
if (_scheduledFiles.isNotEmpty) {
|
||||||
var scheduledFile = _scheduledFiles.removeLast();
|
var scheduledFile = _scheduledFiles.removeLast();
|
||||||
var file = _getFileByPath(scheduledFile.context, [], scheduledFile.path)!;
|
var file = _getFileByPath(scheduledFile.context, [], scheduledFile.path)!;
|
||||||
|
@ -794,10 +807,32 @@ class DeclarationsTracker {
|
||||||
_invalidateExportedDeclarations(invalidatedLibraries, newLibrary);
|
_invalidateExportedDeclarations(invalidatedLibraries, newLibrary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_computeExportedDeclarations(invalidatedLibraries);
|
|
||||||
|
|
||||||
var changedLibraries = <Library>[];
|
// Don't compute exported declarations now, there might be more changes.
|
||||||
|
// Instead, accumulate invalidated libraries, and recompute all later.
|
||||||
|
_invalidatedLibraries.addAll(invalidatedLibraries);
|
||||||
|
|
||||||
var removedLibraries = <int>[];
|
var removedLibraries = <int>[];
|
||||||
|
for (var libraryFile in invalidatedLibraries) {
|
||||||
|
if (!libraryFile.exists) {
|
||||||
|
_idToLibrary.remove(libraryFile.id);
|
||||||
|
removedLibraries.add(libraryFile.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var file in notLibraries) {
|
||||||
|
_idToLibrary.remove(file.id);
|
||||||
|
removedLibraries.add(file.id);
|
||||||
|
}
|
||||||
|
if (removedLibraries.isNotEmpty) {
|
||||||
|
_changesController.add(
|
||||||
|
LibraryChange._([], removedLibraries),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _processInvalidatedLibraries(Set<_File> invalidatedLibraries) {
|
||||||
|
_computeExportedDeclarations(invalidatedLibraries);
|
||||||
|
var changedLibraries = <Library>[];
|
||||||
for (var libraryFile in invalidatedLibraries) {
|
for (var libraryFile in invalidatedLibraries) {
|
||||||
if (libraryFile.exists) {
|
if (libraryFile.exists) {
|
||||||
var library = Library._(
|
var library = Library._(
|
||||||
|
@ -809,17 +844,10 @@ class DeclarationsTracker {
|
||||||
);
|
);
|
||||||
_idToLibrary[library.id] = library;
|
_idToLibrary[library.id] = library;
|
||||||
changedLibraries.add(library);
|
changedLibraries.add(library);
|
||||||
} else {
|
|
||||||
_idToLibrary.remove(libraryFile.id);
|
|
||||||
removedLibraries.add(libraryFile.id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (var file in notLibraries) {
|
|
||||||
_idToLibrary.remove(file.id);
|
|
||||||
removedLibraries.add(file.id);
|
|
||||||
}
|
|
||||||
_changesController.add(
|
_changesController.add(
|
||||||
LibraryChange._(changedLibraries, removedLibraries),
|
LibraryChange._(changedLibraries, []),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -914,6 +914,75 @@ class C2 {}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://github.com/dart-lang/sdk/issues/47804
|
||||||
|
test_updated_exported2() 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'''
|
||||||
|
class A {}
|
||||||
|
''');
|
||||||
|
newFile(b, content: r'''
|
||||||
|
class B {}
|
||||||
|
''');
|
||||||
|
newFile(c, content: r'''
|
||||||
|
export 'a.dart';
|
||||||
|
export 'b.dart';
|
||||||
|
class C {}
|
||||||
|
''');
|
||||||
|
tracker.addContext(testAnalysisContext);
|
||||||
|
|
||||||
|
await _doAllTrackerWork();
|
||||||
|
_assertHasLibrary('package:test/c.dart', declarations: [
|
||||||
|
_ExpectedDeclaration.class_('A', [
|
||||||
|
_ExpectedDeclaration.constructor(''),
|
||||||
|
]),
|
||||||
|
_ExpectedDeclaration.class_('B', [
|
||||||
|
_ExpectedDeclaration.constructor(''),
|
||||||
|
]),
|
||||||
|
_ExpectedDeclaration.class_('C', [
|
||||||
|
_ExpectedDeclaration.constructor(''),
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
changes.clear();
|
||||||
|
|
||||||
|
newFile(a, content: r'''
|
||||||
|
class A2 {}
|
||||||
|
''');
|
||||||
|
newFile(b, content: r'''
|
||||||
|
class B2 {}
|
||||||
|
''');
|
||||||
|
tracker.changeFile(a);
|
||||||
|
tracker.changeFile(b);
|
||||||
|
await _doAllTrackerWork();
|
||||||
|
|
||||||
|
// In general it is OK to get duplicate libraries.
|
||||||
|
// But here we notified about both `a.dart` and `b.dart` changes before
|
||||||
|
// performing any work. So, there is no reason do handle `c.dart` twice.
|
||||||
|
var uniquePathSet = <String>{};
|
||||||
|
for (var change in changes) {
|
||||||
|
for (var library in change.changed) {
|
||||||
|
if (!uniquePathSet.add(library.path)) {
|
||||||
|
fail('Not unique path: ${library.path}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_assertHasLibrary('package:test/c.dart', declarations: [
|
||||||
|
_ExpectedDeclaration.class_('A2', [
|
||||||
|
_ExpectedDeclaration.constructor(''),
|
||||||
|
]),
|
||||||
|
_ExpectedDeclaration.class_('B2', [
|
||||||
|
_ExpectedDeclaration.constructor(''),
|
||||||
|
]),
|
||||||
|
_ExpectedDeclaration.class_('C', [
|
||||||
|
_ExpectedDeclaration.constructor(''),
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
test_updated_library() async {
|
test_updated_library() async {
|
||||||
var a = convertPath('/home/test/lib/a.dart');
|
var a = convertPath('/home/test/lib/a.dart');
|
||||||
var b = convertPath('/home/test/lib/b.dart');
|
var b = convertPath('/home/test/lib/b.dart');
|
||||||
|
|
Loading…
Reference in a new issue