| 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 83769e6d77e53c152d3dfb6cd9677aa65ca2ba35..52290d6aea7b8ad32f3b0ecbcd0ef2db6c879151 100644
|
| --- a/pkg/analyzer/lib/src/generated/engine.dart
|
| +++ b/pkg/analyzer/lib/src/generated/engine.dart
|
| @@ -209,8 +209,10 @@ class AnalysisCache {
|
|
|
| /**
|
| * Remove all information related to the given [source] from this cache.
|
| + * Return the entry associated with the source, or `null` if there was cache
|
| + * entry for the source.
|
| */
|
| - void remove(Source source) {
|
| + SourceEntry remove(Source source) {
|
| int count = _partitions.length;
|
| for (int i = 0; i < count; i++) {
|
| if (_partitions[i].contains(source)) {
|
| @@ -223,10 +225,10 @@ class AnalysisCache {
|
| JavaSystem.currentTimeMillis();
|
| }
|
| }
|
| - _partitions[i].remove(source);
|
| - return;
|
| + return _partitions[i].remove(source);
|
| }
|
| }
|
| + return null;
|
| }
|
|
|
| /**
|
| @@ -353,6 +355,12 @@ abstract class AnalysisContext {
|
| List<Source> get htmlSources;
|
|
|
| /**
|
| + * The stream that is notified when a source either starts or stops being
|
| + * analyzed implicitly.
|
| + */
|
| + Stream<ImplicitAnalysisEvent> get implicitAnalysisEvents;
|
| +
|
| + /**
|
| * Returns `true` if this context was disposed using [dispose].
|
| */
|
| bool get isDisposed;
|
| @@ -1034,6 +1042,12 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| StreamController<SourcesChangedEvent> _onSourcesChangedController;
|
|
|
| /**
|
| + * A subscription for a stream of events indicating when files are (and are
|
| + * not) being implicitly analyzed.
|
| + */
|
| + StreamController<ImplicitAnalysisEvent> _implicitAnalysisEventsController;
|
| +
|
| + /**
|
| * The listeners that are to be notified when various analysis results are
|
| * produced in this context.
|
| */
|
| @@ -1084,6 +1098,8 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| _cache = createCacheFromSourceFactory(null);
|
| _onSourcesChangedController =
|
| new StreamController<SourcesChangedEvent>.broadcast();
|
| + _implicitAnalysisEventsController =
|
| + new StreamController<ImplicitAnalysisEvent>.broadcast();
|
| }
|
|
|
| @override
|
| @@ -1198,6 +1214,10 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| List<Source> get htmlSources => _getSources(SourceKind.HTML);
|
|
|
| @override
|
| + Stream<ImplicitAnalysisEvent> get implicitAnalysisEvents =>
|
| + _implicitAnalysisEventsController.stream;
|
| +
|
| + @override
|
| bool get isDisposed => _disposed;
|
|
|
| @override
|
| @@ -2410,7 +2430,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| } else {
|
| unitEntry.recordResolutionError(thrownException);
|
| }
|
| - _cache.remove(unitSource);
|
| + _removeFromCache(unitSource);
|
| if (thrownException != null) {
|
| throw new AnalysisException('<rethrow>', thrownException);
|
| }
|
| @@ -2483,7 +2503,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| } else {
|
| unitEntry.recordResolutionError(thrownException);
|
| }
|
| - _cache.remove(unitSource);
|
| + _removeFromCache(unitSource);
|
| if (thrownException != null) {
|
| throw new AnalysisException('<rethrow>', thrownException);
|
| }
|
| @@ -2513,7 +2533,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| } else {
|
| dartEntry.recordResolutionErrorInLibrary(
|
| librarySource, thrownException);
|
| - _cache.remove(source);
|
| + _removeFromCache(source);
|
| }
|
| if (source != librarySource) {
|
| _workManager.add(source, SourcePriority.PRIORITY_PART);
|
| @@ -2615,7 +2635,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| for (Source source in missingSources) {
|
| if (getLibrariesContaining(source).isEmpty &&
|
| getLibrariesDependingOn(source).isEmpty) {
|
| - _cache.remove(source);
|
| + _removeFromCache(source);
|
| removalCount++;
|
| }
|
| }
|
| @@ -3385,12 +3405,20 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| htmlEntry.modificationTime = getModificationStamp(source);
|
| htmlEntry.explicitlyAdded = explicitlyAdded;
|
| _cache.put(source, htmlEntry);
|
| + if (!explicitlyAdded) {
|
| + _implicitAnalysisEventsController
|
| + .add(new ImplicitAnalysisEvent(source, true));
|
| + }
|
| return htmlEntry;
|
| } else {
|
| DartEntry dartEntry = new DartEntry();
|
| dartEntry.modificationTime = getModificationStamp(source);
|
| dartEntry.explicitlyAdded = explicitlyAdded;
|
| _cache.put(source, dartEntry);
|
| + if (!explicitlyAdded) {
|
| + _implicitAnalysisEventsController
|
| + .add(new ImplicitAnalysisEvent(source, true));
|
| + }
|
| return dartEntry;
|
| }
|
| }
|
| @@ -4108,6 +4136,16 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| AnalysisEngine.instance.logger.logInformation(message);
|
| }
|
|
|
| + /**
|
| + * Notify all of the analysis listeners that a task is about to be performed.
|
| + */
|
| + void _notifyAboutToPerformTask(String taskDescription) {
|
| + int count = _listeners.length;
|
| + for (int i = 0; i < count; i++) {
|
| + _listeners[i].aboutToPerformTask(this, taskDescription);
|
| + }
|
| + }
|
| +
|
| // /**
|
| // * Notify all of the analysis listeners that the given source is no longer included in the set of
|
| // * sources that are being analyzed.
|
| @@ -4187,16 +4225,6 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| // }
|
|
|
| /**
|
| - * Notify all of the analysis listeners that a task is about to be performed.
|
| - */
|
| - void _notifyAboutToPerformTask(String taskDescription) {
|
| - int count = _listeners.length;
|
| - for (int i = 0; i < count; i++) {
|
| - _listeners[i].aboutToPerformTask(this, taskDescription);
|
| - }
|
| - }
|
| -
|
| - /**
|
| * Notify all of the analysis listeners that the errors associated with the
|
| * given [source] has been updated to the given [errors].
|
| */
|
| @@ -4569,6 +4597,14 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| return dartEntry;
|
| }
|
|
|
| + void _removeFromCache(Source source) {
|
| + SourceEntry entry = _cache.remove(source);
|
| + if (entry != null && entry.explicitlyAdded) {
|
| + _implicitAnalysisEventsController
|
| + .add(new ImplicitAnalysisEvent(source, false));
|
| + }
|
| + }
|
| +
|
| /**
|
| * Remove the given [librarySource] from the list of containing libraries for
|
| * all of the parts referenced by the given [dartEntry].
|
| @@ -4581,7 +4617,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| if (partEntry != null && !identical(partEntry, dartEntry)) {
|
| partEntry.removeContainingLibrary(librarySource);
|
| if (partEntry.containingLibraries.length == 0 && !exists(partSource)) {
|
| - _cache.remove(partSource);
|
| + _removeFromCache(partSource);
|
| }
|
| }
|
| }
|
| @@ -4601,7 +4637,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| partEntry.removeContainingLibrary(librarySource);
|
| if (partEntry.containingLibraries.length == 0 &&
|
| !exists(partSource)) {
|
| - _cache.remove(partSource);
|
| + _removeFromCache(partSource);
|
| }
|
| }
|
| }
|
| @@ -4630,6 +4666,10 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * that referenced the source before it existed.
|
| */
|
| void _sourceAvailable(Source source) {
|
| + // TODO(brianwilkerson) This method needs to check whether the source was
|
| + // previously being implicitly analyzed. If so, the cache entry needs to be
|
| + // update to reflect the new status and an event needs to be generated to
|
| + // inform clients that it is no longer being implicitly analyzed.
|
| SourceEntry sourceEntry = _cache.get(source);
|
| if (sourceEntry == null) {
|
| sourceEntry = _createSourceEntry(source, true);
|
| @@ -4718,7 +4758,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| _invalidateLibraryResolution(librarySource);
|
| }
|
| }
|
| - _cache.remove(source);
|
| + _removeFromCache(source);
|
| _workManager.remove(source);
|
| _removeFromPriorityOrder(source);
|
| }
|
| @@ -6752,11 +6792,13 @@ abstract class CachePartition {
|
| }
|
|
|
| /**
|
| - * Remove all information related to the given [source] from this cache.
|
| + * Remove all information related to the given [source] from this partition.
|
| + * Return the entry associated with the source, or `null` if there was cache
|
| + * entry for the source.
|
| */
|
| - void remove(Source source) {
|
| + SourceEntry remove(Source source) {
|
| _recentlyUsed.remove(source);
|
| - _sourceMap.remove(source);
|
| + return _sourceMap.remove(source);
|
| }
|
|
|
| /**
|
| @@ -8853,6 +8895,32 @@ class HtmlEntry extends SourceEntry {
|
| }
|
|
|
| /**
|
| + * An event indicating when a source either starts or stops being implicitly
|
| + * analyzed.
|
| + */
|
| +class ImplicitAnalysisEvent {
|
| + /**
|
| + * The source whose status has changed.
|
| + */
|
| + final Source source;
|
| +
|
| + /**
|
| + * A flag indicating whether the source is now being analyzed.
|
| + */
|
| + final bool isAnalyzed;
|
| +
|
| + /**
|
| + * Initialize a newly created event to indicate that the given [source] has
|
| + * changed it status to match the [isAnalyzed] flag.
|
| + */
|
| + ImplicitAnalysisEvent(this.source, this.isAnalyzed);
|
| +
|
| + @override
|
| + String toString() =>
|
| + '${isAnalyzed ? '' : 'not '}analyzing ${source.fullName}';
|
| +}
|
| +
|
| +/**
|
| * Instances of the class `IncrementalAnalysisCache` hold information used to perform
|
| * incremental analysis.
|
| *
|
|
|