New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Require analyzer 3.4.1, prepare for future breaking changes. #3269
Conversation
Seeing a lot of |
It looks that the difference in |
In my builder, I think there's some logic related to getting a resolved AST that still uses the analyzer APIs in a retry loop instead of the new method from the |
Actually it looks like the exceptions are more severe , they're coming from |
@jakemac53, is this intended to mean that the session is considered inconsistent if any This could explain how the interleaved execution of reflectable code generation on tests gives rise to these inconsistency exceptions: We're generating code for a few hundred tests, and the code generation is interleaved, so it is definitely possible that one program's generated code is stored on disk during the time where some other program's code generation is ongoing. |
(This comment is pretty much saying the same thing as eernstg, I was just a few minutes late :D But I think there's no easy fix as all builders share the same driver-bound analysis session) I'm convinced these errors aren't just me doing anything weird in the community tests, I think they should also happen for every other What I think might be causing this issue is that, in a typical build, there are lots of concurrent calls to I was able to fix this by wrapping every async analyzer API in a diff --git a/build_resolvers/lib/src/resolver.dart b/build_resolvers/lib/src/resolver.dart
index 099bf532..ecd04bcf 100644
--- a/build_resolvers/lib/src/resolver.dart
+++ b/build_resolvers/lib/src/resolver.dart
@@ -117,7 +117,7 @@ class PerActionResolver implements ReleasableResolver {
// Ensures that we finish resolving one thing before attempting to resolve
// another, otherwise there are race conditions with `_entryPoints` being
// updated before it is actually ready, or resolved more than once.
- final _resolvePool = Pool(1);
+ Pool get _resolvePool => _delegate._driverLock;
Future<void> _resolveIfNecessary(AssetId id, {required bool transitive}) =>
_resolvePool.withResource(() async {
if (!_entryPoints.contains(id)) {
@@ -147,6 +147,8 @@ class AnalyzerResolver implements ReleasableResolver {
final BuildAssetUriResolver _uriResolver;
final AnalysisDriverForPackageBuild _driver;
+ final Pool _driverLock = Pool(1);
+
AnalyzerResolver(this._driver, this._uriResolver);
@override
@@ -160,7 +162,6 @@ class AnalyzerResolver implements ReleasableResolver {
@override
Future<AstNode?> astNodeFor(Element element, {bool resolve = false}) async {
- var session = _driver.currentSession;
final library = element.library;
if (library == null) {
// Invalid elements (e.g. an MultiplyDefinedElement) are not part of any
@@ -170,11 +171,14 @@ class AnalyzerResolver implements ReleasableResolver {
var path = library.source.fullName;
if (resolve) {
- return (await session.getResolvedLibrary(path) as ResolvedLibraryResult)
- .getElementDeclaration(element)
- ?.node;
+ final resolved = await _driverLock.withResource(
+ () => _driver.currentSession.getResolvedLibrary(path))
+ as ResolvedLibraryResult;
+
+ return resolved.getElementDeclaration(element)?.node;
} else {
- return (session.getParsedLibrary(path) as ParsedLibraryResult)
+ return (_driver.currentSession.getParsedLibrary(path)
+ as ParsedLibraryResult)
.getElementDeclaration(element)
?.node;
}
@@ -210,7 +214,8 @@ class AnalyzerResolver implements ReleasableResolver {
throw NonLibraryAssetException(assetId);
}
- final library = await _driver.currentSession.getLibraryByUri(uri.toString())
+ final library = await _driverLock.withResource(
+ () => _driver.currentSession.getLibraryByUri(uri.toString()))
as LibraryElementResult;
if (!allowSyntaxErrors) {
final errors = await _syntacticErrorsFor(library.element);
@@ -243,8 +248,8 @@ class AnalyzerResolver implements ReleasableResolver {
final relevantResults = <ErrorsResult>[];
for (final path in paths) {
- final result =
- await _driver.currentSession.getErrors(path) as ErrorsResult;
+ final result = await _driverLock.withResource(
+ () => _driver.currentSession.getErrors(path)) as ErrorsResult;
if (result.errors
.any((error) => error.errorCode.type == ErrorType.SYNTACTIC_ERROR)) {
relevantResults.add(result); |
cc @scheglov do you have any suggestions here? |
See also dart-lang/sdk#48658 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, not sure what is up with the markdown job here, will land on red for right now
In
analyzer 4.0.0
we will stop processingchangeFile()
immediately, and instead will do it between other async requests. But this will invalidate the session, soapplyPendingFileChanges()
is required before invoking anyAnalysisSession
API.Also, linking elements will become an async operation to support future work on macros (which require async talking to the macro running isolates).
The internal presubmit looks green.