Use new build apis to load results (#959)

This commit is contained in:
Simon Binder 2020-12-29 22:22:32 +01:00
parent 00cbda445c
commit db72da0f07
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
6 changed files with 22 additions and 85 deletions

View File

@ -1,4 +1,3 @@
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@ -60,7 +59,7 @@ class MoorDartParser {
return (method.body as ExpressionFunctionBody).expression;
}
Future<ElementDeclarationResult> loadElementDeclaration(Element element) {
Future<AstNode> loadElementDeclaration(Element element) {
return step.task.backend.loadElementDeclaration(element);
}

View File

@ -68,10 +68,8 @@ class TableParser {
// we expect something like get tableName => "myTableName", the getter
// must do nothing more complicated
final tableNameDeclaration =
await base.loadElementDeclaration(tableNameGetter);
final returnExpr = base.returnExpressionOfMethod(
tableNameDeclaration.node as MethodDeclaration);
final node = await base.loadElementDeclaration(tableNameGetter);
final returnExpr = base.returnExpressionOfMethod(node as MethodDeclaration);
final tableName = base.readStringLiteral(returnExpr, () {
base.step.reportError(ErrorInDartCode(
@ -95,8 +93,8 @@ class TableParser {
return null;
}
final resolved = await base.loadElementDeclaration(primaryKeyGetter);
final ast = resolved.node as MethodDeclaration;
final ast = await base.loadElementDeclaration(primaryKeyGetter)
as MethodDeclaration;
final body = ast.body;
if (body is! ExpressionFunctionBody) {
base.step.reportError(ErrorInDartCode(
@ -132,8 +130,7 @@ class TableParser {
// Was the getter overridden at all?
if (getter.isFromDefaultTable) return null;
final resolved = await base.loadElementDeclaration(getter);
final ast = resolved.node as MethodDeclaration;
final ast = await base.loadElementDeclaration(getter) as MethodDeclaration;
final expr = base.returnExpressionOfMethod(ast);
if (expr == null) return null;
@ -169,8 +166,8 @@ class TableParser {
});
final results = await Future.wait(fields.map((field) async {
final resolved = await base.loadElementDeclaration(field.getter);
final node = resolved.node as MethodDeclaration;
final node =
await base.loadElementDeclaration(field.getter) as MethodDeclaration;
return await base.parseColumn(node, field.getter);
}));

View File

@ -1,4 +1,4 @@
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:logging/logging.dart';
@ -33,12 +33,11 @@ abstract class BackendTask {
throw UnsupportedError('Resolving dart expressions not supported');
}
Future<ElementDeclarationResult> loadElementDeclaration(
Element element) async {
Future<AstNode> loadElementDeclaration(Element element) async {
final resolvedLibrary = await element.library.session
.getResolvedLibraryByElement(element.library);
return resolvedLibrary.getElementDeclaration(element);
return resolvedLibrary.getElementDeclaration(element)?.node;
}
/// Checks whether a file at [uri] exists.

View File

@ -1,6 +1,5 @@
import 'dart:convert';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:build/build.dart' hide log;
@ -31,12 +30,6 @@ class BuildBackendTask extends BackendTask {
final BuildBackend backend;
final TypeDeserializer typeDeserializer;
final Map<AssetId, ResolvedLibraryResult> _cachedResults = {};
/// The analysis session might be invalidated every time we resolve a new
/// library, so we grab a new one instead of using `LibraryElement.session`.
AnalysisSession _currentAnalysisSession;
BuildBackendTask(this.step, this.backend)
: typeDeserializer = TypeDeserializer(step);
@ -47,6 +40,11 @@ class BuildBackendTask extends BackendTask {
return AssetId.resolve(uri.toString(), from: step.inputId);
}
@override
Future<AstNode> loadElementDeclaration(Element element) async {
return await step.resolver.astNodeFor(element, resolve: true);
}
@override
Future<String> readMoor(Uri uri) {
return step.readAsString(_resolve(uri));
@ -56,66 +54,12 @@ class BuildBackendTask extends BackendTask {
Future<LibraryElement> resolveDart(Uri uri) async {
try {
final asset = _resolve(uri);
final library = await step.resolver.libraryFor(asset);
_currentAnalysisSession = library.session;
return library;
return await step.resolver.libraryFor(asset);
} on NonLibraryAssetException catch (_) {
throw NotALibraryException(uri);
}
}
@override
Future<ElementDeclarationResult> loadElementDeclaration(
Element element) async {
// prefer to use a cached value in case the session changed because another
// dart file was read...
final assetId = await step.resolver.assetIdForElement(element);
final result = _cachedResults[assetId];
if (result != null) {
return result.getElementDeclaration(element);
} else {
_currentAnalysisSession ??= element.session;
for (var retries = 0; retries < _maxSessionRetries; retries++) {
try {
final library =
await _libraryInCurrentSession(element.library, assetId);
final result = await _currentAnalysisSession
.getResolvedLibraryByElement(library);
_cachedResults[assetId] = result;
// Note: getElementDeclaration works by comparing source offsets, so
// element.session != session is not a problem in this case.
return result.getElementDeclaration(element);
} on InconsistentAnalysisException {
final isLastTry = retries == _maxSessionRetries - 1;
if (isLastTry) rethrow;
}
}
throw AssertionError('Unreachable, we rethrow in the last iteration');
}
}
Future<LibraryElement> _libraryInCurrentSession(
LibraryElement library, AssetId definingAsset) async {
if (library.session == _currentAnalysisSession) return library;
try {
// This is safe: If this build step knows the library, it has already read
// the originating asset. We can bypass the build asset reader!
return await _currentAnalysisSession
.getLibraryByUri(definingAsset.uri.toString());
} on InconsistentAnalysisException {
final library = await step.resolver.libraryFor(definingAsset);
_currentAnalysisSession = library.session;
return library;
}
}
@override
Logger get log => build.log;
@ -142,6 +86,4 @@ class BuildBackendTask extends BackendTask {
return typeDeserializer
.deserialize(SerializedType.fromJson(serializedType));
}
static const int _maxSessionRetries = 5;
}

View File

@ -32,8 +32,8 @@ dependencies:
source_span: ^1.5.5
# Build system
build: ^1.1.0
build_resolvers: ^1.3.3
build: ^1.6.0
build_resolvers: ^1.5.1
build_config: '>=0.3.1 <1.0.0'
dart_style: ^1.3.3
source_gen: ^0.9.4

View File

@ -34,8 +34,8 @@ void main() {
ParseDartStep(task, session.registerFile(input), library));
Future<MethodDeclaration> _loadDeclaration(Element element) async {
final declaration = await parser.loadElementDeclaration(element);
return declaration.node as MethodDeclaration;
final node = await parser.loadElementDeclaration(element);
return node as MethodDeclaration;
}
Future<void> _verifyReturnExpressionMatches(