Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1900)

Unified Diff: pkg/analyzer/lib/src/generated/engine.dart

Issue 806733003: Make futures returned by AnalysisContext cancelable. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/lib/src/generated/engine.dart
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index a51ae9a23a3711f7327234a354052c59b19a0f9e..78188788b51a36e4fc4081dcf77f2d94ff7df34c 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -11,6 +11,7 @@ import "dart:math" as math;
import 'dart:async';
import 'dart:collection';
+import 'package:analyzer/src/cancelable_future.dart';
import 'package:analyzer/src/task/task_dart.dart';
import '../../instrumentation/instrumentation.dart';
@@ -758,8 +759,8 @@ abstract class AnalysisContext {
* source file is not scheduled to be analyzed within the context of the
* given library.
*/
- Future<CompilationUnit> getResolvedCompilationUnitFuture(Source source,
- Source librarySource);
+ CancelableFuture<CompilationUnit>
+ getResolvedCompilationUnitFuture(Source source, Source librarySource);
/**
* Return a fully resolved HTML unit, or `null` if the resolved unit is not already
@@ -1326,6 +1327,12 @@ class AnalysisContextImpl implements InternalAnalysisContext {
Stream<SourcesChangedEvent> get onSourcesChanged =>
_onSourcesChangedController.stream;
+ /**
+ * Make _pendingFutureSources available to unit tests.
+ */
+ HashMap<Source, List<PendingFuture>> get pendingFutureSources_forTesting =>
+ _pendingFutureSources;
+
@override
List<Source> get prioritySources => _priorityOrder;
@@ -2075,9 +2082,10 @@ class AnalysisContextImpl implements InternalAnalysisContext {
}
@override
- Future<CompilationUnit> getResolvedCompilationUnitFuture(Source unitSource,
- Source librarySource) {
- return _getFuture(unitSource, (SourceEntry sourceEntry) {
+ CancelableFuture<CompilationUnit>
+ getResolvedCompilationUnitFuture(Source unitSource, Source librarySource) {
+ return new _AnalysisFutureHelper<CompilationUnit>(
+ this).getFuture(unitSource, (SourceEntry sourceEntry) {
if (sourceEntry is DartEntry) {
if (sourceEntry.getStateInLibrary(
DartEntry.RESOLVED_UNIT,
@@ -2882,6 +2890,21 @@ class AnalysisContextImpl implements InternalAnalysisContext {
}
/**
+ * Remove the given [pendingFuture] from [_pendingFutureSources], since the
+ * client has indicated its computation is not needed anymore.
+ */
+ void _cancelFuture(PendingFuture pendingFuture) {
+ List<PendingFuture> pendingFutures =
+ _pendingFutureSources[pendingFuture.source];
+ if (pendingFutures != null) {
+ pendingFutures.remove(pendingFuture);
+ if (pendingFutures.isEmpty) {
+ _pendingFutureSources.remove(pendingFuture.source);
+ }
+ }
+ }
+
+ /**
* Compute the transitive closure of all libraries that depend on the given library by adding such
* libraries to the given collection.
*
@@ -3627,37 +3650,6 @@ class AnalysisContextImpl implements InternalAnalysisContext {
}
/**
- * Return a future that will be completed with the result of calling
- * [computeValue]. If [computeValue] returns non-null, the future will be
- * completed immediately with the resulting value. If it returns null, then
- * it will be re-executed in the future, after the next time the cached
- * information for [source] has changed. If [computeValue] throws an
- * exception, the future will fail with that exception.
- *
- * If the [computeValue] still returns null after there is no further
- * analysis to be done for [source], then the future will be completed with
- * the error AnalysisNotScheduledError.
- *
- * Since [computeValue] will be called while the state of analysis is being
- * updated, it should be free of side effects so that it doesn't cause
- * reentrant changes to the analysis state.
- */
- Future /*<T>*/ _getFuture(Source source, /*T*/
- computeValue(SourceEntry sourceEntry)) {
- SourceEntry sourceEntry = getReadableSourceEntryOrNull(source);
- if (sourceEntry == null) {
- return new Future.error(new AnalysisNotScheduledError());
- }
- PendingFuture pendingFuture = new PendingFuture(computeValue);
- if (!pendingFuture.evaluate(sourceEntry)) {
- _pendingFutureSources.putIfAbsent(
- source,
- () => <PendingFuture>[]).add(pendingFuture);
- }
- return pendingFuture.future;
- }
-
- /**
* Given a source for an HTML file, return the data represented by the given descriptor that is
* associated with that source, or the given default value if the source is not an HTML file. This
* method assumes that the data can be produced by parsing the source if it is not already cached.
@@ -9659,7 +9651,6 @@ class DataDescriptor<E> {
String toString() => _name;
}
-
/**
* Instances of the class `DefaultRetentionPolicy` implement a retention policy that will keep
* AST's in the cache if there is analysis information that needs to be computed for a source, where
@@ -9695,6 +9686,7 @@ class DefaultRetentionPolicy implements CacheRetentionPolicy {
}
}
+
/**
* Recursively visits [HtmlUnit] and every embedded [Expression].
*/
@@ -11670,6 +11662,16 @@ class PartitionManager {
*/
class PendingFuture<T> {
/**
+ * The context in which this computation runs.
+ */
+ final AnalysisContextImpl _context;
+
+ /**
+ * The source used by this computation to compute its value.
+ */
+ final Source source;
+
+ /**
* The function which implements the computation.
*/
final PendingFutureComputer<T> _computeValue;
@@ -11677,15 +11679,17 @@ class PendingFuture<T> {
/**
* The completer that should be completed once the computation has succeeded.
*/
- final Completer<T> _completer = new Completer<T>();
+ CancelableCompleter<T> _completer;
- PendingFuture(this._computeValue);
+ PendingFuture(this._context, this.source, this._computeValue) {
+ _completer = new CancelableCompleter<T>(_onCancel);
+ }
/**
* Retrieve the future which will be completed when this object is
* successfully evaluated.
*/
- Future<T> get future => _completer.future;
+ CancelableFuture<T> get future => _completer.future;
/**
* Execute [_computeValue], passing it the given [sourceEntry], and complete
@@ -11727,6 +11731,10 @@ class PendingFuture<T> {
_completer.completeError(exception, stackTrace);
}
}
+
+ void _onCancel() {
+ _context._cancelFuture(this);
+ }
}
/**
@@ -14319,6 +14327,48 @@ class WorkManager_WorkIterator {
}
}
+/**
+ * Helper class used to create futures for AnalysisContextImpl. Using a helper
+ * class allows us to preserve the generic parameter T.
+ */
+class _AnalysisFutureHelper<T> {
+ final AnalysisContextImpl _context;
+
+ _AnalysisFutureHelper(this._context);
+
+ /**
+ * Return a future that will be completed with the result of calling
+ * [computeValue]. If [computeValue] returns non-null, the future will be
+ * completed immediately with the resulting value. If it returns null, then
+ * it will be re-executed in the future, after the next time the cached
+ * information for [source] has changed. If [computeValue] throws an
+ * exception, the future will fail with that exception.
+ *
+ * If the [computeValue] still returns null after there is no further
+ * analysis to be done for [source], then the future will be completed with
+ * the error AnalysisNotScheduledError.
+ *
+ * Since [computeValue] will be called while the state of analysis is being
+ * updated, it should be free of side effects so that it doesn't cause
+ * reentrant changes to the analysis state.
+ */
+ CancelableFuture<T> getFuture(Source source, T
+ computeValue(SourceEntry sourceEntry)) {
+ SourceEntry sourceEntry = _context.getReadableSourceEntryOrNull(source);
+ if (sourceEntry == null) {
+ return new CancelableFuture.error(new AnalysisNotScheduledError());
+ }
+ PendingFuture pendingFuture =
+ new PendingFuture<T>(_context, source, computeValue);
+ if (!pendingFuture.evaluate(sourceEntry)) {
+ _context._pendingFutureSources.putIfAbsent(
+ source,
+ () => <PendingFuture>[]).add(pendingFuture);
+ }
+ return pendingFuture.future;
+ }
+}
+
class _AngularHtmlUnitResolver_visitModelDirectives extends
ht.RecursiveXmlVisitor<Object> {
final AngularHtmlUnitResolver resolver;

Powered by Google App Engine
This is Rietveld 408576698