Make LibraryCycle more null safe.

Change-Id: I1298651fcac80ec20db6c68b9b969da8c6320bde
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/215486
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2021-10-04 22:16:20 +00:00 committed by commit-bot@chromium.org
parent 549bb52d89
commit 6e987219c4
4 changed files with 45 additions and 49 deletions

View file

@ -80,7 +80,7 @@ import 'package:meta/meta.dart';
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
class AnalysisDriver implements AnalysisDriverGeneric {
/// The version of data format, should be incremented on every format change.
static const int DATA_VERSION = 182;
static const int DATA_VERSION = 183;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.

View file

@ -140,7 +140,6 @@ class FileState {
Set<FileState>? _directReferencedLibraries;
LibraryCycle? _libraryCycle;
String? _transitiveSignature;
/// The flag that shows whether the file has an error or warning that
/// might be fixed by a change to another file.
@ -320,10 +319,12 @@ class FileState {
/// Return the signature of the file, based on API signatures of the
/// transitive closure of imported / exported files.
/// TODO(scheglov) Remove it.
String get transitiveSignature {
libraryCycle; // sets _transitiveSignature
_transitiveSignature ??= _invalidTransitiveSignature;
return _transitiveSignature!;
var librarySignatureBuilder = ApiSignature()
..addString(uriStr)
..addString(libraryCycle.transitiveSignature);
return librarySignatureBuilder.toHex();
}
/// The [UnlinkedUnit2] of the file.
@ -335,13 +336,6 @@ class FileState {
/// Return the [uri] string.
String get uriStr => uri.toString();
String get _invalidTransitiveSignature {
return (ApiSignature()
..addString(path)
..addBytes(unlinkedSignature))
.toHex();
}
@override
bool operator ==(Object other) {
return other is FileState && other.uri == uri;
@ -357,14 +351,8 @@ class FileState {
return bytes;
}
void internal_setLibraryCycle(LibraryCycle? cycle, String? signature) {
if (cycle == null) {
_libraryCycle = null;
_transitiveSignature = null;
} else {
_libraryCycle = cycle;
_transitiveSignature = signature;
}
void internal_setLibraryCycle(LibraryCycle? cycle) {
_libraryCycle = cycle;
}
/// Return a new parsed unresolved [CompilationUnit].

View file

@ -121,7 +121,7 @@ class LibraryContext {
}
}
var resolutionKey = cycle.transitiveSignature! + '.linked_bundle';
var resolutionKey = cycle.transitiveSignature + '.linked_bundle';
var resolutionBytes = byteStore.get(resolutionKey) as Uint8List?;
if (resolutionBytes == null) {

View file

@ -20,10 +20,10 @@ void computeLibraryCycle(Uint32List salt, FileState file) {
/// Information about libraries that reference each other, so form a cycle.
class LibraryCycle {
/// The libraries that belong to this cycle.
final List<FileState> libraries = [];
final List<FileState> libraries;
/// The library cycles that this cycle references directly.
final Set<LibraryCycle> directDependencies = <LibraryCycle>{};
final Set<LibraryCycle> directDependencies;
/// The cycles that use this cycle, used to [invalidate] transitively.
final List<LibraryCycle> _directUsers = [];
@ -34,7 +34,17 @@ class LibraryCycle {
/// transitive signatures of the cycles that the [libraries] reference
/// directly. So, indirectly it is based on the transitive closure of all
/// files that [libraries] reference (but we don't compute these files).
String? transitiveSignature;
String transitiveSignature;
LibraryCycle({
required this.libraries,
required this.directDependencies,
required this.transitiveSignature,
}) {
for (var directDependency in directDependencies) {
directDependency._directUsers.add(this);
}
}
/// Invalidate this cycle and any cycles that directly or indirectly use it.
///
@ -42,12 +52,14 @@ class LibraryCycle {
/// [libraries] that share this [LibraryCycle] instance.
void invalidate() {
for (var library in libraries) {
library.internal_setLibraryCycle(null, null);
library.internal_setLibraryCycle(null);
}
for (var user in _directUsers) {
for (var user in _directUsers.toList()) {
user.invalidate();
}
_directUsers.clear();
for (var directDependency in directDependencies) {
directDependency._directUsers.remove(this);
}
}
@override
@ -87,8 +99,6 @@ class _LibraryWalker extends graph.DependencyWalker<_LibraryNode> {
@override
void evaluateScc(List<_LibraryNode> scc) {
var cycle = LibraryCycle();
var signature = ApiSignature();
signature.addUint32List(_salt);
@ -100,17 +110,20 @@ class _LibraryWalker extends graph.DependencyWalker<_LibraryNode> {
});
// Append direct referenced cycles.
var directDependencies = <LibraryCycle>{};
for (var node in scc) {
var file = node.file;
_appendDirectlyReferenced(
cycle, signature, file.importedFiles.whereNotNull().toList());
_appendDirectlyReferenced(
cycle, signature, file.exportedFiles.whereNotNull().toList());
directDependencies,
signature,
file.directReferencedLibraries.whereNotNull().toList(),
);
}
// Fill the cycle with libraries.
var libraries = <FileState>[];
for (var node in scc) {
cycle.libraries.add(node.file);
libraries.add(node.file);
signature.addLanguageVersion(node.file.packageLanguageVersion);
signature.addString(node.file.uriStr);
@ -122,20 +135,16 @@ class _LibraryWalker extends graph.DependencyWalker<_LibraryNode> {
}
}
// Compute the general library cycle signature.
cycle.transitiveSignature = signature.toHex();
// Create the LibraryCycle instance for the cycle.
var cycle = LibraryCycle(
libraries: libraries,
directDependencies: directDependencies,
transitiveSignature: signature.toHex(),
);
// Compute library specific signatures.
// Set the instance into the libraries.
for (var node in scc) {
var librarySignatureBuilder = ApiSignature()
..addString(node.file.uriStr)
..addString(cycle.transitiveSignature!);
var librarySignature = librarySignatureBuilder.toHex();
node.file.internal_setLibraryCycle(
cycle,
librarySignature,
);
node.file.internal_setLibraryCycle(cycle);
}
}
@ -144,7 +153,7 @@ class _LibraryWalker extends graph.DependencyWalker<_LibraryNode> {
}
void _appendDirectlyReferenced(
LibraryCycle cycle,
Set<LibraryCycle> directDependencies,
ApiSignature signature,
List<FileState> directlyReferenced,
) {
@ -155,9 +164,8 @@ class _LibraryWalker extends graph.DependencyWalker<_LibraryNode> {
// We get null when the library is a part of the cycle being build.
if (referencedCycle == null) continue;
if (cycle.directDependencies.add(referencedCycle)) {
referencedCycle._directUsers.add(cycle);
signature.addString(referencedCycle.transitiveSignature!);
if (directDependencies.add(referencedCycle)) {
signature.addString(referencedCycle.transitiveSignature);
}
}
}