Index: dart/pkg/analyzer/lib/src/generated/engine.dart |
=================================================================== |
--- dart/pkg/analyzer/lib/src/generated/engine.dart (revision 29785) |
+++ dart/pkg/analyzer/lib/src/generated/engine.dart (working copy) |
@@ -4054,7 +4054,7 @@ |
AnalysisTask get nextTaskAnalysisTask { |
{ |
bool hintsEnabled = _options.hint; |
- if (_incrementalAnalysisCache != null) { |
+ if (_incrementalAnalysisCache != null && _incrementalAnalysisCache.hasWork()) { |
AnalysisTask task = new IncrementalAnalysisTask(this, _incrementalAnalysisCache); |
_incrementalAnalysisCache = null; |
} |
@@ -4596,6 +4596,7 @@ |
if (unit != null) { |
ChangeNoticeImpl notice = getNotice(task.source); |
notice.compilationUnit = unit; |
+ _incrementalAnalysisCache = IncrementalAnalysisCache.cacheResult(task.cache, unit); |
} |
} |
return null; |
@@ -4646,6 +4647,7 @@ |
dartCopy.setValue(DartEntry.INCLUDED_PARTS, task.includedSources); |
ChangeNoticeImpl notice = getNotice(source); |
notice.setErrors(dartEntry.allErrors, lineInfo); |
+ _incrementalAnalysisCache = IncrementalAnalysisCache.verifyStructure(_incrementalAnalysisCache, source, task.compilationUnit); |
} else { |
dartCopy.recordParseError(); |
} |
@@ -5588,6 +5590,21 @@ |
class IncrementalAnalysisCache { |
/** |
+ * Determine if the incremental analysis result can be cached for the next incremental analysis. |
+ * |
+ * @param cache the prior incremental analysis cache |
+ * @param unit the incrementally updated compilation unit |
+ * @return the cache used for incremental analysis or `null` if incremental analysis results |
+ * cannot be cached for the next incremental analysis |
+ */ |
+ static IncrementalAnalysisCache cacheResult(IncrementalAnalysisCache cache, CompilationUnit unit) { |
+ if (cache != null && unit != null) { |
+ return new IncrementalAnalysisCache(cache.librarySource, cache.source, unit, cache.newContents, cache.newContents, 0, 0, 0); |
+ } |
+ return null; |
+ } |
+ |
+ /** |
* Determine if the cache should be cleared. |
* |
* @param cache the prior cache or `null` if none |
@@ -5617,20 +5634,19 @@ |
* be performed |
*/ |
static IncrementalAnalysisCache update(IncrementalAnalysisCache cache, Source source, String oldContents, String newContents, int offset, int oldLength, int newLength, SourceEntry sourceEntry) { |
- if (cache == null || cache.source != source) { |
- if (sourceEntry is! DartEntryImpl) { |
- return null; |
- } |
+ Source librarySource = null; |
+ CompilationUnit unit = null; |
+ if (sourceEntry is DartEntryImpl) { |
DartEntryImpl dartEntry = sourceEntry as DartEntryImpl; |
List<Source> librarySources = dartEntry.librariesContaining; |
- if (librarySources.length != 1) { |
- return null; |
+ if (librarySources.length == 1) { |
+ librarySource = librarySources[0]; |
+ if (librarySource != null) { |
+ unit = dartEntry.getValue2(DartEntry.RESOLVED_UNIT, librarySource); |
+ } |
} |
- Source librarySource = librarySources[0]; |
- if (librarySource == null) { |
- return null; |
- } |
- CompilationUnit unit = dartEntry.getValue2(DartEntry.RESOLVED_UNIT, librarySource); |
+ } |
+ if (cache == null || cache.source != source || unit != null) { |
if (unit == null) { |
return null; |
} |
@@ -5642,13 +5658,38 @@ |
} |
return new IncrementalAnalysisCache(librarySource, source, unit, oldContents, newContents, offset, oldLength, newLength); |
} |
- if (cache.offset > offset || offset > cache.offset + cache.newLength) { |
- return null; |
+ if (cache.oldLength == 0 && cache.newLength == 0) { |
+ cache.offset = offset; |
+ cache.oldLength = oldLength; |
+ cache.newLength = newLength; |
+ } else { |
+ if (cache.offset > offset || offset > cache.offset + cache.newLength) { |
+ return null; |
+ } |
+ cache.newLength += newLength - oldLength; |
} |
cache.newContents = newContents; |
- cache.newLength += newLength - oldLength; |
return cache; |
} |
+ |
+ /** |
+ * Verify that the incrementally parsed and resolved unit in the incremental cache is structurally |
+ * equivalent to the fully parsed unit. |
+ * |
+ * @param cache the prior cache or `null` if none |
+ * @param source the source of the compilation unit that was parsed (not `null`) |
+ * @param unit the compilation unit that was just parsed |
+ * @return the cache used for incremental analysis or `null` if incremental analysis results |
+ * cannot be cached for the next incremental analysis |
+ */ |
+ static IncrementalAnalysisCache verifyStructure(IncrementalAnalysisCache cache, Source source, CompilationUnit unit) { |
+ if (cache != null && unit != null && cache.source == source) { |
+ if (!ASTComparator.equals3(cache.resolvedUnit, unit)) { |
+ return null; |
+ } |
+ } |
+ return cache; |
+ } |
Source librarySource; |
Source source; |
String oldContents; |
@@ -5667,6 +5708,13 @@ |
this.oldLength = oldLength; |
this.newLength = newLength; |
} |
+ |
+ /** |
+ * Determine if the cache contains source changes that need to be analyzed |
+ * |
+ * @return `true` if the cache contains changes to be analyzed, else `false` |
+ */ |
+ bool hasWork() => oldLength > 0 && newLength > 0; |
} |
/** |
* Instances of the class `InstrumentedAnalysisContextImpl` implement an |
@@ -6841,7 +6889,7 @@ |
/** |
* The information used to perform incremental analysis. |
*/ |
- IncrementalAnalysisCache _cache; |
+ IncrementalAnalysisCache cache; |
/** |
* The compilation unit that was produced by incrementally updating the existing unit. |
@@ -6855,7 +6903,7 @@ |
* @param cache the incremental analysis cache used to perform the analysis |
*/ |
IncrementalAnalysisTask(InternalAnalysisContext context, IncrementalAnalysisCache cache) : super(context) { |
- this._cache = cache; |
+ this.cache = cache; |
} |
accept(AnalysisTaskVisitor visitor) => visitor.visitIncrementalAnalysisTask(this); |
@@ -6864,13 +6912,13 @@ |
* |
* @return the source |
*/ |
- Source get source => _cache != null ? _cache.source : null; |
- String get taskDescription => "incremental analysis ${(_cache != null ? _cache.source : "null")}"; |
+ Source get source => cache != null ? cache.source : null; |
+ String get taskDescription => "incremental analysis ${(cache != null ? cache.source : "null")}"; |
void internalPerform() { |
- if (_cache == null) { |
+ if (cache == null) { |
return; |
} |
- compilationUnit = _cache.resolvedUnit; |
+ compilationUnit = cache.resolvedUnit; |
} |
} |
/** |