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 79ccb0c82767ff852df8b81aae35db39f855f8bd..ae155e2a7d809cb1673260201a6f400ff80a5dc2 100644 |
--- a/pkg/analyzer/lib/src/generated/engine.dart |
+++ b/pkg/analyzer/lib/src/generated/engine.dart |
@@ -78,6 +78,11 @@ class AnalysisCache { |
return _partitions[i].get(source); |
} |
} |
+ // |
+ // We should never get to this point because the last partition should always be a universal |
+ // partition, except in the case of the SDK context, in which case the source should always be |
+ // part of the SDK. |
+ // |
return null; |
} |
@@ -89,6 +94,28 @@ class AnalysisCache { |
int get astSize => _partitions[_partitions.length - 1].astSize; |
/** |
+ * Return context that owns the given source. |
+ * |
+ * @param source the source whose context is to be returned |
+ * @return the context that owns the partition that contains the source |
+ */ |
+ InternalAnalysisContext getContextFor(Source source) { |
+ int count = _partitions.length; |
+ for (int i = 0; i < count; i++) { |
+ if (_partitions[i].contains(source)) { |
+ return _partitions[i].context; |
+ } |
+ } |
+ // |
+ // We should never get to this point because the last partition should always be a universal |
+ // partition, except in the case of the SDK context, in which case the source should always be |
+ // part of the SDK. |
+ // |
+ AnalysisEngine.instance.logger.logInformation2("Could not find context for ${source.fullName}", new JavaException()); |
+ return null; |
+ } |
+ |
+ /** |
* Return information about each of the partitions in this cache. |
* |
* @return information about each of the partitions in this cache |
@@ -923,7 +950,13 @@ class AnalysisContextImpl implements InternalAnalysisContext { |
* A set containing information about the tasks that have been performed since the last change |
* notification. Used to detect infinite loops in [performAnalysisTask]. |
*/ |
- HashSet<String> _recentTasks = new HashSet<String>(); |
+ LinkedHashSet<String> _recentTasks = new LinkedHashSet<String>(); |
+ |
+ /** |
+ * A flag indicating whether we have already reported an infinite loop in |
+ * [performAnalysisTask]. |
+ */ |
+ bool _reportedLoop = false; |
/** |
* The object used to synchronize access to all of the caches. The rules related to the use of |
@@ -967,7 +1000,7 @@ class AnalysisContextImpl implements InternalAnalysisContext { |
*/ |
AnalysisContextImpl() : super() { |
_resultRecorder = new AnalysisContextImpl_AnalysisTaskResultRecorder(this); |
- _privatePartition = new UniversalCachePartition(AnalysisOptionsImpl.DEFAULT_CACHE_SIZE, new AnalysisContextImpl_ContextRetentionPolicy(this)); |
+ _privatePartition = new UniversalCachePartition(this, AnalysisOptionsImpl.DEFAULT_CACHE_SIZE, new AnalysisContextImpl_ContextRetentionPolicy(this)); |
_cache = createCacheFromSourceFactory(null); |
} |
@@ -1005,6 +1038,7 @@ class AnalysisContextImpl implements InternalAnalysisContext { |
return; |
} |
_recentTasks.clear(); |
+ _reportedLoop = false; |
// |
// First, compute the list of sources that have been removed. |
// |
@@ -1303,6 +1337,12 @@ class AnalysisContextImpl implements InternalAnalysisContext { |
} |
@override |
+ InternalAnalysisContext getContextFor(Source source) { |
+ InternalAnalysisContext context = _cache.getContextFor(source); |
+ return context == null ? this : context; |
+ } |
+ |
+ @override |
DeclaredVariables get declaredVariables => _declaredVariables; |
@override |
@@ -1731,14 +1771,16 @@ class AnalysisContextImpl implements InternalAnalysisContext { |
return new AnalysisResult(_getChangeNotices(true), getEnd - getStart, null, -1); |
} |
String taskDescription = task.toString(); |
- // if (recentTasks.add(taskDescription)) { |
- // logInformation("Performing task: " + taskDescription); |
- // } else { |
- // if (TRACE_PERFORM_TASK) { |
- // System.out.print("* "); |
- // } |
- // logInformation("*** Performing repeated task: " + taskDescription); |
- // } |
+ if (!_reportedLoop && !_recentTasks.add(taskDescription)) { |
+ PrintStringWriter writer = new PrintStringWriter(); |
+ writer.print("Performing repeated task: "); |
+ writer.println(taskDescription); |
+ for (String description in _recentTasks) { |
+ writer.print(" "); |
+ writer.println(description); |
+ } |
+ _logInformation(writer.toString()); |
+ } |
_notifyAboutToPerformTask(taskDescription); |
if (_TRACE_PERFORM_TASK) { |
print(taskDescription); |
@@ -1785,13 +1827,24 @@ class AnalysisContextImpl implements InternalAnalysisContext { |
if (dartEntry != null) { |
DartEntryImpl dartCopy = dartEntry.writableCopy; |
_recordElementData(dartCopy, library, library.source, htmlSource); |
- dartCopy.setValue(DartEntry.SCAN_ERRORS, AnalysisError.NO_ERRORS); |
+ dartCopy.setState(SourceEntry.CONTENT, CacheState.FLUSHED); |
+ dartCopy.setValue(SourceEntry.LINE_INFO, new LineInfo(<int> [0])); |
+ dartCopy.setValue(DartEntry.ANGULAR_ERRORS, AnalysisError.NO_ERRORS); |
+ // DartEntry.ELEMENT - set in recordElementData |
+ dartCopy.setValue(DartEntry.EXPORTED_LIBRARIES, Source.EMPTY_ARRAY); |
+ dartCopy.setValue(DartEntry.IMPORTED_LIBRARIES, Source.EMPTY_ARRAY); |
+ dartCopy.setValue(DartEntry.INCLUDED_PARTS, Source.EMPTY_ARRAY); |
+ // DartEntry.IS_CLIENT - set in recordElementData |
+ // DartEntry.IS_LAUNCHABLE - set in recordElementData |
dartCopy.setValue(DartEntry.PARSE_ERRORS, AnalysisError.NO_ERRORS); |
dartCopy.setState(DartEntry.PARSED_UNIT, CacheState.FLUSHED); |
+ dartCopy.setState(DartEntry.PUBLIC_NAMESPACE, CacheState.FLUSHED); |
+ dartCopy.setValue(DartEntry.SCAN_ERRORS, AnalysisError.NO_ERRORS); |
+ dartCopy.setValue(DartEntry.SOURCE_KIND, SourceKind.LIBRARY); |
+ dartCopy.setState(DartEntry.TOKEN_STREAM, CacheState.FLUSHED); |
dartCopy.setValueInLibrary(DartEntry.RESOLUTION_ERRORS, librarySource, AnalysisError.NO_ERRORS); |
dartCopy.setStateInLibrary(DartEntry.RESOLVED_UNIT, librarySource, CacheState.FLUSHED); |
dartCopy.setValueInLibrary(DartEntry.VERIFICATION_ERRORS, librarySource, AnalysisError.NO_ERRORS); |
- dartCopy.setValue(DartEntry.ANGULAR_ERRORS, AnalysisError.NO_ERRORS); |
dartCopy.setValueInLibrary(DartEntry.HINTS, librarySource, AnalysisError.NO_ERRORS); |
_cache.put(librarySource, dartCopy); |
} |
@@ -1882,6 +1935,7 @@ class AnalysisContextImpl implements InternalAnalysisContext { |
@override |
void setChangedContents(Source source, String contents, int offset, int oldLength, int newLength) { |
_recentTasks.clear(); |
+ _reportedLoop = false; |
String originalContents = _contentCache.setContents(source, contents); |
if (contents != null) { |
if (contents != originalContents) { |
@@ -1906,6 +1960,7 @@ class AnalysisContextImpl implements InternalAnalysisContext { |
@override |
void setContents(Source source, String contents) { |
_recentTasks.clear(); |
+ _reportedLoop = false; |
String originalContents = _contentCache.setContents(source, contents); |
if (contents != null) { |
if (contents != originalContents) { |
@@ -3731,6 +3786,8 @@ class AnalysisContextImpl implements InternalAnalysisContext { |
} |
} |
_removeFromPartsUsingMap(oldPartMap); |
+ _recentTasks.clear(); |
+ _reportedLoop = false; |
} |
/** |
@@ -6761,7 +6818,7 @@ abstract class AnalysisTask { |
} on AnalysisException catch (exception) { |
throw exception; |
} catch (exception, stackTrace) { |
- throw new AnalysisException("Exception", new CaughtException(exception, stackTrace)); |
+ throw new AnalysisException(exception.toString(), new CaughtException(exception, stackTrace)); |
} |
} |
} |
@@ -7468,7 +7525,7 @@ class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> { |
_unitElement = new CompilationUnitElementImpl(unitName); |
_unitElement.source = _source; |
// create LibraryElementImpl |
- _libraryElement = new LibraryElementImpl.forNode(_context, null); |
+ _libraryElement = new LibraryElementImpl.forNode(_context.getContextFor(_source), null); |
_libraryElement.definingCompilationUnit = _unitElement; |
_libraryElement.angularHtml = true; |
_injectedLibraries.add(_libraryElement); |
@@ -7832,9 +7889,10 @@ abstract class AngularXmlExpression extends ht.XmlExpression { |
*/ |
abstract class CachePartition { |
/** |
- * A table mapping the sources known to the context to the information known about the source. |
+ * The context that owns this partition. Multiple contexts can reference a partition, but only one |
+ * context can own it. |
*/ |
- HashMap<Source, SourceEntry> _sourceMap = new HashMap<Source, SourceEntry>(); |
+ final InternalAnalysisContext context; |
/** |
* The maximum number of sources for which AST structures should be kept in the cache. |
@@ -7847,6 +7905,12 @@ abstract class CachePartition { |
final CacheRetentionPolicy _retentionPolicy; |
/** |
+ * A table mapping the sources belonging to this partition to the information known about those |
+ * sources. |
+ */ |
+ HashMap<Source, SourceEntry> _sourceMap = new HashMap<Source, SourceEntry>(); |
+ |
+ /** |
* A list containing the most recently accessed sources with the most recently used at the end of |
* the list. When more sources are added than the maximum allowed then the least recently used |
* source will be removed and will have it's cached AST structure flushed. |
@@ -7857,12 +7921,13 @@ abstract class CachePartition { |
* Initialize a newly created cache to maintain at most the given number of AST structures in the |
* cache. |
* |
+ * @param context the context that owns this partition |
* @param maxCacheSize the maximum number of sources for which AST structures should be kept in |
* the cache |
* @param retentionPolicy the policy used to determine which pieces of data to remove from the |
* cache |
*/ |
- CachePartition(int maxCacheSize, this._retentionPolicy) { |
+ CachePartition(this.context, int maxCacheSize, this._retentionPolicy) { |
this._maxCacheSize = maxCacheSize; |
_recentlyUsed = new List<Source>(); |
} |
@@ -11793,6 +11858,18 @@ class InstrumentedAnalysisContextImpl implements InternalAnalysisContext { |
TimestampedData<String> getContents(Source source) => _basis.getContents(source); |
@override |
+ InternalAnalysisContext getContextFor(Source source) { |
+ InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getContextFor"); |
+ _checkThread(instrumentation); |
+ try { |
+ instrumentation.metric3("contextId", _contextId); |
+ return _basis.getContextFor(source); |
+ } finally { |
+ instrumentation.log(); |
+ } |
+ } |
+ |
+ @override |
DeclaredVariables get declaredVariables => _basis.declaredVariables; |
@override |
@@ -12360,6 +12437,14 @@ abstract class InternalAnalysisContext implements AnalysisContext { |
InternalAnalysisContext extractContextInto(SourceContainer container, InternalAnalysisContext newContext); |
/** |
+ * Return context that owns the given source. |
+ * |
+ * @param source the source whose context is to be returned |
+ * @return the context that owns the partition that contains the source |
+ */ |
+ InternalAnalysisContext getContextFor(Source source); |
+ |
+ /** |
* Return an array containing all of the sources that have been marked as priority sources. |
* Clients must not modify the returned array. |
* |
@@ -13142,7 +13227,7 @@ class PartitionManager { |
SdkCachePartition forSdk(DartSdk sdk) { |
SdkCachePartition partition = _sdkPartitions[sdk]; |
if (partition == null) { |
- partition = new SdkCachePartition(_DEFAULT_SDK_CACHE_SIZE); |
+ partition = new SdkCachePartition(sdk.context as InternalAnalysisContext, _DEFAULT_SDK_CACHE_SIZE); |
_sdkPartitions[sdk] = partition; |
} |
return partition; |
@@ -14724,10 +14809,11 @@ class SdkCachePartition extends CachePartition { |
/** |
* Initialize a newly created partition. |
* |
+ * @param context the context that owns this partition |
* @param maxCacheSize the maximum number of sources for which AST structures should be kept in |
* the cache |
*/ |
- SdkCachePartition(int maxCacheSize) : super(maxCacheSize, DefaultRetentionPolicy.POLICY); |
+ SdkCachePartition(InternalAnalysisContext context, int maxCacheSize) : super(context, maxCacheSize, DefaultRetentionPolicy.POLICY); |
@override |
bool contains(Source source) => source.isInSystemLibrary; |
@@ -15278,12 +15364,13 @@ class UniversalCachePartition extends CachePartition { |
/** |
* Initialize a newly created partition. |
* |
+ * @param context the context that owns this partition |
* @param maxCacheSize the maximum number of sources for which AST structures should be kept in |
* the cache |
* @param retentionPolicy the policy used to determine which pieces of data to remove from the |
* cache |
*/ |
- UniversalCachePartition(int maxCacheSize, CacheRetentionPolicy retentionPolicy) : super(maxCacheSize, retentionPolicy); |
+ UniversalCachePartition(InternalAnalysisContext context, int maxCacheSize, CacheRetentionPolicy retentionPolicy) : super(context, maxCacheSize, retentionPolicy); |
@override |
bool contains(Source source) => true; |