Try to work around invalidation exceptions.

We have a spike in exceptions internally, and I suspect that it was
caused by https://dart-review.googlesource.com/c/sdk/+/219942

But I was unable to understand why it happens.
So, this workaround is the best I can think of now.

Change-Id: I714eb6666706aad457b72e066978aa2d734fb89f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/220640
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Konstantin Shcheglov
2021-11-17 23:26:21 +00:00
committed by commit-bot@chromium.org
parent 051c198bff
commit 76ddb43454
2 changed files with 24 additions and 0 deletions
@@ -1783,6 +1783,11 @@ class AnalysisDriver implements AnalysisDriverGeneric {
void _removePotentiallyAffectedLibraries(String path) {
var affected = <FileState>{};
_fsState.collectAffected(path, affected);
for (var file in affected) {
file.invalidateLibraryCycle();
}
_libraryContext?.elementFactory.removeLibraries(
affected.map((e) => e.uriStr).toSet(),
);
@@ -352,6 +352,11 @@ class FileState {
_libraryCycle = cycle;
}
void invalidateLibraryCycle() {
_libraryCycle?.invalidate();
_libraryCycle = null;
}
/// Return a new parsed unresolved [CompilationUnit].
CompilationUnitImpl parse([AnalysisErrorListener? errorListener]) {
errorListener ??= AnalysisErrorListener.NULL_LISTENER;
@@ -765,6 +770,20 @@ class FileSystemState {
/// Collected files that transitively reference a file with the [path].
/// These files are potentially affected by the change.
void collectAffected(String path, Set<FileState> affected) {
// TODO(scheglov) This should not be necessary.
// We use affected files to remove library elements, and we can only get
// these library elements when we link or load them, using library cycles.
// And we get library cycles by asking `directReferencedFiles`.
while (true) {
final knownFiles = this.knownFiles.toList();
for (var file in knownFiles.toList()) {
file.directReferencedFiles;
}
if (this.knownFiles.length == knownFiles.length) {
break;
}
}
collectAffected(FileState file) {
if (affected.add(file)) {
for (var other in file.referencingFiles) {