| Index: pkg/analyzer_experimental/lib/src/generated/engine.dart
|
| diff --git a/pkg/analyzer_experimental/lib/src/generated/engine.dart b/pkg/analyzer_experimental/lib/src/generated/engine.dart
|
| index 909e4f7b03aac67c00b1051740ca73590d472436..4c6d3d79909db707046566e0d3ecb381cbe6cc97 100644
|
| --- a/pkg/analyzer_experimental/lib/src/generated/engine.dart
|
| +++ b/pkg/analyzer_experimental/lib/src/generated/engine.dart
|
| @@ -82,16 +82,26 @@ class AnalysisEngine {
|
| Logger _logger = Logger.NULL;
|
|
|
| /**
|
| + * A flag indicating whether the new analysis context should be created.
|
| + */
|
| + bool _useExperimentalContext = false;
|
| +
|
| + /**
|
| * Create a new context in which analysis can be performed.
|
| *
|
| * @return the analysis context that was created
|
| */
|
| AnalysisContext createAnalysisContext() {
|
| if (Instrumentation.isNullLogger) {
|
| + if (_useExperimentalContext) {
|
| + return new DelegatingAnalysisContextImpl2();
|
| + }
|
| return new DelegatingAnalysisContextImpl();
|
| - } else {
|
| - return new InstrumentedAnalysisContextImpl.con1(new DelegatingAnalysisContextImpl());
|
| }
|
| + if (_useExperimentalContext) {
|
| + return new InstrumentedAnalysisContextImpl.con1(new DelegatingAnalysisContextImpl2());
|
| + }
|
| + return new InstrumentedAnalysisContextImpl.con1(new DelegatingAnalysisContextImpl());
|
| }
|
|
|
| /**
|
| @@ -102,6 +112,13 @@ class AnalysisEngine {
|
| Logger get logger => _logger;
|
|
|
| /**
|
| + * Return `true` if the new analysis context should be created.
|
| + *
|
| + * @return `true` if the new analysis context should be created
|
| + */
|
| + bool get useExperimentalContext => _useExperimentalContext;
|
| +
|
| + /**
|
| * Set the logger that should receive information about errors within the analysis engine to the
|
| * given logger.
|
| *
|
| @@ -111,6 +128,15 @@ class AnalysisEngine {
|
| void set logger(Logger logger2) {
|
| this._logger = logger2 == null ? Logger.NULL : logger2;
|
| }
|
| +
|
| + /**
|
| + * Set whether the new analysis context should be created to the given flag.
|
| + *
|
| + * @param use `true` if the new analysis context should be created
|
| + */
|
| + void set useExperimentalContext(bool use) {
|
| + _useExperimentalContext = use;
|
| + }
|
| }
|
| /**
|
| * Container with statistics about the [AnalysisContext].
|
| @@ -523,6 +549,8 @@ abstract class AnalysisContext {
|
|
|
| /**
|
| * Parse and resolve a single source within the given context to produce a fully resolved AST.
|
| + * Return the resolved AST structure, or `null` if the source could not be either parsed or
|
| + * resolved.
|
| *
|
| * @param unitSource the source to be parsed and resolved
|
| * @param librarySource the source of the defining compilation unit of the library containing the
|
| @@ -917,6 +945,15 @@ class AnalysisCache {
|
| }
|
|
|
| /**
|
| + * Remove all information related to the given source from this cache.
|
| + *
|
| + * @param source the source to be removed
|
| + */
|
| + void remove(Source source) {
|
| + _sourceMap.remove(source);
|
| + }
|
| +
|
| + /**
|
| * Set the sources for which data should not be flushed to the given array.
|
| *
|
| * @param sources the sources for which data should not be flushed
|
| @@ -1501,6 +1538,34 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| }
|
|
|
| /**
|
| + * Record that an in-process parse has stopped without recording results because the results were
|
| + * invalidated before they could be recorded.
|
| + */
|
| + void recordParseNotInProcess() {
|
| + if (identical(getState(SourceEntry.LINE_INFO), CacheState.IN_PROCESS)) {
|
| + setState(SourceEntry.LINE_INFO, CacheState.INVALID);
|
| + }
|
| + if (identical(_sourceKindState, CacheState.IN_PROCESS)) {
|
| + _sourceKindState = CacheState.INVALID;
|
| + }
|
| + if (identical(_parseErrorsState, CacheState.IN_PROCESS)) {
|
| + _parseErrorsState = CacheState.INVALID;
|
| + }
|
| + if (identical(_parsedUnitState, CacheState.IN_PROCESS)) {
|
| + _parsedUnitState = CacheState.INVALID;
|
| + }
|
| + if (identical(_exportedLibrariesState, CacheState.IN_PROCESS)) {
|
| + _exportedLibrariesState = CacheState.INVALID;
|
| + }
|
| + if (identical(_importedLibrariesState, CacheState.IN_PROCESS)) {
|
| + _importedLibrariesState = CacheState.INVALID;
|
| + }
|
| + if (identical(_includedPartsState, CacheState.IN_PROCESS)) {
|
| + _includedPartsState = CacheState.INVALID;
|
| + }
|
| + }
|
| +
|
| + /**
|
| * Record that an error occurred while attempting to scan or parse the entry represented by this
|
| * entry. This will set the state of all resolution-based information as being in error, but will
|
| * not change the state of any parse results.
|
| @@ -1517,6 +1582,26 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| }
|
|
|
| /**
|
| + * Record that an in-process parse has stopped without recording results because the results were
|
| + * invalidated before they could be recorded.
|
| + */
|
| + void recordResolutionNotInProcess() {
|
| + if (identical(_elementState, CacheState.IN_PROCESS)) {
|
| + _elementState = CacheState.INVALID;
|
| + }
|
| + if (identical(_clientServerState, CacheState.IN_PROCESS)) {
|
| + _clientServerState = CacheState.INVALID;
|
| + }
|
| + if (identical(_launchableState, CacheState.IN_PROCESS)) {
|
| + _launchableState = CacheState.INVALID;
|
| + }
|
| + if (identical(_publicNamespaceState, CacheState.IN_PROCESS)) {
|
| + _publicNamespaceState = CacheState.INVALID;
|
| + }
|
| + _resolutionState.recordResolutionNotInProcess();
|
| + }
|
| +
|
| + /**
|
| * Remove any resolution information associated with this compilation unit being part of the given
|
| * library, presumably because it is no longer part of the library.
|
| *
|
| @@ -1910,6 +1995,25 @@ class DartEntryImpl_ResolutionState {
|
| }
|
|
|
| /**
|
| + * Record that an in-process parse has stopped without recording results because the results
|
| + * were invalidated before they could be recorded.
|
| + */
|
| + void recordResolutionNotInProcess() {
|
| + if (identical(_resolvedUnitState, CacheState.IN_PROCESS)) {
|
| + _resolvedUnitState = CacheState.INVALID;
|
| + }
|
| + if (identical(_resolutionErrorsState, CacheState.IN_PROCESS)) {
|
| + _resolutionErrorsState = CacheState.INVALID;
|
| + }
|
| + if (identical(_hintsState, CacheState.IN_PROCESS)) {
|
| + _hintsState = CacheState.INVALID;
|
| + }
|
| + if (_nextState != null) {
|
| + _nextState.recordResolutionNotInProcess();
|
| + }
|
| + }
|
| +
|
| + /**
|
| * Write a textual representation of this state to the given builder. The result will only be
|
| * used for debugging purposes.
|
| *
|
| @@ -2099,7 +2203,19 @@ class HtmlEntryImpl extends SourceEntryImpl implements HtmlEntry {
|
| }
|
|
|
| /**
|
| - * Invalidate all of the resolution information associated with the compilation unit.
|
| + * Invalidate all of the information associated with the HTML file.
|
| + */
|
| + void invalidateAllInformation() {
|
| + setState(SourceEntry.LINE_INFO, CacheState.INVALID);
|
| + _parsedUnit = null;
|
| + _parsedUnitState = CacheState.INVALID;
|
| + _referencedLibraries = Source.EMPTY_ARRAY;
|
| + _referencedLibrariesState = CacheState.INVALID;
|
| + invalidateAllResolutionInformation();
|
| + }
|
| +
|
| + /**
|
| + * Invalidate all of the resolution information associated with the HTML file.
|
| */
|
| void invalidateAllResolutionInformation() {
|
| _element = null;
|
| @@ -2109,6 +2225,15 @@ class HtmlEntryImpl extends SourceEntryImpl implements HtmlEntry {
|
| _hints = AnalysisError.NO_ERRORS;
|
| _hintsState = CacheState.INVALID;
|
| }
|
| +
|
| + /**
|
| + * Record that an error was encountered while attempting to resolve the source associated with
|
| + * this entry.
|
| + */
|
| + void recordResolutionError() {
|
| + setState(HtmlEntry.ELEMENT, CacheState.ERROR);
|
| + setState(HtmlEntry.RESOLUTION_ERRORS, CacheState.ERROR);
|
| + }
|
| void setState(DataDescriptor descriptor, CacheState state) {
|
| if (identical(descriptor, HtmlEntry.ELEMENT)) {
|
| _element = updatedValue(state, _element, null);
|
| @@ -2368,7 +2493,13 @@ class AnalysisContentStatisticsImpl implements AnalysisContentStatistics {
|
| Iterable<AnalysisContentStatistics_CacheRow> items = _dataMap.values;
|
| return new List.from(items);
|
| }
|
| - void putCacheItem(DataDescriptor rowDesc, CacheState state) {
|
| + void putCacheItem(DartEntry dartEntry, DataDescriptor descriptor) {
|
| + putCacheItem3(descriptor, dartEntry.getState(descriptor));
|
| + }
|
| + void putCacheItem2(DartEntry dartEntry, Source librarySource, DataDescriptor descriptor) {
|
| + putCacheItem3(descriptor, dartEntry.getState2(descriptor, librarySource));
|
| + }
|
| + void putCacheItem3(DataDescriptor rowDesc, CacheState state) {
|
| String rowName = rowDesc.toString();
|
| AnalysisContentStatisticsImpl_CacheRowImpl row = _dataMap[rowName] as AnalysisContentStatisticsImpl_CacheRowImpl;
|
| if (row == null) {
|
| @@ -2426,7 +2557,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * object.
|
| */
|
| static void putStatCacheItem(AnalysisContentStatisticsImpl statistics, DartEntry dartEntry, Source librarySource, DataDescriptor key) {
|
| - statistics.putCacheItem(key, dartEntry.getState2(key, librarySource));
|
| + statistics.putCacheItem3(key, dartEntry.getState2(key, librarySource));
|
| }
|
|
|
| /**
|
| @@ -2434,7 +2565,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * statistics object.
|
| */
|
| static void putStatCacheItem2(AnalysisContentStatisticsImpl statistics, SourceEntry entry, DataDescriptor key) {
|
| - statistics.putCacheItem(key, entry.getState(key));
|
| + statistics.putCacheItem3(key, entry.getState(key));
|
| }
|
|
|
| /**
|
| @@ -2515,6 +2646,15 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * in Dart.
|
| */
|
| static String _TYPE_DART = "application/dart";
|
| +
|
| + /**
|
| + * Initialize a newly created analysis context.
|
| + */
|
| + AnalysisContextImpl() : super() {
|
| + if (AnalysisEngine.instance.useExperimentalContext) {
|
| + throw new RuntimeException("Should not be creating an instance of AnalysisContextImpl");
|
| + }
|
| + }
|
| void addSourceInfo(Source source, SourceEntry info) {
|
| _sourceMap[source] = info;
|
| }
|
| @@ -2686,6 +2826,18 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| internalParseDart(source);
|
| }
|
| }
|
| + ResolvableHtmlUnit computeResolvableHtmlUnit(Source source) {
|
| + HtmlEntry htmlEntry = getReadableHtmlEntry(source);
|
| + if (htmlEntry == null) {
|
| + throw new AnalysisException.con1("computeResolvableHtmlUnit invoked for non-HTML file: ${source.fullName}");
|
| + }
|
| + htmlEntry = internalCacheHtmlParseData(source, htmlEntry, [HtmlEntry.PARSED_UNIT]);
|
| + HtmlUnit unit = htmlEntry.getValue(HtmlEntry.PARSED_UNIT);
|
| + if (unit == null) {
|
| + throw new AnalysisException.con1("Internal error: computeResolvableHtmlUnit could not parse ${source.fullName}");
|
| + }
|
| + return new ResolvableHtmlUnit(htmlEntry.modificationTime, unit);
|
| + }
|
| AnalysisContext extractContext(SourceContainer container) => extractContextInto(container, AnalysisEngine.instance.createAnalysisContext() as InternalAnalysisContext);
|
| InternalAnalysisContext extractContextInto(SourceContainer container, InternalAnalysisContext newContext) {
|
| List<Source> sourcesToRemove = new List<Source>();
|
| @@ -4826,1278 +4978,4129 @@ class Source_ContentReceiver_7 implements Source_ContentReceiver {
|
| }
|
| }
|
| /**
|
| - * Instances of the class `AnalysisErrorInfoImpl` represent the analysis errors and line info
|
| - * associated with a source.
|
| + * Instances of the class `AnalysisContextImpl` implement an [AnalysisContext].
|
| + *
|
| + * @coverage dart.engine
|
| */
|
| -class AnalysisErrorInfoImpl implements AnalysisErrorInfo {
|
| +class AnalysisContextImpl2 implements InternalAnalysisContext {
|
|
|
| /**
|
| - * The analysis errors associated with a source, or `null` if there are no errors.
|
| + * The set of analysis options controlling the behavior of this context.
|
| */
|
| - List<AnalysisError> _errors;
|
| + AnalysisOptions _options = new AnalysisOptionsImpl();
|
|
|
| /**
|
| - * The line information associated with the errors, or `null` if there are no errors.
|
| + * The source factory used to create the sources that can be analyzed in this context.
|
| */
|
| - LineInfo _lineInfo;
|
| + SourceFactory _sourceFactory;
|
|
|
| /**
|
| - * Initialize an newly created error info with the errors and line information
|
| - *
|
| - * @param errors the errors as a result of analysis
|
| - * @param lineinfo the line info for the errors
|
| + * A table mapping the sources known to the context to the information known about the source.
|
| */
|
| - AnalysisErrorInfoImpl(List<AnalysisError> errors, LineInfo lineInfo) {
|
| - this._errors = errors;
|
| - this._lineInfo = lineInfo;
|
| - }
|
| + AnalysisCache _cache = new AnalysisCache(_MAX_CACHE_SIZE);
|
|
|
| /**
|
| - * Return the errors of analysis, or `null` if there were no errors.
|
| - *
|
| - * @return the errors as a result of the analysis
|
| + * A table mapping sources to the change notices that are waiting to be returned related to that
|
| + * source.
|
| */
|
| - List<AnalysisError> get errors => _errors;
|
| + Map<Source, ChangeNoticeImpl> _pendingNotices = new Map<Source, ChangeNoticeImpl>();
|
|
|
| /**
|
| - * Return the line information associated with the errors, or `null` if there were no
|
| - * errors.
|
| + * The object used to synchronize access to all of the caches. The rules related to the use of
|
| + * this lock object are
|
| + *
|
| + * * no analysis work is done while holding the lock, and
|
| + * * no analysis results can be recorded unless we have obtained the lock and validated that the
|
| + * results are for the same version (modification time) of the source as our current cache
|
| + * content.
|
| *
|
| - * @return the line information associated with the errors
|
| */
|
| - LineInfo get lineInfo => _lineInfo;
|
| -}
|
| -/**
|
| - * Instances of the class `AnalysisOptions` represent a set of analysis options used to
|
| - * control the behavior of an analysis context.
|
| - */
|
| -class AnalysisOptionsImpl implements AnalysisOptions {
|
| + Object _cacheLock = new Object();
|
|
|
| /**
|
| - * A flag indicating whether analysis is to use strict mode. In strict mode, error reporting is
|
| - * based exclusively on the static type information.
|
| + * The object used to record the results of performing an analysis task.
|
| */
|
| - bool _strictMode = true;
|
| + AnalysisContextImpl2_AnalysisTaskResultRecorder _resultRecorder;
|
|
|
| /**
|
| - * A flag indicating whether analysis is to generate hint results (e.g. type inference based
|
| - * information and pub best practices).
|
| + * The maximum number of sources for which data should be kept in the cache.
|
| */
|
| - bool _hint = true;
|
| - bool get hint => _hint;
|
| + static int _MAX_CACHE_SIZE = 64;
|
|
|
| /**
|
| - * Return `true` if analysis is to use strict mode. In strict mode, error reporting is based
|
| - * exclusively on the static type information.
|
| + * The maximum number of sources that can be on the priority list. This <b>must</b> be less than
|
| + * the [MAX_CACHE_SIZE] in order to prevent an infinite loop in performAnalysisTask().
|
| *
|
| - * @return `true` if analysis is to use strict mode
|
| + * @see #setAnalysisPriorityOrder(List)
|
| */
|
| - bool get strictMode => _strictMode;
|
| + static int _MAX_PRIORITY_LIST_SIZE = _MAX_CACHE_SIZE - 4;
|
|
|
| /**
|
| - * Set whether analysis is to generate hint results (e.g. type inference based information and pub
|
| - * best practices).
|
| - *
|
| - * @param hint `true` if analysis is to generate hint results
|
| + * Initialize a newly created analysis context.
|
| */
|
| - void set hint(bool hint2) {
|
| - this._hint = hint2;
|
| + AnalysisContextImpl2() : super() {
|
| + _resultRecorder = new AnalysisContextImpl2_AnalysisTaskResultRecorder(this);
|
| }
|
| -
|
| - /**
|
| - * Set whether analysis is to use strict mode to the given value. In strict mode, error reporting
|
| - * is based exclusively on the static type information.
|
| - *
|
| - * @param isStrict `true` if analysis is to use strict mode
|
| - */
|
| - void set strictMode(bool isStrict) {
|
| - _strictMode = isStrict;
|
| + void addSourceInfo(Source source, SourceEntry info) {
|
| + _cache.put(source, info);
|
| }
|
| -}
|
| -/**
|
| - * The enumeration `CacheState` defines the possible states of cached data.
|
| - */
|
| -class CacheState extends Enum<CacheState> {
|
| -
|
| - /**
|
| - * The data is not in the cache and the last time an attempt was made to compute the data an
|
| - * exception occurred, making it pointless to attempt.
|
| - *
|
| - * Valid Transitions:
|
| - *
|
| - * * [INVALID] if a source was modified that might cause the data to be computable
|
| - *
|
| - */
|
| - static final CacheState ERROR = new CacheState('ERROR', 0);
|
| -
|
| - /**
|
| - * The data is not in the cache because it was flushed from the cache in order to control memory
|
| - * usage. If the data is recomputed, results do not need to be reported.
|
| - *
|
| - * Valid Transitions:
|
| - *
|
| - * * [IN_PROCESS] if the data is being recomputed
|
| - * * [INVALID] if a source was modified that causes the data to need to be recomputed
|
| - *
|
| - */
|
| - static final CacheState FLUSHED = new CacheState('FLUSHED', 1);
|
| -
|
| - /**
|
| - * The data might or might not be in the cache but is in the process of being recomputed.
|
| - *
|
| - * Valid Transitions:
|
| - *
|
| - * * [ERROR] if an exception occurred while trying to compute the data
|
| - * * [VALID] if the data was successfully computed and stored in the cache
|
| - *
|
| - */
|
| - static final CacheState IN_PROCESS = new CacheState('IN_PROCESS', 2);
|
| -
|
| - /**
|
| - * The data is not in the cache and needs to be recomputed so that results can be reported.
|
| - *
|
| - * Valid Transitions:
|
| - *
|
| - * * [IN_PROCESS] if an attempt is being made to recompute the data
|
| - *
|
| - */
|
| - static final CacheState INVALID = new CacheState('INVALID', 3);
|
| -
|
| - /**
|
| - * The data is in the cache and up-to-date.
|
| - *
|
| - * Valid Transitions:
|
| - *
|
| - * * [FLUSHED] if the data is removed in order to manage memory usage
|
| - * * [INVALID] if a source was modified in such a way as to invalidate the previous data
|
| - *
|
| - */
|
| - static final CacheState VALID = new CacheState('VALID', 4);
|
| - static final List<CacheState> values = [ERROR, FLUSHED, IN_PROCESS, INVALID, VALID];
|
| - CacheState(String name, int ordinal) : super(name, ordinal);
|
| -}
|
| -/**
|
| - * Instances of the class `ChangeNoticeImpl` represent a change to the analysis results
|
| - * associated with a given source.
|
| - *
|
| - * @coverage dart.engine
|
| - */
|
| -class ChangeNoticeImpl implements ChangeNotice {
|
| -
|
| - /**
|
| - * The source for which the result is being reported.
|
| - */
|
| - Source _source;
|
| -
|
| - /**
|
| - * The fully resolved AST that changed as a result of the analysis, or `null` if the AST was
|
| - * not changed.
|
| - */
|
| - CompilationUnit _compilationUnit;
|
| -
|
| - /**
|
| - * The errors that changed as a result of the analysis, or `null` if errors were not
|
| - * changed.
|
| - */
|
| - List<AnalysisError> _errors;
|
| -
|
| - /**
|
| - * The line information associated with the source, or `null` if errors were not changed.
|
| - */
|
| - LineInfo _lineInfo;
|
| -
|
| - /**
|
| - * An empty array of change notices.
|
| - */
|
| - static List<ChangeNoticeImpl> EMPTY_ARRAY = new List<ChangeNoticeImpl>(0);
|
| -
|
| - /**
|
| - * Initialize a newly created notice associated with the given source.
|
| - *
|
| - * @param source the source for which the change is being reported
|
| - */
|
| - ChangeNoticeImpl(Source source) {
|
| - this._source = source;
|
| - }
|
| -
|
| - /**
|
| - * Return the fully resolved AST that changed as a result of the analysis, or `null` if the
|
| - * AST was not changed.
|
| - *
|
| - * @return the fully resolved AST that changed as a result of the analysis
|
| - */
|
| - CompilationUnit get compilationUnit => _compilationUnit;
|
| -
|
| - /**
|
| - * Return the errors that changed as a result of the analysis, or `null` if errors were not
|
| - * changed.
|
| - *
|
| - * @return the errors that changed as a result of the analysis
|
| - */
|
| - List<AnalysisError> get errors => _errors;
|
| -
|
| - /**
|
| - * Return the line information associated with the source, or `null` if errors were not
|
| - * changed.
|
| - *
|
| - * @return the line information associated with the source
|
| - */
|
| - LineInfo get lineInfo => _lineInfo;
|
| -
|
| - /**
|
| - * Return the source for which the result is being reported.
|
| - *
|
| - * @return the source for which the result is being reported
|
| - */
|
| - Source get source => _source;
|
| -
|
| - /**
|
| - * Set the fully resolved AST that changed as a result of the analysis to the given AST.
|
| - *
|
| - * @param compilationUnit the fully resolved AST that changed as a result of the analysis
|
| - */
|
| - void set compilationUnit(CompilationUnit compilationUnit2) {
|
| - this._compilationUnit = compilationUnit2;
|
| - }
|
| -
|
| - /**
|
| - * Set the errors that changed as a result of the analysis to the given errors and set the line
|
| - * information to the given line information.
|
| - *
|
| - * @param errors the errors that changed as a result of the analysis
|
| - * @param lineInfo the line information associated with the source
|
| - */
|
| - void setErrors(List<AnalysisError> errors2, LineInfo lineInfo2) {
|
| - this._errors = errors2;
|
| - this._lineInfo = lineInfo2;
|
| - }
|
| -}
|
| -/**
|
| - * Instances of the class `DelegatingAnalysisContextImpl` extend [AnalysisContextImpl
|
| - ] to delegate sources to the appropriate analysis context. For instance, if the
|
| - * source is in a system library then the analysis context from the [DartSdk] is used.
|
| - *
|
| - * @coverage dart.engine
|
| - */
|
| -class DelegatingAnalysisContextImpl extends AnalysisContextImpl {
|
| -
|
| - /**
|
| - * This references the [InternalAnalysisContext] held onto by the [DartSdk] which is
|
| - * used (instead of this [AnalysisContext]) for SDK sources. This field is set when
|
| - * #setSourceFactory(SourceFactory) is called, and references the analysis context in the
|
| - * [DartUriResolver] in the [SourceFactory], this analysis context assumes that there
|
| - * will be such a resolver.
|
| - */
|
| - InternalAnalysisContext _sdkAnalysisContext;
|
| - void addSourceInfo(Source source, SourceEntry info) {
|
| - if (source.isInSystemLibrary) {
|
| - _sdkAnalysisContext.addSourceInfo(source, info);
|
| - } else {
|
| - super.addSourceInfo(source, info);
|
| + void applyChanges(ChangeSet changeSet) {
|
| + if (changeSet.isEmpty) {
|
| + return;
|
| }
|
| - }
|
| - List<AnalysisError> computeErrors(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.computeErrors(source);
|
| - } else {
|
| - return super.computeErrors(source);
|
| + {
|
| + List<Source> removedSources = new List<Source>.from(changeSet.removed);
|
| + for (SourceContainer container in changeSet.removedContainers) {
|
| + addSourcesInContainer(removedSources, container);
|
| + }
|
| + bool addedDartSource = false;
|
| + for (Source source in changeSet.added3) {
|
| + if (sourceAvailable(source)) {
|
| + addedDartSource = true;
|
| + }
|
| + }
|
| + for (Source source in changeSet.changed3) {
|
| + sourceChanged(source);
|
| + }
|
| + for (Source source in removedSources) {
|
| + sourceRemoved(source);
|
| + }
|
| + if (addedDartSource) {
|
| + for (MapEntry<Source, SourceEntry> mapEntry in _cache.entrySet()) {
|
| + if (!mapEntry.getKey().isInSystemLibrary && mapEntry.getValue() is DartEntry) {
|
| + DartEntryImpl dartCopy = ((mapEntry.getValue() as DartEntry)).writableCopy;
|
| + dartCopy.invalidateAllResolutionInformation();
|
| + mapEntry.setValue(dartCopy);
|
| + }
|
| + }
|
| + }
|
| }
|
| }
|
| - List<Source> computeExportedLibraries(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.computeExportedLibraries(source);
|
| - } else {
|
| - return super.computeExportedLibraries(source);
|
| + String computeDocumentationComment(Element element) {
|
| + if (element == null) {
|
| + return null;
|
| }
|
| - }
|
| - HtmlElement computeHtmlElement(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.computeHtmlElement(source);
|
| - } else {
|
| - return super.computeHtmlElement(source);
|
| + Source source = element.source;
|
| + if (source == null) {
|
| + return null;
|
| }
|
| - }
|
| - List<Source> computeImportedLibraries(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.computeImportedLibraries(source);
|
| - } else {
|
| - return super.computeImportedLibraries(source);
|
| + CompilationUnit unit = parseCompilationUnit(source);
|
| + if (unit == null) {
|
| + return null;
|
| + }
|
| + NodeLocator locator = new NodeLocator.con1(element.nameOffset);
|
| + ASTNode nameNode = locator.searchWithin(unit);
|
| + while (nameNode != null) {
|
| + if (nameNode is AnnotatedNode) {
|
| + Comment comment = ((nameNode as AnnotatedNode)).documentationComment;
|
| + if (comment == null) {
|
| + return null;
|
| + }
|
| + JavaStringBuilder builder = new JavaStringBuilder();
|
| + List<Token> tokens = comment.tokens;
|
| + for (int i = 0; i < tokens.length; i++) {
|
| + if (i > 0) {
|
| + builder.append('\n');
|
| + }
|
| + builder.append(tokens[i].lexeme);
|
| + }
|
| + return builder.toString();
|
| + }
|
| + nameNode = nameNode.parent;
|
| }
|
| + return null;
|
| }
|
| - SourceKind computeKindOf(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.computeKindOf(source);
|
| - } else {
|
| - return super.computeKindOf(source);
|
| + List<AnalysisError> computeErrors(Source source) {
|
| + SourceEntry sourceEntry = getReadableSourceEntry(source);
|
| + if (sourceEntry is DartEntry) {
|
| + List<AnalysisError> errors = new List<AnalysisError>();
|
| + DartEntry dartEntry = sourceEntry as DartEntry;
|
| + ListUtilities.addAll(errors, getDartParseData(source, dartEntry, DartEntry.PARSE_ERRORS));
|
| + dartEntry = getReadableDartEntry(source);
|
| + if (identical(dartEntry.getValue(DartEntry.SOURCE_KIND), SourceKind.LIBRARY)) {
|
| + ListUtilities.addAll(errors, getDartResolutionData(source, source, dartEntry, DartEntry.RESOLUTION_ERRORS));
|
| + } else {
|
| + List<Source> libraries = getLibrariesContaining(source);
|
| + for (Source librarySource in libraries) {
|
| + ListUtilities.addAll(errors, getDartResolutionData(source, librarySource, dartEntry, DartEntry.RESOLUTION_ERRORS));
|
| + }
|
| + }
|
| + if (errors.isEmpty) {
|
| + return AnalysisError.NO_ERRORS;
|
| + }
|
| + return new List.from(errors);
|
| + } else if (sourceEntry is HtmlEntry) {
|
| + HtmlEntry htmlEntry = sourceEntry as HtmlEntry;
|
| + return getHtmlResolutionData2(source, htmlEntry, HtmlEntry.RESOLUTION_ERRORS);
|
| }
|
| + return AnalysisError.NO_ERRORS;
|
| }
|
| - LibraryElement computeLibraryElement(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.computeLibraryElement(source);
|
| - } else {
|
| - return super.computeLibraryElement(source);
|
| + List<Source> computeExportedLibraries(Source source) => getDartParseData2(source, DartEntry.EXPORTED_LIBRARIES, Source.EMPTY_ARRAY);
|
| + HtmlElement computeHtmlElement(Source source) => getHtmlResolutionData(source, HtmlEntry.ELEMENT, null);
|
| + List<Source> computeImportedLibraries(Source source) => getDartParseData2(source, DartEntry.IMPORTED_LIBRARIES, Source.EMPTY_ARRAY);
|
| + SourceKind computeKindOf(Source source) {
|
| + SourceEntry sourceEntry = getReadableSourceEntry(source);
|
| + if (sourceEntry == null) {
|
| + return SourceKind.UNKNOWN;
|
| + } else if (sourceEntry is DartEntry) {
|
| + try {
|
| + return getDartParseData(source, sourceEntry as DartEntry, DartEntry.SOURCE_KIND);
|
| + } on AnalysisException catch (exception) {
|
| + return SourceKind.UNKNOWN;
|
| + }
|
| }
|
| + return sourceEntry.kind;
|
| }
|
| + LibraryElement computeLibraryElement(Source source) => getDartResolutionData2(source, source, DartEntry.ELEMENT, null);
|
| LineInfo computeLineInfo(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.computeLineInfo(source);
|
| - } else {
|
| - return super.computeLineInfo(source);
|
| + SourceEntry sourceEntry = getReadableSourceEntry(source);
|
| + if (sourceEntry is HtmlEntry) {
|
| + return getHtmlParseData(source, SourceEntry.LINE_INFO, null);
|
| + } else if (sourceEntry is DartEntry) {
|
| + return getDartParseData2(source, SourceEntry.LINE_INFO, null);
|
| }
|
| + return null;
|
| }
|
| ResolvableCompilationUnit computeResolvableCompilationUnit(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.computeResolvableCompilationUnit(source);
|
| - } else {
|
| - return super.computeResolvableCompilationUnit(source);
|
| + while (true) {
|
| + {
|
| + DartEntry dartEntry = getReadableDartEntry(source);
|
| + if (dartEntry == null) {
|
| + throw new AnalysisException.con1("computeResolvableCompilationUnit for non-Dart: ${source.fullName}");
|
| + }
|
| + if (identical(dartEntry.getState(DartEntry.PARSED_UNIT), CacheState.ERROR)) {
|
| + throw new AnalysisException.con1("Internal error: computeResolvableCompilationUnit could not parse ${source.fullName}");
|
| + }
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + CompilationUnit unit = dartCopy.resolvableCompilationUnit;
|
| + if (unit != null) {
|
| + _cache.put(source, dartCopy);
|
| + return new ResolvableCompilationUnit(dartCopy.modificationTime, unit);
|
| + }
|
| + }
|
| + cacheDartParseData(source, getReadableDartEntry(source), DartEntry.PARSED_UNIT);
|
| }
|
| }
|
| - AnalysisErrorInfo getErrors(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.getErrors(source);
|
| - } else {
|
| - return super.getErrors(source);
|
| + ResolvableHtmlUnit computeResolvableHtmlUnit(Source source) {
|
| + HtmlEntry htmlEntry = getReadableHtmlEntry(source);
|
| + if (htmlEntry == null) {
|
| + throw new AnalysisException.con1("computeResolvableHtmlUnit invoked for non-HTML file: ${source.fullName}");
|
| }
|
| - }
|
| - HtmlElement getHtmlElement(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.getHtmlElement(source);
|
| - } else {
|
| - return super.getHtmlElement(source);
|
| + htmlEntry = cacheHtmlParseData(source, htmlEntry, HtmlEntry.PARSED_UNIT);
|
| + HtmlUnit unit = htmlEntry.getValue(HtmlEntry.PARSED_UNIT);
|
| + if (unit == null) {
|
| + throw new AnalysisException.con1("Internal error: computeResolvableHtmlUnit could not parse ${source.fullName}");
|
| }
|
| + return new ResolvableHtmlUnit(htmlEntry.modificationTime, unit);
|
| }
|
| - List<Source> getHtmlFilesReferencing(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.getHtmlFilesReferencing(source);
|
| - } else {
|
| - return super.getHtmlFilesReferencing(source);
|
| + AnalysisContext extractContext(SourceContainer container) => extractContextInto(container, AnalysisEngine.instance.createAnalysisContext() as InternalAnalysisContext);
|
| + InternalAnalysisContext extractContextInto(SourceContainer container, InternalAnalysisContext newContext) {
|
| + List<Source> sourcesToRemove = new List<Source>();
|
| + {
|
| + for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
|
| + Source source = entry.getKey();
|
| + if (container.contains(source)) {
|
| + sourcesToRemove.add(source);
|
| + newContext.addSourceInfo(source, entry.getValue().writableCopy);
|
| + }
|
| + }
|
| }
|
| + return newContext;
|
| }
|
| - SourceKind getKindOf(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.getKindOf(source);
|
| - } else {
|
| - return super.getKindOf(source);
|
| + AnalysisOptions get analysisOptions => _options;
|
| + Element getElement(ElementLocation location) {
|
| + try {
|
| + List<String> components = ((location as ElementLocationImpl)).components;
|
| + Source librarySource = computeSourceFromEncoding(components[0]);
|
| + ElementImpl element = computeLibraryElement(librarySource) as ElementImpl;
|
| + for (int i = 1; i < components.length; i++) {
|
| + if (element == null) {
|
| + return null;
|
| + }
|
| + element = element.getChild(components[i]);
|
| + }
|
| + return element;
|
| + } on AnalysisException catch (exception) {
|
| + return null;
|
| }
|
| }
|
| - List<Source> getLibrariesContaining(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.getLibrariesContaining(source);
|
| - } else {
|
| - return super.getLibrariesContaining(source);
|
| + AnalysisErrorInfo getErrors(Source source) {
|
| + SourceEntry sourceEntry = getReadableSourceEntry(source);
|
| + if (sourceEntry is DartEntry) {
|
| + DartEntry dartEntry = sourceEntry as DartEntry;
|
| + return new AnalysisErrorInfoImpl(dartEntry.allErrors, dartEntry.getValue(SourceEntry.LINE_INFO));
|
| + } else if (sourceEntry is HtmlEntry) {
|
| + HtmlEntry htmlEntry = sourceEntry as HtmlEntry;
|
| + return new AnalysisErrorInfoImpl(htmlEntry.allErrors, htmlEntry.getValue(SourceEntry.LINE_INFO));
|
| }
|
| + return new AnalysisErrorInfoImpl(AnalysisError.NO_ERRORS, null);
|
| }
|
| - List<Source> getLibrariesDependingOn(Source librarySource) {
|
| - if (librarySource.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.getLibrariesDependingOn(librarySource);
|
| - } else {
|
| - return super.getLibrariesDependingOn(librarySource);
|
| + HtmlElement getHtmlElement(Source source) {
|
| + SourceEntry sourceEntry = getReadableSourceEntry(source);
|
| + if (sourceEntry is HtmlEntry) {
|
| + return ((sourceEntry as HtmlEntry)).getValue(HtmlEntry.ELEMENT);
|
| }
|
| + return null;
|
| }
|
| - LibraryElement getLibraryElement(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.getLibraryElement(source);
|
| - } else {
|
| - return super.getLibraryElement(source);
|
| + List<Source> getHtmlFilesReferencing(Source source) {
|
| + SourceKind sourceKind = getKindOf(source);
|
| + if (sourceKind == null) {
|
| + return Source.EMPTY_ARRAY;
|
| }
|
| - }
|
| - List<Source> get librarySources => ArrayUtils.addAll(super.librarySources, _sdkAnalysisContext.librarySources);
|
| - LineInfo getLineInfo(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.getLineInfo(source);
|
| - } else {
|
| - return super.getLineInfo(source);
|
| + {
|
| + List<Source> htmlSources = new List<Source>();
|
| + while (true) {
|
| + if (sourceKind == SourceKind.LIBRARY) {
|
| + } else if (sourceKind == SourceKind.PART) {
|
| + List<Source> librarySources = getLibrariesContaining(source);
|
| + for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
|
| + SourceEntry sourceEntry = entry.getValue();
|
| + if (identical(sourceEntry.kind, SourceKind.HTML)) {
|
| + List<Source> referencedLibraries = ((sourceEntry as HtmlEntry)).getValue(HtmlEntry.REFERENCED_LIBRARIES);
|
| + if (containsAny(referencedLibraries, librarySources)) {
|
| + htmlSources.add(entry.getKey());
|
| + }
|
| + }
|
| + }
|
| + }
|
| + break;
|
| + }
|
| + if (htmlSources.isEmpty) {
|
| + return Source.EMPTY_ARRAY;
|
| + }
|
| + return new List.from(htmlSources);
|
| }
|
| }
|
| - Namespace getPublicNamespace(LibraryElement library) {
|
| - Source source = library.source;
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.getPublicNamespace(library);
|
| - } else {
|
| - return super.getPublicNamespace(library);
|
| + List<Source> get htmlSources => getSources(SourceKind.HTML);
|
| + SourceKind getKindOf(Source source) {
|
| + SourceEntry sourceEntry = getReadableSourceEntry(source);
|
| + if (sourceEntry == null) {
|
| + return SourceKind.UNKNOWN;
|
| }
|
| + return sourceEntry.kind;
|
| }
|
| - Namespace getPublicNamespace2(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.getPublicNamespace2(source);
|
| - } else {
|
| - return super.getPublicNamespace2(source);
|
| + List<Source> get launchableClientLibrarySources {
|
| + List<Source> sources = new List<Source>();
|
| + {
|
| + for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
|
| + Source source = entry.getKey();
|
| + SourceEntry sourceEntry = entry.getValue();
|
| + if (identical(sourceEntry.kind, SourceKind.LIBRARY) && !source.isInSystemLibrary) {
|
| + sources.add(source);
|
| + }
|
| + }
|
| }
|
| + return new List.from(sources);
|
| }
|
| - CompilationUnit getResolvedCompilationUnit(Source unitSource, LibraryElement library) {
|
| - if (unitSource.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.getResolvedCompilationUnit(unitSource, library);
|
| - } else {
|
| - return super.getResolvedCompilationUnit(unitSource, library);
|
| + List<Source> get launchableServerLibrarySources {
|
| + List<Source> sources = new List<Source>();
|
| + {
|
| + for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
|
| + Source source = entry.getKey();
|
| + SourceEntry sourceEntry = entry.getValue();
|
| + if (identical(sourceEntry.kind, SourceKind.LIBRARY) && !source.isInSystemLibrary) {
|
| + sources.add(source);
|
| + }
|
| + }
|
| }
|
| + return new List.from(sources);
|
| }
|
| - CompilationUnit getResolvedCompilationUnit2(Source unitSource, Source librarySource) {
|
| - if (unitSource.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.getResolvedCompilationUnit2(unitSource, librarySource);
|
| - } else {
|
| - return super.getResolvedCompilationUnit2(unitSource, librarySource);
|
| + List<Source> getLibrariesContaining(Source source) {
|
| + {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry == null || sourceEntry.kind != SourceKind.PART) {
|
| + return <Source> [source];
|
| + }
|
| + List<Source> librarySources = new List<Source>();
|
| + for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
|
| + sourceEntry = entry.getValue();
|
| + if (identical(sourceEntry.kind, SourceKind.LIBRARY)) {
|
| + if (contains(((sourceEntry as DartEntry)).getValue(DartEntry.INCLUDED_PARTS), source)) {
|
| + librarySources.add(entry.getKey());
|
| + }
|
| + }
|
| + }
|
| + if (librarySources.isEmpty) {
|
| + return Source.EMPTY_ARRAY;
|
| + }
|
| + return new List.from(librarySources);
|
| }
|
| }
|
| - bool isClientLibrary(Source librarySource) {
|
| - if (librarySource.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.isClientLibrary(librarySource);
|
| - } else {
|
| - return super.isClientLibrary(librarySource);
|
| + List<Source> getLibrariesDependingOn(Source librarySource) {
|
| + {
|
| + List<Source> dependentLibraries = new List<Source>();
|
| + for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
|
| + SourceEntry sourceEntry = entry.getValue();
|
| + if (identical(sourceEntry.kind, SourceKind.LIBRARY)) {
|
| + if (contains(((sourceEntry as DartEntry)).getValue(DartEntry.EXPORTED_LIBRARIES), librarySource)) {
|
| + dependentLibraries.add(entry.getKey());
|
| + }
|
| + if (contains(((sourceEntry as DartEntry)).getValue(DartEntry.IMPORTED_LIBRARIES), librarySource)) {
|
| + dependentLibraries.add(entry.getKey());
|
| + }
|
| + }
|
| + }
|
| + if (dependentLibraries.isEmpty) {
|
| + return Source.EMPTY_ARRAY;
|
| + }
|
| + return new List.from(dependentLibraries);
|
| }
|
| }
|
| - bool isServerLibrary(Source librarySource) {
|
| - if (librarySource.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.isServerLibrary(librarySource);
|
| - } else {
|
| - return super.isServerLibrary(librarySource);
|
| + LibraryElement getLibraryElement(Source source) {
|
| + SourceEntry sourceEntry = getReadableSourceEntry(source);
|
| + if (sourceEntry is DartEntry) {
|
| + return ((sourceEntry as DartEntry)).getValue(DartEntry.ELEMENT);
|
| }
|
| + return null;
|
| }
|
| - CompilationUnit parseCompilationUnit(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.parseCompilationUnit(source);
|
| - } else {
|
| - return super.parseCompilationUnit(source);
|
| + List<Source> get librarySources => getSources(SourceKind.LIBRARY);
|
| + LineInfo getLineInfo(Source source) {
|
| + SourceEntry sourceEntry = getReadableSourceEntry(source);
|
| + if (sourceEntry != null) {
|
| + return sourceEntry.getValue(SourceEntry.LINE_INFO);
|
| }
|
| + return null;
|
| }
|
| - HtmlUnit parseHtmlUnit(Source source) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.parseHtmlUnit(source);
|
| - } else {
|
| - return super.parseHtmlUnit(source);
|
| + Namespace getPublicNamespace(LibraryElement library) {
|
| + Source source = library.definingCompilationUnit.source;
|
| + DartEntry dartEntry = getReadableDartEntry(source);
|
| + if (dartEntry == null) {
|
| + return null;
|
| }
|
| - }
|
| - void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
|
| - if (elementMap.isEmpty) {
|
| - return;
|
| + Namespace namespace = null;
|
| + if (identical(dartEntry.getValue(DartEntry.ELEMENT), library)) {
|
| + namespace = dartEntry.getValue(DartEntry.PUBLIC_NAMESPACE);
|
| }
|
| - Source source = new JavaIterator(elementMap.keys.toSet()).next();
|
| - if (source.isInSystemLibrary) {
|
| - _sdkAnalysisContext.recordLibraryElements(elementMap);
|
| - } else {
|
| - super.recordLibraryElements(elementMap);
|
| + if (namespace == null) {
|
| + NamespaceBuilder builder = new NamespaceBuilder();
|
| + namespace = builder.createPublicNamespace(library);
|
| + {
|
| + dartEntry = getReadableDartEntry(source);
|
| + if (dartEntry == null) {
|
| + AnalysisEngine.instance.logger.logError3(new AnalysisException.con1("A Dart file became a non-Dart file: ${source.fullName}"));
|
| + return null;
|
| + }
|
| + if (identical(dartEntry.getValue(DartEntry.ELEMENT), library)) {
|
| + DartEntryImpl dartCopy = getReadableDartEntry(source).writableCopy;
|
| + dartCopy.setValue(DartEntry.PUBLIC_NAMESPACE, namespace);
|
| + _cache.put(source, dartCopy);
|
| + }
|
| + }
|
| }
|
| + return namespace;
|
| }
|
| - CompilationUnit resolveCompilationUnit(Source source, LibraryElement library) {
|
| - if (source.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.resolveCompilationUnit(source, library);
|
| - } else {
|
| - return super.resolveCompilationUnit(source, library);
|
| + Namespace getPublicNamespace2(Source source) {
|
| + DartEntry dartEntry = getReadableDartEntry(source);
|
| + if (dartEntry == null) {
|
| + return null;
|
| }
|
| - }
|
| - CompilationUnit resolveCompilationUnit2(Source unitSource, Source librarySource) {
|
| - if (unitSource.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.resolveCompilationUnit2(unitSource, librarySource);
|
| - } else {
|
| - return super.resolveCompilationUnit2(unitSource, librarySource);
|
| + Namespace namespace = dartEntry.getValue(DartEntry.PUBLIC_NAMESPACE);
|
| + if (namespace == null) {
|
| + LibraryElement library = computeLibraryElement(source);
|
| + if (library == null) {
|
| + return null;
|
| + }
|
| + NamespaceBuilder builder = new NamespaceBuilder();
|
| + namespace = builder.createPublicNamespace(library);
|
| + {
|
| + dartEntry = getReadableDartEntry(source);
|
| + if (dartEntry == null) {
|
| + throw new AnalysisException.con1("A Dart file became a non-Dart file: ${source.fullName}");
|
| + }
|
| + if (identical(dartEntry.getValue(DartEntry.ELEMENT), library)) {
|
| + DartEntryImpl dartCopy = getReadableDartEntry(source).writableCopy;
|
| + dartCopy.setValue(DartEntry.PUBLIC_NAMESPACE, namespace);
|
| + _cache.put(source, dartCopy);
|
| + }
|
| + }
|
| }
|
| + return namespace;
|
| }
|
| - HtmlUnit resolveHtmlUnit(Source unitSource) {
|
| - if (unitSource.isInSystemLibrary) {
|
| - return _sdkAnalysisContext.resolveHtmlUnit(unitSource);
|
| - } else {
|
| - return super.resolveHtmlUnit(unitSource);
|
| + CompilationUnit getResolvedCompilationUnit(Source unitSource, LibraryElement library) {
|
| + if (library == null) {
|
| + return null;
|
| }
|
| + return getResolvedCompilationUnit2(unitSource, library.source);
|
| }
|
| - void setContents(Source source, String contents) {
|
| - if (source.isInSystemLibrary) {
|
| - _sdkAnalysisContext.setContents(source, contents);
|
| - } else {
|
| - super.setContents(source, contents);
|
| + CompilationUnit getResolvedCompilationUnit2(Source unitSource, Source librarySource) {
|
| + SourceEntry sourceEntry = getReadableSourceEntry(unitSource);
|
| + if (sourceEntry is DartEntry) {
|
| + return ((sourceEntry as DartEntry)).getValue2(DartEntry.RESOLVED_UNIT, librarySource);
|
| }
|
| + return null;
|
| }
|
| - void set sourceFactory(SourceFactory factory) {
|
| - super.sourceFactory = factory;
|
| - DartSdk sdk = factory.dartSdk;
|
| - if (sdk != null) {
|
| - _sdkAnalysisContext = sdk.context as InternalAnalysisContext;
|
| - if (_sdkAnalysisContext is DelegatingAnalysisContextImpl) {
|
| - _sdkAnalysisContext = null;
|
| - throw new IllegalStateException("The context provided by an SDK cannot itself be a delegating analysis context");
|
| - }
|
| - } else {
|
| - throw new IllegalStateException("SourceFactorys provided to DelegatingAnalysisContextImpls must have a DartSdk associated with the provided SourceFactory.");
|
| - }
|
| - }
|
| -}
|
| -/**
|
| - * Instances of the class `InstrumentedAnalysisContextImpl` implement an
|
| - * [AnalysisContext] by recording instrumentation data and delegating to
|
| - * another analysis context to do the non-instrumentation work.
|
| - *
|
| - * @coverage dart.engine
|
| - */
|
| -class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
|
| -
|
| - /**
|
| - * Record an exception that was thrown during analysis.
|
| - *
|
| - * @param instrumentation the instrumentation builder being used to record the exception
|
| - * @param exception the exception being reported
|
| - */
|
| - static void recordAnalysisException(InstrumentationBuilder instrumentation, AnalysisException exception) {
|
| - instrumentation.record(exception);
|
| - }
|
| -
|
| - /**
|
| - * The unique identifier used to identify this analysis context in the instrumentation data.
|
| - */
|
| - String _contextId = UUID.randomUUID().toString();
|
| -
|
| - /**
|
| - * The analysis context to which all of the non-instrumentation work is delegated.
|
| - */
|
| - InternalAnalysisContext _basis;
|
| -
|
| - /**
|
| - * Create a new [InstrumentedAnalysisContextImpl] which wraps a new
|
| - * [AnalysisContextImpl] as the basis context.
|
| - */
|
| - InstrumentedAnalysisContextImpl() : this.con1(new AnalysisContextImpl());
|
| + SourceFactory get sourceFactory => _sourceFactory;
|
|
|
| /**
|
| - * Create a new [InstrumentedAnalysisContextImpl] with a specified basis context, aka the
|
| - * context to wrap and instrument.
|
| + * Return a list of the sources that would be processed by [performAnalysisTask]. This
|
| + * method duplicates, and must therefore be kept in sync with, [getNextTaskAnalysisTask].
|
| + * This method is intended to be used for testing purposes only.
|
| *
|
| - * @param context some [InstrumentedAnalysisContext] to wrap and instrument
|
| + * @return a list of the sources that would be processed by [performAnalysisTask]
|
| */
|
| - InstrumentedAnalysisContextImpl.con1(InternalAnalysisContext context) {
|
| - _basis = context;
|
| - }
|
| - void addSourceInfo(Source source, SourceEntry info) {
|
| - _basis.addSourceInfo(source, info);
|
| - }
|
| - void applyChanges(ChangeSet changeSet) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-applyChanges");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - _basis.applyChanges(changeSet);
|
| - } finally {
|
| - instrumentation.log();
|
| + List<Source> get sourcesNeedingProcessing {
|
| + Set<Source> sources = new Set<Source>();
|
| + {
|
| + for (Source source in _cache.priorityOrder) {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry is DartEntry) {
|
| + DartEntry dartEntry = sourceEntry as DartEntry;
|
| + CacheState parseErrorsState = dartEntry.getState(DartEntry.PARSE_ERRORS);
|
| + if (identical(parseErrorsState, CacheState.INVALID) || identical(parseErrorsState, CacheState.FLUSHED)) {
|
| + javaSetAdd(sources, source);
|
| + }
|
| + CacheState parseUnitState = dartEntry.getState(DartEntry.PARSED_UNIT);
|
| + if (identical(parseUnitState, CacheState.INVALID) || identical(parseUnitState, CacheState.FLUSHED)) {
|
| + javaSetAdd(sources, source);
|
| + }
|
| + for (Source librarySource in getLibrariesContaining(source)) {
|
| + SourceEntry libraryEntry = _cache.get(librarySource);
|
| + if (libraryEntry is DartEntry) {
|
| + CacheState elementState = libraryEntry.getState(DartEntry.ELEMENT);
|
| + if (identical(elementState, CacheState.INVALID) || identical(elementState, CacheState.FLUSHED)) {
|
| + javaSetAdd(sources, source);
|
| + }
|
| + CacheState resolvedUnitState = dartEntry.getState2(DartEntry.RESOLVED_UNIT, librarySource);
|
| + if (identical(resolvedUnitState, CacheState.INVALID) || identical(resolvedUnitState, CacheState.FLUSHED)) {
|
| + LibraryElement libraryElement = libraryEntry.getValue(DartEntry.ELEMENT);
|
| + if (libraryElement != null) {
|
| + javaSetAdd(sources, source);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + } else if (sourceEntry is HtmlEntry) {
|
| + HtmlEntry htmlEntry = sourceEntry as HtmlEntry;
|
| + CacheState parsedUnitState = htmlEntry.getState(HtmlEntry.PARSED_UNIT);
|
| + if (identical(parsedUnitState, CacheState.INVALID) || identical(parsedUnitState, CacheState.FLUSHED)) {
|
| + javaSetAdd(sources, source);
|
| + }
|
| + CacheState elementState = htmlEntry.getState(HtmlEntry.ELEMENT);
|
| + if (identical(elementState, CacheState.INVALID) || identical(elementState, CacheState.FLUSHED)) {
|
| + javaSetAdd(sources, source);
|
| + }
|
| + }
|
| + }
|
| + for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
|
| + SourceEntry sourceEntry = entry.getValue();
|
| + if (sourceEntry is DartEntry) {
|
| + DartEntry dartEntry = sourceEntry as DartEntry;
|
| + if (identical(dartEntry.getState(DartEntry.PARSED_UNIT), CacheState.INVALID)) {
|
| + javaSetAdd(sources, entry.getKey());
|
| + }
|
| + } else if (sourceEntry is HtmlEntry) {
|
| + HtmlEntry htmlEntry = sourceEntry as HtmlEntry;
|
| + if (identical(htmlEntry.getState(HtmlEntry.PARSED_UNIT), CacheState.INVALID)) {
|
| + javaSetAdd(sources, entry.getKey());
|
| + }
|
| + }
|
| + }
|
| + for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
|
| + SourceEntry sourceEntry = entry.getValue();
|
| + if (sourceEntry is DartEntry && identical(sourceEntry.kind, SourceKind.LIBRARY)) {
|
| + DartEntry dartEntry = sourceEntry as DartEntry;
|
| + if (identical(dartEntry.getState(DartEntry.ELEMENT), CacheState.INVALID)) {
|
| + javaSetAdd(sources, entry.getKey());
|
| + }
|
| + } else if (sourceEntry is HtmlEntry) {
|
| + HtmlEntry htmlEntry = sourceEntry as HtmlEntry;
|
| + if (identical(htmlEntry.getState(HtmlEntry.ELEMENT), CacheState.INVALID)) {
|
| + javaSetAdd(sources, entry.getKey());
|
| + }
|
| + }
|
| + }
|
| }
|
| + return new List<Source>.from(sources);
|
| }
|
| - String computeDocumentationComment(Element element) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeDocumentationComment");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.computeDocumentationComment(element);
|
| - } finally {
|
| - instrumentation.log();
|
| + AnalysisContentStatistics get statistics {
|
| + AnalysisContentStatisticsImpl statistics = new AnalysisContentStatisticsImpl();
|
| + {
|
| + for (MapEntry<Source, SourceEntry> mapEntry in _cache.entrySet()) {
|
| + SourceEntry entry = mapEntry.getValue();
|
| + if (entry is DartEntry) {
|
| + Source source = mapEntry.getKey();
|
| + DartEntry dartEntry = entry as DartEntry;
|
| + SourceKind kind = dartEntry.getValue(DartEntry.SOURCE_KIND);
|
| + statistics.putCacheItem(dartEntry, DartEntry.PARSE_ERRORS);
|
| + statistics.putCacheItem(dartEntry, DartEntry.PARSED_UNIT);
|
| + statistics.putCacheItem(dartEntry, DartEntry.SOURCE_KIND);
|
| + statistics.putCacheItem(dartEntry, DartEntry.LINE_INFO);
|
| + if (identical(kind, SourceKind.LIBRARY)) {
|
| + statistics.putCacheItem(dartEntry, DartEntry.ELEMENT);
|
| + statistics.putCacheItem(dartEntry, DartEntry.EXPORTED_LIBRARIES);
|
| + statistics.putCacheItem(dartEntry, DartEntry.IMPORTED_LIBRARIES);
|
| + statistics.putCacheItem(dartEntry, DartEntry.INCLUDED_PARTS);
|
| + statistics.putCacheItem(dartEntry, DartEntry.IS_CLIENT);
|
| + statistics.putCacheItem(dartEntry, DartEntry.IS_LAUNCHABLE);
|
| + }
|
| + List<Source> librarySources = getLibrariesContaining(source);
|
| + for (Source librarySource in librarySources) {
|
| + statistics.putCacheItem2(dartEntry, librarySource, DartEntry.RESOLUTION_ERRORS);
|
| + statistics.putCacheItem2(dartEntry, librarySource, DartEntry.RESOLVED_UNIT);
|
| + }
|
| + }
|
| + }
|
| }
|
| + return statistics;
|
| }
|
| - List<AnalysisError> computeErrors(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeErrors");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - List<AnalysisError> errors = _basis.computeErrors(source);
|
| - instrumentation.metric2("Errors-count", errors.length);
|
| - return errors;
|
| - } finally {
|
| - instrumentation.log();
|
| + bool isClientLibrary(Source librarySource) {
|
| + SourceEntry sourceEntry = getReadableSourceEntry(librarySource);
|
| + if (sourceEntry is DartEntry) {
|
| + DartEntry dartEntry = sourceEntry as DartEntry;
|
| + return dartEntry.getValue(DartEntry.IS_CLIENT) && dartEntry.getValue(DartEntry.IS_LAUNCHABLE);
|
| }
|
| + return false;
|
| }
|
| - List<Source> computeExportedLibraries(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeExportedLibraries");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.computeExportedLibraries(source);
|
| - } finally {
|
| - instrumentation.log();
|
| + bool isServerLibrary(Source librarySource) {
|
| + SourceEntry sourceEntry = getReadableSourceEntry(librarySource);
|
| + if (sourceEntry is DartEntry) {
|
| + DartEntry dartEntry = sourceEntry as DartEntry;
|
| + return !dartEntry.getValue(DartEntry.IS_CLIENT) && dartEntry.getValue(DartEntry.IS_LAUNCHABLE);
|
| }
|
| + return false;
|
| }
|
| - HtmlElement computeHtmlElement(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeHtmlElement");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.computeHtmlElement(source);
|
| - } on AnalysisException catch (e) {
|
| - recordAnalysisException(instrumentation, e);
|
| - throw e;
|
| - } finally {
|
| - instrumentation.log();
|
| + void mergeContext(AnalysisContext context) {
|
| + if (context is InstrumentedAnalysisContextImpl) {
|
| + context = ((context as InstrumentedAnalysisContextImpl)).basis;
|
| }
|
| - }
|
| - List<Source> computeImportedLibraries(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeImportedLibraries");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.computeImportedLibraries(source);
|
| - } finally {
|
| - instrumentation.log();
|
| + if (context is! AnalysisContextImpl2) {
|
| + return;
|
| }
|
| - }
|
| - SourceKind computeKindOf(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeKindOf");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.computeKindOf(source);
|
| - } finally {
|
| - instrumentation.log();
|
| + {
|
| + for (MapEntry<Source, SourceEntry> entry in ((context as AnalysisContextImpl2))._cache.entrySet()) {
|
| + Source newSource = entry.getKey();
|
| + SourceEntry existingEntry = getReadableSourceEntry(newSource);
|
| + if (existingEntry == null) {
|
| + _cache.put(newSource, entry.getValue().writableCopy);
|
| + } else {
|
| + }
|
| + }
|
| }
|
| }
|
| - LibraryElement computeLibraryElement(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeLibraryElement");
|
| + CompilationUnit parseCompilationUnit(Source source) => getDartParseData2(source, DartEntry.PARSED_UNIT, null);
|
| + HtmlUnit parseHtmlUnit(Source source) => getHtmlParseData(source, HtmlEntry.PARSED_UNIT, null);
|
| + List<ChangeNotice> performAnalysisTask() {
|
| + AnalysisTask task = nextTaskAnalysisTask;
|
| + if (task == null) {
|
| + return getChangeNotices(true);
|
| + }
|
| try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.computeLibraryElement(source);
|
| - } on AnalysisException catch (e) {
|
| - recordAnalysisException(instrumentation, e);
|
| - throw e;
|
| - } finally {
|
| - instrumentation.log();
|
| + task.perform(_resultRecorder);
|
| + } on AnalysisException catch (exception) {
|
| + if (exception.cause is! JavaIOException) {
|
| + AnalysisEngine.instance.logger.logError2("Internal error while performing the task: ${task}", exception);
|
| + }
|
| }
|
| + return getChangeNotices(false);
|
| }
|
| - LineInfo computeLineInfo(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeLineInfo");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.computeLineInfo(source);
|
| - } on AnalysisException catch (e) {
|
| - recordAnalysisException(instrumentation, e);
|
| - throw e;
|
| - } finally {
|
| - instrumentation.log();
|
| + void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
|
| + {
|
| + Source htmlSource = _sourceFactory.forUri(DartSdk.DART_HTML);
|
| + for (MapEntry<Source, LibraryElement> entry in getMapEntrySet(elementMap)) {
|
| + Source librarySource = entry.getKey();
|
| + LibraryElement library = entry.getValue();
|
| + DartEntry dartEntry = getReadableDartEntry(librarySource);
|
| + if (dartEntry != null) {
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + recordElementData(dartCopy, library, htmlSource);
|
| + _cache.put(librarySource, dartCopy);
|
| + }
|
| + }
|
| }
|
| }
|
| - ResolvableCompilationUnit computeResolvableCompilationUnit(Source source) => _basis.computeResolvableCompilationUnit(source);
|
| - AnalysisContext extractContext(SourceContainer container) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-extractContext");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - InstrumentedAnalysisContextImpl newContext = new InstrumentedAnalysisContextImpl();
|
| - _basis.extractContextInto(container, newContext._basis);
|
| - return newContext;
|
| - } finally {
|
| - instrumentation.log();
|
| + CompilationUnit resolveCompilationUnit(Source unitSource, LibraryElement library) {
|
| + if (library == null) {
|
| + return null;
|
| }
|
| + return resolveCompilationUnit2(unitSource, library.source);
|
| }
|
| - InternalAnalysisContext extractContextInto(SourceContainer container, InternalAnalysisContext newContext) => _basis.extractContextInto(container, newContext);
|
| - AnalysisOptions get analysisOptions {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getAnalysisOptions");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.analysisOptions;
|
| - } finally {
|
| - instrumentation.log();
|
| + CompilationUnit resolveCompilationUnit2(Source unitSource, Source librarySource) => getDartResolutionData2(unitSource, librarySource, DartEntry.RESOLVED_UNIT, null);
|
| + HtmlUnit resolveHtmlUnit(Source htmlSource) => parseHtmlUnit(htmlSource);
|
| + void set analysisOptions(AnalysisOptions options2) {
|
| + {
|
| + this._options = options2;
|
| + invalidateAllResolutionInformation();
|
| }
|
| }
|
| -
|
| - /**
|
| - * @return the underlying [AnalysisContext].
|
| - */
|
| - AnalysisContext get basis => _basis;
|
| - Element getElement(ElementLocation location) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getElement");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.getElement(location);
|
| - } finally {
|
| - instrumentation.log();
|
| + void set analysisPriorityOrder(List<Source> sources) {
|
| + {
|
| + if (sources == null || sources.isEmpty) {
|
| + _cache.priorityOrder = Source.EMPTY_ARRAY;
|
| + } else {
|
| + while (sources.remove(null)) {
|
| + }
|
| + if (sources.isEmpty) {
|
| + _cache.priorityOrder = Source.EMPTY_ARRAY;
|
| + }
|
| + int count = Math.min(sources.length, _MAX_PRIORITY_LIST_SIZE);
|
| + List<Source> priorityOrder = new List<Source>(count);
|
| + for (int i = 0; i < count; i++) {
|
| + priorityOrder[i] = sources[i];
|
| + }
|
| + _cache.priorityOrder = priorityOrder;
|
| + }
|
| }
|
| }
|
| - AnalysisErrorInfo getErrors(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getErrors");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - AnalysisErrorInfo ret = _basis.getErrors(source);
|
| - if (ret != null) {
|
| - instrumentation.metric2("Errors-count", ret.errors.length);
|
| + void setContents(Source source, String contents) {
|
| + {
|
| + if (_sourceFactory.setContents(source, contents)) {
|
| + sourceChanged(source);
|
| }
|
| - return ret;
|
| - } finally {
|
| - instrumentation.log();
|
| }
|
| }
|
| - HtmlElement getHtmlElement(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getHtmlElement");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.getHtmlElement(source);
|
| - } finally {
|
| - instrumentation.log();
|
| + void set sourceFactory(SourceFactory factory) {
|
| + {
|
| + if (identical(_sourceFactory, factory)) {
|
| + return;
|
| + } else if (factory.context != null) {
|
| + throw new IllegalStateException("Source factories cannot be shared between contexts");
|
| + }
|
| + if (_sourceFactory != null) {
|
| + _sourceFactory.context = null;
|
| + }
|
| + factory.context = this;
|
| + _sourceFactory = factory;
|
| + invalidateAllResolutionInformation();
|
| }
|
| }
|
| - List<Source> getHtmlFilesReferencing(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getHtmlFilesReferencing");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - List<Source> ret = _basis.getHtmlFilesReferencing(source);
|
| - if (ret != null) {
|
| - instrumentation.metric2("Source-count", ret.length);
|
| + Iterable<Source> sourcesToResolve(List<Source> changedSources) {
|
| + List<Source> librarySources = new List<Source>();
|
| + for (Source source in changedSources) {
|
| + if (identical(computeKindOf(source), SourceKind.LIBRARY)) {
|
| + librarySources.add(source);
|
| }
|
| - return ret;
|
| - } finally {
|
| - instrumentation.log();
|
| }
|
| + return librarySources;
|
| }
|
| - List<Source> get htmlSources {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getHtmlSources");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - List<Source> ret = _basis.htmlSources;
|
| - if (ret != null) {
|
| - instrumentation.metric2("Source-count", ret.length);
|
| +
|
| + /**
|
| + * Add all of the sources contained in the given source container to the given list of sources.
|
| + *
|
| + * Note: This method must only be invoked while we are synchronized on [cacheLock].
|
| + *
|
| + * @param sources the list to which sources are to be added
|
| + * @param container the source container containing the sources to be added to the list
|
| + */
|
| + void addSourcesInContainer(List<Source> sources, SourceContainer container) {
|
| + for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
|
| + Source source = entry.getKey();
|
| + if (container.contains(source)) {
|
| + sources.add(source);
|
| }
|
| - return ret;
|
| - } finally {
|
| - instrumentation.log();
|
| }
|
| }
|
| - SourceKind getKindOf(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getKindOf");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.getKindOf(source);
|
| - } finally {
|
| - instrumentation.log();
|
| +
|
| + /**
|
| + * Return `true` if the modification times of the sources used by the given library resolver
|
| + * to resolve one or more libraries are consistent with the modification times in the cache.
|
| + *
|
| + * @param resolver the library resolver used to resolve one or more libraries
|
| + * @return `true` if we should record the results of the resolution
|
| + * @throws AnalysisException if any of the modification times could not be determined (this should
|
| + * not happen)
|
| + */
|
| + bool allModificationTimesMatch(LibraryResolver resolver) {
|
| + bool allTimesMatch = true;
|
| + for (Library library in resolver.resolvedLibraries) {
|
| + for (Source source in library.compilationUnitSources) {
|
| + DartEntry dartEntry = getReadableDartEntry(source);
|
| + if (dartEntry == null) {
|
| + throw new AnalysisException.con1("Internal error: attempting to reolve non-Dart file as a Dart file: ${source.fullName}");
|
| + }
|
| + int sourceTime = source.modificationStamp;
|
| + int resultTime = library.getModificationTime(source);
|
| + if (sourceTime != resultTime) {
|
| + sourceChanged(source);
|
| + allTimesMatch = false;
|
| + }
|
| + }
|
| }
|
| + return allTimesMatch;
|
| }
|
| - List<Source> get launchableClientLibrarySources {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLaunchableClientLibrarySources");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - List<Source> ret = _basis.launchableClientLibrarySources;
|
| - if (ret != null) {
|
| - instrumentation.metric2("Source-count", ret.length);
|
| +
|
| + /**
|
| + * Given a source for a Dart file, return a cache entry in which the data represented by the given
|
| + * descriptor is available. This method assumes that the data can be produced by parsing the
|
| + * source if it is not already cached.
|
| + *
|
| + * @param source the source representing the Dart file
|
| + * @param dartEntry the cache entry associated with the Dart file
|
| + * @param descriptor the descriptor representing the data to be returned
|
| + * @return a cache entry containing the required data
|
| + * @throws AnalysisException if data could not be returned because the source could not be
|
| + * resolved
|
| + */
|
| + DartEntry cacheDartParseData(Source source, DartEntry dartEntry, DataDescriptor descriptor) {
|
| + if (identical(descriptor, DartEntry.PARSED_UNIT)) {
|
| + CompilationUnit unit = dartEntry.anyParsedCompilationUnit;
|
| + if (unit != null) {
|
| + return dartEntry;
|
| }
|
| - return ret;
|
| - } finally {
|
| - instrumentation.log();
|
| }
|
| + CacheState state = dartEntry.getState(descriptor);
|
| + while (state != CacheState.ERROR && state != CacheState.VALID) {
|
| + dartEntry = new ParseDartTask(this, source).perform(_resultRecorder) as DartEntry;
|
| + state = dartEntry.getState(descriptor);
|
| + }
|
| + return dartEntry;
|
| }
|
| - List<Source> get launchableServerLibrarySources {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLaunchableServerLibrarySources");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - List<Source> ret = _basis.launchableServerLibrarySources;
|
| - if (ret != null) {
|
| - instrumentation.metric2("Source-count", ret.length);
|
| - }
|
| - return ret;
|
| - } finally {
|
| - instrumentation.log();
|
| +
|
| + /**
|
| + * Given a source for a Dart file and the library that contains it, return a cache entry in which
|
| + * the data represented by the given descriptor is available. This method assumes that the data
|
| + * can be produced by resolving the source in the context of the library if it is not already
|
| + * cached.
|
| + *
|
| + * @param unitSource the source representing the Dart file
|
| + * @param librarySource the source representing the library containing the Dart file
|
| + * @param dartEntry the cache entry associated with the Dart file
|
| + * @param descriptor the descriptor representing the data to be returned
|
| + * @return a cache entry containing the required data
|
| + * @throws AnalysisException if data could not be returned because the source could not be parsed
|
| + */
|
| + DartEntry cacheDartResolutionData(Source unitSource, Source librarySource, DartEntry dartEntry, DataDescriptor descriptor) {
|
| + CacheState state = (identical(descriptor, DartEntry.ELEMENT)) ? dartEntry.getState(descriptor) : dartEntry.getState2(descriptor, librarySource);
|
| + while (state != CacheState.ERROR && state != CacheState.VALID) {
|
| + dartEntry = new ResolveDartLibraryTask(this, unitSource, librarySource).perform(_resultRecorder) as DartEntry;
|
| + state = (identical(descriptor, DartEntry.ELEMENT)) ? dartEntry.getState(descriptor) : dartEntry.getState2(descriptor, librarySource);
|
| }
|
| + return dartEntry;
|
| }
|
| - List<Source> getLibrariesContaining(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLibrariesContaining");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - List<Source> ret = _basis.getLibrariesContaining(source);
|
| - if (ret != null) {
|
| - instrumentation.metric2("Source-count", ret.length);
|
| - }
|
| - return ret;
|
| - } finally {
|
| - instrumentation.log2(2);
|
| +
|
| + /**
|
| + * Given a source for an HTML file, return a cache entry in which all of the data represented by
|
| + * the given descriptors is available. This method assumes that the data can be produced by
|
| + * parsing the source if it is not already cached.
|
| + *
|
| + * @param source the source representing the HTML file
|
| + * @param htmlEntry the cache entry associated with the HTML file
|
| + * @param descriptor the descriptor representing the data to be returned
|
| + * @return a cache entry containing the required data
|
| + * @throws AnalysisException if data could not be returned because the source could not be
|
| + * resolved
|
| + */
|
| + HtmlEntry cacheHtmlParseData(Source source, HtmlEntry htmlEntry, DataDescriptor descriptor) {
|
| + CacheState state = htmlEntry.getState(descriptor);
|
| + while (state != CacheState.ERROR && state != CacheState.VALID) {
|
| + htmlEntry = new ParseHtmlTask(this, source).perform(_resultRecorder) as HtmlEntry;
|
| + state = htmlEntry.getState(descriptor);
|
| }
|
| + return htmlEntry;
|
| }
|
| - List<Source> getLibrariesDependingOn(Source librarySource) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLibrariesDependingOn");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - List<Source> ret = _basis.getLibrariesDependingOn(librarySource);
|
| - if (ret != null) {
|
| - instrumentation.metric2("Source-count", ret.length);
|
| - }
|
| - return ret;
|
| - } finally {
|
| - instrumentation.log();
|
| +
|
| + /**
|
| + * Given a source for an HTML file, return a cache entry in which the the data represented by the
|
| + * given descriptor is available. This method assumes that the data can be produced by resolving
|
| + * the source if it is not already cached.
|
| + *
|
| + * @param source the source representing the HTML file
|
| + * @param dartEntry the cache entry associated with the HTML file
|
| + * @param descriptor the descriptor representing the data to be returned
|
| + * @return a cache entry containing the required data
|
| + * @throws AnalysisException if data could not be returned because the source could not be
|
| + * resolved
|
| + */
|
| + HtmlEntry cacheHtmlResolutionData(Source source, HtmlEntry htmlEntry, DataDescriptor descriptor) {
|
| + CacheState state = htmlEntry.getState(descriptor);
|
| + while (state != CacheState.ERROR && state != CacheState.VALID) {
|
| + htmlEntry = new ResolveHtmlTask(this, source).perform(_resultRecorder) as HtmlEntry;
|
| + state = htmlEntry.getState(descriptor);
|
| }
|
| + return htmlEntry;
|
| }
|
| - LibraryElement getLibraryElement(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLibraryElement");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.getLibraryElement(source);
|
| - } finally {
|
| - instrumentation.log();
|
| +
|
| + /**
|
| + * Given the encoded form of a source, use the source factory to reconstitute the original source.
|
| + *
|
| + * @param encoding the encoded form of a source
|
| + * @return the source represented by the encoding
|
| + */
|
| + Source computeSourceFromEncoding(String encoding) {
|
| + {
|
| + return _sourceFactory.fromEncoding(encoding);
|
| }
|
| }
|
| - List<Source> get librarySources {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLibrarySources");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - List<Source> ret = _basis.librarySources;
|
| - if (ret != null) {
|
| - instrumentation.metric2("Source-count", ret.length);
|
| +
|
| + /**
|
| + * Return `true` if the given array of sources contains the given source.
|
| + *
|
| + * @param sources the sources being searched
|
| + * @param targetSource the source being searched for
|
| + * @return `true` if the given source is in the array
|
| + */
|
| + bool contains(List<Source> sources, Source targetSource) {
|
| + for (Source source in sources) {
|
| + if (source == targetSource) {
|
| + return true;
|
| }
|
| - return ret;
|
| - } finally {
|
| - instrumentation.log();
|
| }
|
| + return false;
|
| }
|
| - LineInfo getLineInfo(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLineInfo");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.getLineInfo(source);
|
| - } finally {
|
| - instrumentation.log();
|
| +
|
| + /**
|
| + * Return `true` if the given array of sources contains any of the given target sources.
|
| + *
|
| + * @param sources the sources being searched
|
| + * @param targetSources the sources being searched for
|
| + * @return `true` if any of the given target sources are in the array
|
| + */
|
| + bool containsAny(List<Source> sources, List<Source> targetSources) {
|
| + for (Source targetSource in targetSources) {
|
| + if (contains(sources, targetSource)) {
|
| + return true;
|
| + }
|
| }
|
| + return false;
|
| }
|
| - Namespace getPublicNamespace(LibraryElement library) => _basis.getPublicNamespace(library);
|
| - Namespace getPublicNamespace2(Source source) => _basis.getPublicNamespace2(source);
|
| - CompilationUnit getResolvedCompilationUnit(Source unitSource, LibraryElement library) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getResolvedCompilationUnit");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.getResolvedCompilationUnit(unitSource, library);
|
| - } finally {
|
| - instrumentation.log();
|
| +
|
| + /**
|
| + * Create a source information object suitable for the given source. Return the source information
|
| + * object that was created, or `null` if the source should not be tracked by this context.
|
| + *
|
| + * @param source the source for which an information object is being created
|
| + * @return the source information object that was created
|
| + */
|
| + SourceEntry createSourceEntry(Source source) {
|
| + String name = source.shortName;
|
| + if (AnalysisEngine.isHtmlFileName(name)) {
|
| + HtmlEntryImpl htmlEntry = new HtmlEntryImpl();
|
| + htmlEntry.modificationTime = source.modificationStamp;
|
| + _cache.put(source, htmlEntry);
|
| + return htmlEntry;
|
| + } else {
|
| + DartEntryImpl dartEntry = new DartEntryImpl();
|
| + dartEntry.modificationTime = source.modificationStamp;
|
| + _cache.put(source, dartEntry);
|
| + return dartEntry;
|
| }
|
| }
|
| - CompilationUnit getResolvedCompilationUnit2(Source unitSource, Source librarySource) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getResolvedCompilationUnit");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.getResolvedCompilationUnit2(unitSource, librarySource);
|
| - } finally {
|
| - instrumentation.log2(2);
|
| +
|
| + /**
|
| + * Return an array containing all of the change notices that are waiting to be returned. If there
|
| + * are no notices, then return either `null` or an empty array, depending on the value of
|
| + * the argument.
|
| + *
|
| + * @param nullIfEmpty `true` if `null` should be returned when there are no notices
|
| + * @return the change notices that are waiting to be returned
|
| + */
|
| + List<ChangeNotice> getChangeNotices(bool nullIfEmpty) {
|
| + {
|
| + if (_pendingNotices.isEmpty) {
|
| + if (nullIfEmpty) {
|
| + return null;
|
| + }
|
| + return ChangeNoticeImpl.EMPTY_ARRAY;
|
| + }
|
| + List<ChangeNotice> notices = new List.from(_pendingNotices.values);
|
| + _pendingNotices.clear();
|
| + return notices;
|
| }
|
| }
|
| - SourceFactory get sourceFactory {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getSourceFactory");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.sourceFactory;
|
| - } finally {
|
| - instrumentation.log2(2);
|
| +
|
| + /**
|
| + * Given a source for a Dart file, return the data represented by the given descriptor that is
|
| + * associated with that source. This method assumes that the data can be produced by parsing the
|
| + * source if it is not already cached.
|
| + *
|
| + * @param source the source representing the Dart file
|
| + * @param dartEntry the cache entry associated with the Dart file
|
| + * @param descriptor the descriptor representing the data to be returned
|
| + * @return the requested data about the given source
|
| + * @throws AnalysisException if data could not be returned because the source could not be parsed
|
| + */
|
| + Object getDartParseData(Source source, DartEntry dartEntry, DataDescriptor descriptor) {
|
| + dartEntry = cacheDartParseData(source, dartEntry, descriptor);
|
| + if (identical(descriptor, DartEntry.PARSED_UNIT)) {
|
| + return dartEntry.anyParsedCompilationUnit as Object;
|
| }
|
| + return dartEntry.getValue(descriptor);
|
| }
|
| - AnalysisContentStatistics get statistics => _basis.statistics;
|
| - bool isClientLibrary(Source librarySource) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-isClientLibrary");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.isClientLibrary(librarySource);
|
| - } finally {
|
| - instrumentation.log();
|
| +
|
| + /**
|
| + * Given a source for a Dart 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 a Dart file. This
|
| + * method assumes that the data can be produced by parsing the source if it is not already cached.
|
| + *
|
| + * @param source the source representing the Dart file
|
| + * @param descriptor the descriptor representing the data to be returned
|
| + * @param defaultValue the value to be returned if the source is not a Dart file
|
| + * @return the requested data about the given source
|
| + * @throws AnalysisException if data could not be returned because the source could not be parsed
|
| + */
|
| + Object getDartParseData2(Source source, DataDescriptor descriptor, Object defaultValue) {
|
| + DartEntry dartEntry = getReadableDartEntry(source);
|
| + if (dartEntry == null) {
|
| + return defaultValue;
|
| }
|
| + return getDartParseData(source, dartEntry, descriptor);
|
| }
|
| - bool isServerLibrary(Source librarySource) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-isServerLibrary");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.isServerLibrary(librarySource);
|
| - } finally {
|
| - instrumentation.log();
|
| +
|
| + /**
|
| + * Given a source for a Dart file and the library that contains it, return the data represented by
|
| + * the given descriptor that is associated with that source. This method assumes that the data can
|
| + * be produced by resolving the source in the context of the library if it is not already cached.
|
| + *
|
| + * @param unitSource the source representing the Dart file
|
| + * @param librarySource the source representing the library containing the Dart file
|
| + * @param dartEntry the entry representing the Dart file
|
| + * @param descriptor the descriptor representing the data to be returned
|
| + * @return the requested data about the given source
|
| + * @throws AnalysisException if data could not be returned because the source could not be
|
| + * resolved
|
| + */
|
| + Object getDartResolutionData(Source unitSource, Source librarySource, DartEntry dartEntry, DataDescriptor descriptor) {
|
| + dartEntry = cacheDartResolutionData(unitSource, librarySource, dartEntry, descriptor);
|
| + if (identical(descriptor, DartEntry.ELEMENT)) {
|
| + return dartEntry.getValue(descriptor);
|
| }
|
| + return dartEntry.getValue2(descriptor, librarySource);
|
| }
|
| - void mergeContext(AnalysisContext context) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-mergeContext");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - if (context is InstrumentedAnalysisContextImpl) {
|
| - context = ((context as InstrumentedAnalysisContextImpl))._basis;
|
| - }
|
| - _basis.mergeContext(context);
|
| - } finally {
|
| - instrumentation.log();
|
| +
|
| + /**
|
| + * Given a source for a Dart file and the library that contains it, return the data represented by
|
| + * the given descriptor that is associated with that source, or the given default value if the
|
| + * source is not a Dart file. This method assumes that the data can be produced by resolving the
|
| + * source in the context of the library if it is not already cached.
|
| + *
|
| + * @param unitSource the source representing the Dart file
|
| + * @param librarySource the source representing the library containing the Dart file
|
| + * @param descriptor the descriptor representing the data to be returned
|
| + * @param defaultValue the value to be returned if the source is not a Dart file
|
| + * @return the requested data about the given source
|
| + * @throws AnalysisException if data could not be returned because the source could not be
|
| + * resolved
|
| + */
|
| + Object getDartResolutionData2(Source unitSource, Source librarySource, DataDescriptor descriptor, Object defaultValue) {
|
| + DartEntry dartEntry = getReadableDartEntry(unitSource);
|
| + if (dartEntry == null) {
|
| + return defaultValue;
|
| }
|
| + return getDartResolutionData(unitSource, librarySource, dartEntry, descriptor);
|
| }
|
| - CompilationUnit parseCompilationUnit(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-parseCompilationUnit");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.parseCompilationUnit(source);
|
| - } on AnalysisException catch (e) {
|
| - recordAnalysisException(instrumentation, e);
|
| - throw e;
|
| - } finally {
|
| - instrumentation.log();
|
| +
|
| + /**
|
| + * 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.
|
| + *
|
| + * @param source the source representing the Dart file
|
| + * @param descriptor the descriptor representing the data to be returned
|
| + * @param defaultValue the value to be returned if the source is not an HTML file
|
| + * @return the requested data about the given source
|
| + * @throws AnalysisException if data could not be returned because the source could not be parsed
|
| + */
|
| + Object getHtmlParseData(Source source, DataDescriptor descriptor, Object defaultValue) {
|
| + HtmlEntry htmlEntry = getReadableHtmlEntry(source);
|
| + if (htmlEntry == null) {
|
| + return defaultValue;
|
| }
|
| + htmlEntry = cacheHtmlParseData(source, htmlEntry, descriptor);
|
| + return htmlEntry.getValue(descriptor);
|
| }
|
| - HtmlUnit parseHtmlUnit(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-parseHtmlUnit");
|
| +
|
| + /**
|
| + * 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 resolving the source if it is not already
|
| + * cached.
|
| + *
|
| + * @param source the source representing the HTML file
|
| + * @param descriptor the descriptor representing the data to be returned
|
| + * @param defaultValue the value to be returned if the source is not an HTML file
|
| + * @return the requested data about the given source
|
| + * @throws AnalysisException if data could not be returned because the source could not be
|
| + * resolved
|
| + */
|
| + Object getHtmlResolutionData(Source source, DataDescriptor descriptor, Object defaultValue) {
|
| + HtmlEntry htmlEntry = getReadableHtmlEntry(source);
|
| + if (htmlEntry == null) {
|
| + return defaultValue;
|
| + }
|
| + return getHtmlResolutionData2(source, htmlEntry, descriptor);
|
| + }
|
| +
|
| + /**
|
| + * Given a source for an HTML file, return the data represented by the given descriptor that is
|
| + * associated with that source. This method assumes that the data can be produced by resolving the
|
| + * source if it is not already cached.
|
| + *
|
| + * @param source the source representing the HTML file
|
| + * @param htmlEntry the entry representing the HTML file
|
| + * @param descriptor the descriptor representing the data to be returned
|
| + * @return the requested data about the given source
|
| + * @throws AnalysisException if data could not be returned because the source could not be
|
| + * resolved
|
| + */
|
| + Object getHtmlResolutionData2(Source source, HtmlEntry htmlEntry, DataDescriptor descriptor) {
|
| + htmlEntry = cacheHtmlResolutionData(source, htmlEntry, descriptor);
|
| + return htmlEntry.getValue(descriptor);
|
| + }
|
| +
|
| + /**
|
| + * Look through the cache for a task that needs to be performed. Return the task that was found,
|
| + * or `null` if there is no more work to be done.
|
| + *
|
| + * @return the next task that needs to be performed
|
| + */
|
| + AnalysisTask get nextTaskAnalysisTask {
|
| + {
|
| + for (Source source in _cache.priorityOrder) {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry is DartEntry) {
|
| + DartEntry dartEntry = sourceEntry as DartEntry;
|
| + CacheState parseErrorsState = dartEntry.getState(DartEntry.PARSE_ERRORS);
|
| + if (identical(parseErrorsState, CacheState.INVALID) || identical(parseErrorsState, CacheState.FLUSHED)) {
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.setState(DartEntry.PARSE_ERRORS, CacheState.IN_PROCESS);
|
| + _cache.put(source, dartCopy);
|
| + return new ParseDartTask(this, source);
|
| + }
|
| + CacheState parseUnitState = dartEntry.getState(DartEntry.PARSED_UNIT);
|
| + if (identical(parseUnitState, CacheState.INVALID) || identical(parseUnitState, CacheState.FLUSHED)) {
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.setState(DartEntry.PARSED_UNIT, CacheState.IN_PROCESS);
|
| + _cache.put(source, dartCopy);
|
| + return new ParseDartTask(this, source);
|
| + }
|
| + for (Source librarySource in getLibrariesContaining(source)) {
|
| + SourceEntry libraryEntry = _cache.get(librarySource);
|
| + if (libraryEntry is DartEntry) {
|
| + CacheState elementState = libraryEntry.getState(DartEntry.ELEMENT);
|
| + if (identical(elementState, CacheState.INVALID) || identical(elementState, CacheState.FLUSHED)) {
|
| + DartEntryImpl libraryCopy = ((libraryEntry as DartEntry)).writableCopy;
|
| + libraryCopy.setState(DartEntry.ELEMENT, CacheState.IN_PROCESS);
|
| + _cache.put(librarySource, libraryCopy);
|
| + return new ResolveDartLibraryTask(this, source, librarySource);
|
| + }
|
| + CacheState resolvedUnitState = dartEntry.getState2(DartEntry.RESOLVED_UNIT, librarySource);
|
| + if (identical(resolvedUnitState, CacheState.INVALID) || identical(resolvedUnitState, CacheState.FLUSHED)) {
|
| + LibraryElement libraryElement = libraryEntry.getValue(DartEntry.ELEMENT);
|
| + if (libraryElement != null) {
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.setState2(DartEntry.RESOLVED_UNIT, librarySource, CacheState.IN_PROCESS);
|
| + _cache.put(source, dartCopy);
|
| + return new ResolveDartUnitTask(this, source, libraryElement);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + } else if (sourceEntry is HtmlEntry) {
|
| + HtmlEntry htmlEntry = sourceEntry as HtmlEntry;
|
| + CacheState parsedUnitState = htmlEntry.getState(HtmlEntry.PARSED_UNIT);
|
| + if (identical(parsedUnitState, CacheState.INVALID) || identical(parsedUnitState, CacheState.FLUSHED)) {
|
| + HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| + htmlCopy.setState(HtmlEntry.PARSED_UNIT, CacheState.IN_PROCESS);
|
| + _cache.put(source, htmlCopy);
|
| + return new ParseHtmlTask(this, source);
|
| + }
|
| + CacheState elementState = htmlEntry.getState(HtmlEntry.ELEMENT);
|
| + if (identical(elementState, CacheState.INVALID) || identical(elementState, CacheState.FLUSHED)) {
|
| + HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| + htmlCopy.setState(HtmlEntry.ELEMENT, CacheState.IN_PROCESS);
|
| + _cache.put(source, htmlCopy);
|
| + return new ResolveHtmlTask(this, source);
|
| + }
|
| + }
|
| + }
|
| + for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
|
| + SourceEntry sourceEntry = entry.getValue();
|
| + if (sourceEntry is DartEntry) {
|
| + DartEntry dartEntry = sourceEntry as DartEntry;
|
| + if (identical(dartEntry.getState(DartEntry.PARSED_UNIT), CacheState.INVALID)) {
|
| + Source source = entry.getKey();
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.setState(DartEntry.PARSE_ERRORS, CacheState.IN_PROCESS);
|
| + _cache.put(source, dartCopy);
|
| + return new ParseDartTask(this, source);
|
| + }
|
| + } else if (sourceEntry is HtmlEntry) {
|
| + HtmlEntry htmlEntry = sourceEntry as HtmlEntry;
|
| + if (identical(htmlEntry.getState(HtmlEntry.PARSED_UNIT), CacheState.INVALID)) {
|
| + Source source = entry.getKey();
|
| + HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| + htmlCopy.setState(HtmlEntry.PARSED_UNIT, CacheState.IN_PROCESS);
|
| + _cache.put(source, htmlCopy);
|
| + return new ParseHtmlTask(this, source);
|
| + }
|
| + }
|
| + }
|
| + for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
|
| + SourceEntry sourceEntry = entry.getValue();
|
| + if (sourceEntry is DartEntry && identical(sourceEntry.kind, SourceKind.LIBRARY)) {
|
| + DartEntry dartEntry = sourceEntry as DartEntry;
|
| + if (identical(dartEntry.getState(DartEntry.ELEMENT), CacheState.INVALID)) {
|
| + Source source = entry.getKey();
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.setState(DartEntry.ELEMENT, CacheState.IN_PROCESS);
|
| + _cache.put(source, dartCopy);
|
| + return new ResolveDartLibraryTask(this, source, source);
|
| + }
|
| + } else if (sourceEntry is HtmlEntry) {
|
| + HtmlEntry htmlEntry = sourceEntry as HtmlEntry;
|
| + if (identical(htmlEntry.getState(HtmlEntry.ELEMENT), CacheState.INVALID)) {
|
| + Source source = entry.getKey();
|
| + HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| + htmlCopy.setState(HtmlEntry.ELEMENT, CacheState.IN_PROCESS);
|
| + _cache.put(source, htmlCopy);
|
| + return new ResolveHtmlTask(this, source);
|
| + }
|
| + }
|
| + }
|
| + return null;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Return a change notice for the given source, creating one if one does not already exist.
|
| + *
|
| + * @param source the source for which changes are being reported
|
| + * @return a change notice for the given source
|
| + */
|
| + ChangeNoticeImpl getNotice(Source source) {
|
| + ChangeNoticeImpl notice = _pendingNotices[source];
|
| + if (notice == null) {
|
| + notice = new ChangeNoticeImpl(source);
|
| + _pendingNotices[source] = notice;
|
| + }
|
| + return notice;
|
| + }
|
| +
|
| + /**
|
| + * Return the cache entry associated with the given source, or `null` if the source is not a
|
| + * Dart file.
|
| + *
|
| + * @param source the source for which a cache entry is being sought
|
| + * @return the source cache entry associated with the given source
|
| + */
|
| + DartEntry getReadableDartEntry(Source source) {
|
| + {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry == null) {
|
| + sourceEntry = createSourceEntry(source);
|
| + }
|
| + if (sourceEntry is DartEntry) {
|
| + _cache.accessed(source);
|
| + return sourceEntry as DartEntry;
|
| + }
|
| + return null;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Return the cache entry associated with the given source, or `null` if the source is not
|
| + * an HTML file.
|
| + *
|
| + * @param source the source for which a cache entry is being sought
|
| + * @return the source cache entry associated with the given source
|
| + */
|
| + HtmlEntry getReadableHtmlEntry(Source source) {
|
| + {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry == null) {
|
| + sourceEntry = createSourceEntry(source);
|
| + }
|
| + if (sourceEntry is HtmlEntry) {
|
| + _cache.accessed(source);
|
| + return sourceEntry as HtmlEntry;
|
| + }
|
| + return null;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Return the cache entry associated with the given source, or `null` if there is no entry
|
| + * associated with the source.
|
| + *
|
| + * @param source the source for which a cache entry is being sought
|
| + * @return the source cache entry associated with the given source
|
| + */
|
| + SourceEntry getReadableSourceEntry(Source source) {
|
| + {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry == null) {
|
| + sourceEntry = createSourceEntry(source);
|
| + }
|
| + if (sourceEntry != null) {
|
| + _cache.accessed(source);
|
| + }
|
| + return sourceEntry;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Return an array containing all of the sources known to this context that have the given kind.
|
| + *
|
| + * @param kind the kind of sources to be returned
|
| + * @return all of the sources known to this context that have the given kind
|
| + */
|
| + List<Source> getSources(SourceKind kind2) {
|
| + List<Source> sources = new List<Source>();
|
| + {
|
| + for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
|
| + if (identical(entry.getValue().kind, kind2)) {
|
| + sources.add(entry.getKey());
|
| + }
|
| + }
|
| + }
|
| + return new List.from(sources);
|
| + }
|
| +
|
| + /**
|
| + * Invalidate all of the resolution results computed by this context.
|
| + *
|
| + * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
|
| + */
|
| + void invalidateAllResolutionInformation() {
|
| + for (MapEntry<Source, SourceEntry> mapEntry in _cache.entrySet()) {
|
| + SourceEntry sourceEntry = mapEntry.getValue();
|
| + if (sourceEntry is HtmlEntry) {
|
| + HtmlEntryImpl htmlCopy = ((sourceEntry as HtmlEntry)).writableCopy;
|
| + htmlCopy.invalidateAllResolutionInformation();
|
| + mapEntry.setValue(htmlCopy);
|
| + } else if (sourceEntry is DartEntry) {
|
| + DartEntryImpl dartCopy = ((sourceEntry as DartEntry)).writableCopy;
|
| + dartCopy.invalidateAllResolutionInformation();
|
| + mapEntry.setValue(dartCopy);
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * In response to a change to at least one of the compilation units in the given library,
|
| + * invalidate any results that are dependent on the result of resolving that library.
|
| + *
|
| + * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
|
| + *
|
| + * @param librarySource the source of the library being invalidated
|
| + */
|
| + void invalidateLibraryResolution(Source librarySource) {
|
| + DartEntry libraryEntry = getReadableDartEntry(librarySource);
|
| + if (libraryEntry != null) {
|
| + List<Source> includedParts = libraryEntry.getValue(DartEntry.INCLUDED_PARTS);
|
| + DartEntryImpl libraryCopy = libraryEntry.writableCopy;
|
| + libraryCopy.invalidateAllResolutionInformation();
|
| + libraryCopy.setState(DartEntry.INCLUDED_PARTS, CacheState.INVALID);
|
| + _cache.put(librarySource, libraryCopy);
|
| + for (Source partSource in includedParts) {
|
| + DartEntry partEntry = getReadableDartEntry(partSource);
|
| + if (partEntry != null) {
|
| + DartEntryImpl partCopy = partEntry.writableCopy;
|
| + partCopy.invalidateAllResolutionInformation();
|
| + _cache.put(partSource, partCopy);
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Return `true` if this library is, or depends on, dart:html.
|
| + *
|
| + * @param library the library being tested
|
| + * @param visitedLibraries a collection of the libraries that have been visited, used to prevent
|
| + * infinite recursion
|
| + * @return `true` if this library is, or depends on, dart:html
|
| + */
|
| + bool isClient(LibraryElement library, Source htmlSource, Set<LibraryElement> visitedLibraries) {
|
| + if (visitedLibraries.contains(library)) {
|
| + return false;
|
| + }
|
| + if (library.source == htmlSource) {
|
| + return true;
|
| + }
|
| + javaSetAdd(visitedLibraries, library);
|
| + for (LibraryElement imported in library.importedLibraries) {
|
| + if (isClient(imported, htmlSource, visitedLibraries)) {
|
| + return true;
|
| + }
|
| + }
|
| + for (LibraryElement exported in library.exportedLibraries) {
|
| + if (isClient(exported, htmlSource, visitedLibraries)) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + /**
|
| + * Given a cache entry and a library element, record the library element and other information
|
| + * gleaned from the element in the cache entry.
|
| + *
|
| + * @param dartCopy the cache entry in which data is to be recorded
|
| + * @param library the library element used to record information
|
| + * @param htmlSource the source for the HTML library
|
| + */
|
| + void recordElementData(DartEntryImpl dartCopy, LibraryElement library, Source htmlSource) {
|
| + dartCopy.setValue(DartEntry.ELEMENT, library);
|
| + dartCopy.setValue(DartEntry.IS_LAUNCHABLE, library.entryPoint != null);
|
| + dartCopy.setValue(DartEntry.IS_CLIENT, isClient(library, htmlSource, new Set<LibraryElement>()));
|
| + List<Source> unitSources = new List<Source>();
|
| + unitSources.add(library.definingCompilationUnit.source);
|
| + for (CompilationUnitElement part in library.parts) {
|
| + Source partSource = part.source;
|
| + unitSources.add(partSource);
|
| + }
|
| + dartCopy.setValue(DartEntry.INCLUDED_PARTS, new List.from(unitSources));
|
| + }
|
| +
|
| + /**
|
| + * Record the results produced by performing a [ParseDartTask]. If the results were computed
|
| + * from data that is now out-of-date, then the results will not be recorded.
|
| + *
|
| + * @param task the task that was performed
|
| + * @return an entry containing the computed results
|
| + * @throws AnalysisException if the results could not be recorded
|
| + */
|
| + DartEntry recordParseDartTaskResults(ParseDartTask task) {
|
| + Source source = task.source;
|
| + AnalysisException thrownException = task.exception;
|
| + DartEntry dartEntry = null;
|
| + {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry is! DartEntry) {
|
| + throw new AnalysisException.con1("Internal error: attempting to parse non-Dart file as a Dart file: ${source.fullName}");
|
| + }
|
| + dartEntry = sourceEntry as DartEntry;
|
| + _cache.accessed(source);
|
| + int sourceTime = source.modificationStamp;
|
| + int resultTime = task.modificationTime;
|
| + if (sourceTime == resultTime) {
|
| + if (dartEntry.modificationTime != sourceTime) {
|
| + sourceChanged(source);
|
| + dartEntry = getReadableDartEntry(source);
|
| + if (dartEntry == null) {
|
| + throw new AnalysisException.con1("A Dart file became a non-Dart file: ${source.fullName}");
|
| + }
|
| + }
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + if (thrownException == null) {
|
| + LineInfo lineInfo = task.lineInfo;
|
| + dartCopy.setValue(SourceEntry.LINE_INFO, lineInfo);
|
| + if (task.hasPartOfDirective() && !task.hasLibraryDirective()) {
|
| + dartCopy.setValue(DartEntry.SOURCE_KIND, SourceKind.PART);
|
| + } else {
|
| + dartCopy.setValue(DartEntry.SOURCE_KIND, SourceKind.LIBRARY);
|
| + }
|
| + dartCopy.setValue(DartEntry.PARSED_UNIT, task.compilationUnit);
|
| + dartCopy.setValue(DartEntry.PARSE_ERRORS, task.errors);
|
| + dartCopy.setValue(DartEntry.EXPORTED_LIBRARIES, task.exportedSources);
|
| + dartCopy.setValue(DartEntry.IMPORTED_LIBRARIES, task.importedSources);
|
| + dartCopy.setValue(DartEntry.INCLUDED_PARTS, task.includedSources);
|
| + } else {
|
| + dartCopy.recordParseError();
|
| + }
|
| + _cache.put(source, dartCopy);
|
| + dartEntry = dartCopy;
|
| + } else {
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.recordParseNotInProcess();
|
| + _cache.put(source, dartCopy);
|
| + dartEntry = dartCopy;
|
| + }
|
| + }
|
| + if (thrownException != null) {
|
| + throw thrownException;
|
| + }
|
| + return dartEntry;
|
| + }
|
| +
|
| + /**
|
| + * Record the results produced by performing a [ParseHtmlTask]. If the results were computed
|
| + * from data that is now out-of-date, then the results will not be recorded.
|
| + *
|
| + * @param task the task that was performed
|
| + * @return an entry containing the computed results
|
| + * @throws AnalysisException if the results could not be recorded
|
| + */
|
| + HtmlEntry recordParseHtmlTaskResults(ParseHtmlTask task) {
|
| + Source source = task.source;
|
| + AnalysisException thrownException = task.exception;
|
| + HtmlEntry htmlEntry = null;
|
| + {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry is! HtmlEntry) {
|
| + throw new AnalysisException.con1("Internal error: attempting to parse non-HTML file as a HTML file: ${source.fullName}");
|
| + }
|
| + htmlEntry = sourceEntry as HtmlEntry;
|
| + _cache.accessed(source);
|
| + int sourceTime = source.modificationStamp;
|
| + int resultTime = task.modificationTime;
|
| + if (sourceTime == resultTime) {
|
| + if (htmlEntry.modificationTime != sourceTime) {
|
| + sourceChanged(source);
|
| + htmlEntry = getReadableHtmlEntry(source);
|
| + if (htmlEntry == null) {
|
| + throw new AnalysisException.con1("An HTML file became a non-HTML file: ${source.fullName}");
|
| + }
|
| + }
|
| + HtmlEntryImpl htmlCopy = ((sourceEntry as HtmlEntry)).writableCopy;
|
| + if (thrownException == null) {
|
| + LineInfo lineInfo = task.lineInfo;
|
| + HtmlUnit unit = task.htmlUnit;
|
| + htmlCopy.setValue(SourceEntry.LINE_INFO, lineInfo);
|
| + htmlCopy.setValue(HtmlEntry.PARSED_UNIT, unit);
|
| + htmlCopy.setValue(HtmlEntry.REFERENCED_LIBRARIES, task.referencedLibraries);
|
| + ChangeNoticeImpl notice = getNotice(source);
|
| + notice.setErrors(htmlEntry.allErrors, lineInfo);
|
| + } else {
|
| + htmlCopy.setState(SourceEntry.LINE_INFO, CacheState.ERROR);
|
| + htmlCopy.setState(HtmlEntry.PARSED_UNIT, CacheState.ERROR);
|
| + htmlCopy.setState(HtmlEntry.REFERENCED_LIBRARIES, CacheState.ERROR);
|
| + }
|
| + _cache.put(source, htmlCopy);
|
| + htmlEntry = htmlCopy;
|
| + } else {
|
| + HtmlEntryImpl htmlCopy = ((sourceEntry as HtmlEntry)).writableCopy;
|
| + if (identical(htmlCopy.getState(SourceEntry.LINE_INFO), CacheState.IN_PROCESS)) {
|
| + htmlCopy.setState(SourceEntry.LINE_INFO, CacheState.INVALID);
|
| + }
|
| + if (identical(htmlCopy.getState(HtmlEntry.PARSED_UNIT), CacheState.IN_PROCESS)) {
|
| + htmlCopy.setState(HtmlEntry.PARSED_UNIT, CacheState.INVALID);
|
| + }
|
| + if (identical(htmlCopy.getState(HtmlEntry.REFERENCED_LIBRARIES), CacheState.IN_PROCESS)) {
|
| + htmlCopy.setState(HtmlEntry.REFERENCED_LIBRARIES, CacheState.INVALID);
|
| + }
|
| + _cache.put(source, htmlCopy);
|
| + htmlEntry = htmlCopy;
|
| + }
|
| + }
|
| + if (thrownException != null) {
|
| + throw thrownException;
|
| + }
|
| + return htmlEntry;
|
| + }
|
| +
|
| + /**
|
| + * Record the results produced by performing a [ResolveDartLibraryTask]. If the results were
|
| + * computed from data that is now out-of-date, then the results will not be recorded.
|
| + *
|
| + * @param task the task that was performed
|
| + * @return an entry containing the computed results
|
| + * @throws AnalysisException if the results could not be recorded
|
| + */
|
| + DartEntry recordResolveDartLibraryTaskResults(ResolveDartLibraryTask task) {
|
| + LibraryResolver resolver = task.libraryResolver;
|
| + AnalysisException thrownException = task.exception;
|
| + DartEntry unitEntry = null;
|
| + {
|
| + if (allModificationTimesMatch(resolver)) {
|
| + Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML);
|
| + Source unitSource = task.unitSource;
|
| + RecordingErrorListener errorListener = resolver.errorListener;
|
| + for (Library library in resolver.resolvedLibraries) {
|
| + Source librarySource = library.librarySource;
|
| + for (Source source in library.compilationUnitSources) {
|
| + CompilationUnit unit = library.getAST(source);
|
| + List<AnalysisError> errors = errorListener.getErrors2(source);
|
| + unit.resolutionErrors = errors;
|
| + LineInfo lineInfo = unit.lineInfo;
|
| + DartEntry dartEntry = _cache.get(source) as DartEntry;
|
| + int sourceTime = source.modificationStamp;
|
| + if (dartEntry.modificationTime != sourceTime) {
|
| + sourceChanged(source);
|
| + dartEntry = getReadableDartEntry(source);
|
| + if (dartEntry == null) {
|
| + throw new AnalysisException.con1("A Dart file became a non-Dart file: ${source.fullName}");
|
| + }
|
| + }
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + if (thrownException == null) {
|
| + dartCopy.setValue(SourceEntry.LINE_INFO, lineInfo);
|
| + dartCopy.setState(DartEntry.PARSED_UNIT, CacheState.FLUSHED);
|
| + dartCopy.setValue2(DartEntry.RESOLVED_UNIT, librarySource, unit);
|
| + dartCopy.setValue2(DartEntry.RESOLUTION_ERRORS, librarySource, errors);
|
| + if (identical(source, librarySource)) {
|
| + recordElementData(dartCopy, library.libraryElement, htmlSource);
|
| + }
|
| + } else {
|
| + dartCopy.recordResolutionError();
|
| + }
|
| + _cache.put(source, dartCopy);
|
| + if (source == unitSource) {
|
| + unitEntry = dartCopy;
|
| + }
|
| + ChangeNoticeImpl notice = getNotice(source);
|
| + notice.compilationUnit = unit;
|
| + notice.setErrors(dartCopy.allErrors, lineInfo);
|
| + }
|
| + }
|
| + } else {
|
| + for (Library library in resolver.resolvedLibraries) {
|
| + for (Source source in library.compilationUnitSources) {
|
| + DartEntry dartEntry = getReadableDartEntry(source);
|
| + if (dartEntry != null) {
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.recordResolutionNotInProcess();
|
| + _cache.put(source, dartCopy);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| + if (thrownException != null) {
|
| + throw thrownException;
|
| + }
|
| + return unitEntry;
|
| + }
|
| +
|
| + /**
|
| + * Record the results produced by performing a [ResolveDartUnitTask]. If the results were
|
| + * computed from data that is now out-of-date, then the results will not be recorded.
|
| + *
|
| + * @param task the task that was performed
|
| + * @return an entry containing the computed results
|
| + * @throws AnalysisException if the results could not be recorded
|
| + */
|
| + SourceEntry recordResolveDartUnitTaskResults(ResolveDartUnitTask task) {
|
| + Source source = task.source;
|
| + AnalysisException thrownException = task.exception;
|
| + DartEntry dartEntry = null;
|
| + {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry is! DartEntry) {
|
| + throw new AnalysisException.con1("Internal error: attempting to reolve non-Dart file as a Dart file: ${source.fullName}");
|
| + }
|
| + dartEntry = sourceEntry as DartEntry;
|
| + _cache.accessed(source);
|
| + int sourceTime = source.modificationStamp;
|
| + int resultTime = task.modificationTime;
|
| + if (sourceTime == resultTime) {
|
| + if (dartEntry.modificationTime != sourceTime) {
|
| + sourceChanged(source);
|
| + dartEntry = getReadableDartEntry(source);
|
| + if (dartEntry == null) {
|
| + throw new AnalysisException.con1("A Dart file became a non-Dart file: ${source.fullName}");
|
| + }
|
| + }
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + if (thrownException == null) {
|
| + dartCopy.setValue2(DartEntry.RESOLVED_UNIT, task.librarySource, task.resolvedUnit);
|
| + } else {
|
| + dartCopy.setState(DartEntry.RESOLVED_UNIT, CacheState.ERROR);
|
| + }
|
| + _cache.put(source, dartCopy);
|
| + dartEntry = dartCopy;
|
| + } else {
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + if (identical(dartCopy.getState(DartEntry.RESOLVED_UNIT), CacheState.IN_PROCESS)) {
|
| + dartCopy.setState(DartEntry.RESOLVED_UNIT, CacheState.INVALID);
|
| + }
|
| + _cache.put(source, dartCopy);
|
| + dartEntry = dartCopy;
|
| + }
|
| + }
|
| + if (thrownException != null) {
|
| + throw thrownException;
|
| + }
|
| + return dartEntry;
|
| + }
|
| +
|
| + /**
|
| + * Record the results produced by performing a [ResolveHtmlTask]. If the results were
|
| + * computed from data that is now out-of-date, then the results will not be recorded.
|
| + *
|
| + * @param task the task that was performed
|
| + * @return an entry containing the computed results
|
| + * @throws AnalysisException if the results could not be recorded
|
| + */
|
| + SourceEntry recordResolveHtmlTaskResults(ResolveHtmlTask task) {
|
| + Source source = task.source;
|
| + AnalysisException thrownException = task.exception;
|
| + HtmlEntry htmlEntry = null;
|
| + {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry is! HtmlEntry) {
|
| + throw new AnalysisException.con1("Internal error: attempting to reolve non-HTML file as an HTML file: ${source.fullName}");
|
| + }
|
| + htmlEntry = sourceEntry as HtmlEntry;
|
| + _cache.accessed(source);
|
| + int sourceTime = source.modificationStamp;
|
| + int resultTime = task.modificationTime;
|
| + if (sourceTime == resultTime) {
|
| + if (htmlEntry.modificationTime != sourceTime) {
|
| + sourceChanged(source);
|
| + htmlEntry = getReadableHtmlEntry(source);
|
| + if (htmlEntry == null) {
|
| + throw new AnalysisException.con1("An HTML file became a non-HTML file: ${source.fullName}");
|
| + }
|
| + }
|
| + HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| + if (thrownException == null) {
|
| + htmlCopy.setValue(HtmlEntry.ELEMENT, task.element);
|
| + htmlCopy.setValue(HtmlEntry.RESOLUTION_ERRORS, task.resolutionErrors);
|
| + } else {
|
| + htmlCopy.recordResolutionError();
|
| + }
|
| + _cache.put(source, htmlCopy);
|
| + htmlEntry = htmlCopy;
|
| + } else {
|
| + HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| + if (identical(htmlCopy.getState(HtmlEntry.ELEMENT), CacheState.IN_PROCESS)) {
|
| + htmlCopy.setState(HtmlEntry.ELEMENT, CacheState.INVALID);
|
| + }
|
| + if (identical(htmlCopy.getState(HtmlEntry.RESOLUTION_ERRORS), CacheState.IN_PROCESS)) {
|
| + htmlCopy.setState(HtmlEntry.RESOLUTION_ERRORS, CacheState.INVALID);
|
| + }
|
| + _cache.put(source, htmlCopy);
|
| + htmlEntry = htmlCopy;
|
| + }
|
| + }
|
| + if (thrownException != null) {
|
| + throw thrownException;
|
| + }
|
| + return htmlEntry;
|
| + }
|
| +
|
| + /**
|
| + * Create an entry for the newly added source. Return `true` if the new source is a Dart
|
| + * file.
|
| + *
|
| + * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
|
| + *
|
| + * @param source the source that has been added
|
| + * @return `true` if the new source is a Dart file
|
| + */
|
| + bool sourceAvailable(Source source) {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry == null) {
|
| + sourceEntry = createSourceEntry(source);
|
| + } else {
|
| + SourceEntryImpl sourceCopy = sourceEntry.writableCopy;
|
| + sourceCopy.modificationTime = source.modificationStamp;
|
| + _cache.put(source, sourceCopy);
|
| + }
|
| + return sourceEntry is DartEntry;
|
| + }
|
| +
|
| + /**
|
| + * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
|
| + *
|
| + * @param source the source that has been changed
|
| + */
|
| + void sourceChanged(Source source) {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry is HtmlEntry) {
|
| + HtmlEntryImpl htmlCopy = ((sourceEntry as HtmlEntry)).writableCopy;
|
| + htmlCopy.modificationTime = source.modificationStamp;
|
| + htmlCopy.invalidateAllInformation();
|
| + _cache.put(source, htmlCopy);
|
| + } else if (sourceEntry is DartEntry) {
|
| + List<Source> containingLibraries = getLibrariesContaining(source);
|
| + for (Source library in containingLibraries) {
|
| + invalidateLibraryResolution(library);
|
| + }
|
| + DartEntryImpl dartCopy = ((sourceEntry as DartEntry)).writableCopy;
|
| + dartCopy.modificationTime = source.modificationStamp;
|
| + dartCopy.invalidateAllInformation();
|
| + _cache.put(source, dartCopy);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
|
| + *
|
| + * @param source the source that has been deleted
|
| + */
|
| + void sourceRemoved(Source source) {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry is DartEntry) {
|
| + Set<Source> libraries = new Set<Source>();
|
| + for (Source librarySource in getLibrariesContaining(source)) {
|
| + javaSetAdd(libraries, librarySource);
|
| + for (Source dependentLibrary in getLibrariesDependingOn(librarySource)) {
|
| + javaSetAdd(libraries, dependentLibrary);
|
| + }
|
| + }
|
| + for (Source librarySource in libraries) {
|
| + invalidateLibraryResolution(librarySource);
|
| + }
|
| + }
|
| + _cache.remove(source);
|
| + }
|
| +}
|
| +/**
|
| + * Instances of the class `AnalysisTaskResultRecorder` are used by an analysis context to
|
| + * record the results of a task.
|
| + */
|
| +class AnalysisContextImpl2_AnalysisTaskResultRecorder implements AnalysisTaskVisitor<SourceEntry> {
|
| + final AnalysisContextImpl2 AnalysisContextImpl2_this;
|
| + AnalysisContextImpl2_AnalysisTaskResultRecorder(this.AnalysisContextImpl2_this);
|
| + DartEntry visitParseDartTask(ParseDartTask task) => AnalysisContextImpl2_this.recordParseDartTaskResults(task);
|
| + HtmlEntry visitParseHtmlTask(ParseHtmlTask task) => AnalysisContextImpl2_this.recordParseHtmlTaskResults(task);
|
| + DartEntry visitResolveDartLibraryTask(ResolveDartLibraryTask task) => AnalysisContextImpl2_this.recordResolveDartLibraryTaskResults(task);
|
| + SourceEntry visitResolveDartUnitTask(ResolveDartUnitTask task) => AnalysisContextImpl2_this.recordResolveDartUnitTaskResults(task);
|
| + SourceEntry visitResolveHtmlTask(ResolveHtmlTask task) => AnalysisContextImpl2_this.recordResolveHtmlTaskResults(task);
|
| +}
|
| +/**
|
| + * Instances of the class `AnalysisErrorInfoImpl` represent the analysis errors and line info
|
| + * associated with a source.
|
| + */
|
| +class AnalysisErrorInfoImpl implements AnalysisErrorInfo {
|
| +
|
| + /**
|
| + * The analysis errors associated with a source, or `null` if there are no errors.
|
| + */
|
| + List<AnalysisError> _errors;
|
| +
|
| + /**
|
| + * The line information associated with the errors, or `null` if there are no errors.
|
| + */
|
| + LineInfo _lineInfo;
|
| +
|
| + /**
|
| + * Initialize an newly created error info with the errors and line information
|
| + *
|
| + * @param errors the errors as a result of analysis
|
| + * @param lineinfo the line info for the errors
|
| + */
|
| + AnalysisErrorInfoImpl(List<AnalysisError> errors, LineInfo lineInfo) {
|
| + this._errors = errors;
|
| + this._lineInfo = lineInfo;
|
| + }
|
| +
|
| + /**
|
| + * Return the errors of analysis, or `null` if there were no errors.
|
| + *
|
| + * @return the errors as a result of the analysis
|
| + */
|
| + List<AnalysisError> get errors => _errors;
|
| +
|
| + /**
|
| + * Return the line information associated with the errors, or `null` if there were no
|
| + * errors.
|
| + *
|
| + * @return the line information associated with the errors
|
| + */
|
| + LineInfo get lineInfo => _lineInfo;
|
| +}
|
| +/**
|
| + * Instances of the class `AnalysisOptions` represent a set of analysis options used to
|
| + * control the behavior of an analysis context.
|
| + */
|
| +class AnalysisOptionsImpl implements AnalysisOptions {
|
| +
|
| + /**
|
| + * A flag indicating whether analysis is to use strict mode. In strict mode, error reporting is
|
| + * based exclusively on the static type information.
|
| + */
|
| + bool _strictMode = true;
|
| +
|
| + /**
|
| + * A flag indicating whether analysis is to generate hint results (e.g. type inference based
|
| + * information and pub best practices).
|
| + */
|
| + bool _hint = true;
|
| + bool get hint => _hint;
|
| +
|
| + /**
|
| + * Return `true` if analysis is to use strict mode. In strict mode, error reporting is based
|
| + * exclusively on the static type information.
|
| + *
|
| + * @return `true` if analysis is to use strict mode
|
| + */
|
| + bool get strictMode => _strictMode;
|
| +
|
| + /**
|
| + * Set whether analysis is to generate hint results (e.g. type inference based information and pub
|
| + * best practices).
|
| + *
|
| + * @param hint `true` if analysis is to generate hint results
|
| + */
|
| + void set hint(bool hint2) {
|
| + this._hint = hint2;
|
| + }
|
| +
|
| + /**
|
| + * Set whether analysis is to use strict mode to the given value. In strict mode, error reporting
|
| + * is based exclusively on the static type information.
|
| + *
|
| + * @param isStrict `true` if analysis is to use strict mode
|
| + */
|
| + void set strictMode(bool isStrict) {
|
| + _strictMode = isStrict;
|
| + }
|
| +}
|
| +/**
|
| + * The enumeration `CacheState` defines the possible states of cached data.
|
| + */
|
| +class CacheState extends Enum<CacheState> {
|
| +
|
| + /**
|
| + * The data is not in the cache and the last time an attempt was made to compute the data an
|
| + * exception occurred, making it pointless to attempt.
|
| + *
|
| + * Valid Transitions:
|
| + *
|
| + * * [INVALID] if a source was modified that might cause the data to be computable
|
| + *
|
| + */
|
| + static final CacheState ERROR = new CacheState('ERROR', 0);
|
| +
|
| + /**
|
| + * The data is not in the cache because it was flushed from the cache in order to control memory
|
| + * usage. If the data is recomputed, results do not need to be reported.
|
| + *
|
| + * Valid Transitions:
|
| + *
|
| + * * [IN_PROCESS] if the data is being recomputed
|
| + * * [INVALID] if a source was modified that causes the data to need to be recomputed
|
| + *
|
| + */
|
| + static final CacheState FLUSHED = new CacheState('FLUSHED', 1);
|
| +
|
| + /**
|
| + * The data might or might not be in the cache but is in the process of being recomputed.
|
| + *
|
| + * Valid Transitions:
|
| + *
|
| + * * [ERROR] if an exception occurred while trying to compute the data
|
| + * * [VALID] if the data was successfully computed and stored in the cache
|
| + *
|
| + */
|
| + static final CacheState IN_PROCESS = new CacheState('IN_PROCESS', 2);
|
| +
|
| + /**
|
| + * The data is not in the cache and needs to be recomputed so that results can be reported.
|
| + *
|
| + * Valid Transitions:
|
| + *
|
| + * * [IN_PROCESS] if an attempt is being made to recompute the data
|
| + *
|
| + */
|
| + static final CacheState INVALID = new CacheState('INVALID', 3);
|
| +
|
| + /**
|
| + * The data is in the cache and up-to-date.
|
| + *
|
| + * Valid Transitions:
|
| + *
|
| + * * [FLUSHED] if the data is removed in order to manage memory usage
|
| + * * [INVALID] if a source was modified in such a way as to invalidate the previous data
|
| + *
|
| + */
|
| + static final CacheState VALID = new CacheState('VALID', 4);
|
| + static final List<CacheState> values = [ERROR, FLUSHED, IN_PROCESS, INVALID, VALID];
|
| + CacheState(String name, int ordinal) : super(name, ordinal);
|
| +}
|
| +/**
|
| + * Instances of the class `ChangeNoticeImpl` represent a change to the analysis results
|
| + * associated with a given source.
|
| + *
|
| + * @coverage dart.engine
|
| + */
|
| +class ChangeNoticeImpl implements ChangeNotice {
|
| +
|
| + /**
|
| + * The source for which the result is being reported.
|
| + */
|
| + Source _source;
|
| +
|
| + /**
|
| + * The fully resolved AST that changed as a result of the analysis, or `null` if the AST was
|
| + * not changed.
|
| + */
|
| + CompilationUnit _compilationUnit;
|
| +
|
| + /**
|
| + * The errors that changed as a result of the analysis, or `null` if errors were not
|
| + * changed.
|
| + */
|
| + List<AnalysisError> _errors;
|
| +
|
| + /**
|
| + * The line information associated with the source, or `null` if errors were not changed.
|
| + */
|
| + LineInfo _lineInfo;
|
| +
|
| + /**
|
| + * An empty array of change notices.
|
| + */
|
| + static List<ChangeNoticeImpl> EMPTY_ARRAY = new List<ChangeNoticeImpl>(0);
|
| +
|
| + /**
|
| + * Initialize a newly created notice associated with the given source.
|
| + *
|
| + * @param source the source for which the change is being reported
|
| + */
|
| + ChangeNoticeImpl(Source source) {
|
| + this._source = source;
|
| + }
|
| +
|
| + /**
|
| + * Return the fully resolved AST that changed as a result of the analysis, or `null` if the
|
| + * AST was not changed.
|
| + *
|
| + * @return the fully resolved AST that changed as a result of the analysis
|
| + */
|
| + CompilationUnit get compilationUnit => _compilationUnit;
|
| +
|
| + /**
|
| + * Return the errors that changed as a result of the analysis, or `null` if errors were not
|
| + * changed.
|
| + *
|
| + * @return the errors that changed as a result of the analysis
|
| + */
|
| + List<AnalysisError> get errors => _errors;
|
| +
|
| + /**
|
| + * Return the line information associated with the source, or `null` if errors were not
|
| + * changed.
|
| + *
|
| + * @return the line information associated with the source
|
| + */
|
| + LineInfo get lineInfo => _lineInfo;
|
| +
|
| + /**
|
| + * Return the source for which the result is being reported.
|
| + *
|
| + * @return the source for which the result is being reported
|
| + */
|
| + Source get source => _source;
|
| +
|
| + /**
|
| + * Set the fully resolved AST that changed as a result of the analysis to the given AST.
|
| + *
|
| + * @param compilationUnit the fully resolved AST that changed as a result of the analysis
|
| + */
|
| + void set compilationUnit(CompilationUnit compilationUnit2) {
|
| + this._compilationUnit = compilationUnit2;
|
| + }
|
| +
|
| + /**
|
| + * Set the errors that changed as a result of the analysis to the given errors and set the line
|
| + * information to the given line information.
|
| + *
|
| + * @param errors the errors that changed as a result of the analysis
|
| + * @param lineInfo the line information associated with the source
|
| + */
|
| + void setErrors(List<AnalysisError> errors2, LineInfo lineInfo2) {
|
| + this._errors = errors2;
|
| + this._lineInfo = lineInfo2;
|
| + }
|
| +}
|
| +/**
|
| + * Instances of the class `DelegatingAnalysisContextImpl` extend [AnalysisContextImpl
|
| + ] to delegate sources to the appropriate analysis context. For instance, if the
|
| + * source is in a system library then the analysis context from the [DartSdk] is used.
|
| + *
|
| + * @coverage dart.engine
|
| + */
|
| +class DelegatingAnalysisContextImpl extends AnalysisContextImpl {
|
| +
|
| + /**
|
| + * This references the [InternalAnalysisContext] held onto by the [DartSdk] which is
|
| + * used (instead of this [AnalysisContext]) for SDK sources. This field is set when
|
| + * #setSourceFactory(SourceFactory) is called, and references the analysis context in the
|
| + * [DartUriResolver] in the [SourceFactory], this analysis context assumes that there
|
| + * will be such a resolver.
|
| + */
|
| + InternalAnalysisContext _sdkAnalysisContext;
|
| + void addSourceInfo(Source source, SourceEntry info) {
|
| + if (source.isInSystemLibrary) {
|
| + _sdkAnalysisContext.addSourceInfo(source, info);
|
| + } else {
|
| + super.addSourceInfo(source, info);
|
| + }
|
| + }
|
| + List<AnalysisError> computeErrors(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeErrors(source);
|
| + } else {
|
| + return super.computeErrors(source);
|
| + }
|
| + }
|
| + List<Source> computeExportedLibraries(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeExportedLibraries(source);
|
| + } else {
|
| + return super.computeExportedLibraries(source);
|
| + }
|
| + }
|
| + HtmlElement computeHtmlElement(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeHtmlElement(source);
|
| + } else {
|
| + return super.computeHtmlElement(source);
|
| + }
|
| + }
|
| + List<Source> computeImportedLibraries(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeImportedLibraries(source);
|
| + } else {
|
| + return super.computeImportedLibraries(source);
|
| + }
|
| + }
|
| + SourceKind computeKindOf(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeKindOf(source);
|
| + } else {
|
| + return super.computeKindOf(source);
|
| + }
|
| + }
|
| + LibraryElement computeLibraryElement(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeLibraryElement(source);
|
| + } else {
|
| + return super.computeLibraryElement(source);
|
| + }
|
| + }
|
| + LineInfo computeLineInfo(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeLineInfo(source);
|
| + } else {
|
| + return super.computeLineInfo(source);
|
| + }
|
| + }
|
| + ResolvableCompilationUnit computeResolvableCompilationUnit(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeResolvableCompilationUnit(source);
|
| + } else {
|
| + return super.computeResolvableCompilationUnit(source);
|
| + }
|
| + }
|
| + AnalysisErrorInfo getErrors(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getErrors(source);
|
| + } else {
|
| + return super.getErrors(source);
|
| + }
|
| + }
|
| + HtmlElement getHtmlElement(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getHtmlElement(source);
|
| + } else {
|
| + return super.getHtmlElement(source);
|
| + }
|
| + }
|
| + List<Source> getHtmlFilesReferencing(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getHtmlFilesReferencing(source);
|
| + } else {
|
| + return super.getHtmlFilesReferencing(source);
|
| + }
|
| + }
|
| + SourceKind getKindOf(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getKindOf(source);
|
| + } else {
|
| + return super.getKindOf(source);
|
| + }
|
| + }
|
| + List<Source> getLibrariesContaining(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getLibrariesContaining(source);
|
| + } else {
|
| + return super.getLibrariesContaining(source);
|
| + }
|
| + }
|
| + List<Source> getLibrariesDependingOn(Source librarySource) {
|
| + if (librarySource.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getLibrariesDependingOn(librarySource);
|
| + } else {
|
| + return super.getLibrariesDependingOn(librarySource);
|
| + }
|
| + }
|
| + LibraryElement getLibraryElement(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getLibraryElement(source);
|
| + } else {
|
| + return super.getLibraryElement(source);
|
| + }
|
| + }
|
| + List<Source> get librarySources => ArrayUtils.addAll(super.librarySources, _sdkAnalysisContext.librarySources);
|
| + LineInfo getLineInfo(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getLineInfo(source);
|
| + } else {
|
| + return super.getLineInfo(source);
|
| + }
|
| + }
|
| + Namespace getPublicNamespace(LibraryElement library) {
|
| + Source source = library.source;
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getPublicNamespace(library);
|
| + } else {
|
| + return super.getPublicNamespace(library);
|
| + }
|
| + }
|
| + Namespace getPublicNamespace2(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getPublicNamespace2(source);
|
| + } else {
|
| + return super.getPublicNamespace2(source);
|
| + }
|
| + }
|
| + CompilationUnit getResolvedCompilationUnit(Source unitSource, LibraryElement library) {
|
| + if (unitSource.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getResolvedCompilationUnit(unitSource, library);
|
| + } else {
|
| + return super.getResolvedCompilationUnit(unitSource, library);
|
| + }
|
| + }
|
| + CompilationUnit getResolvedCompilationUnit2(Source unitSource, Source librarySource) {
|
| + if (unitSource.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getResolvedCompilationUnit2(unitSource, librarySource);
|
| + } else {
|
| + return super.getResolvedCompilationUnit2(unitSource, librarySource);
|
| + }
|
| + }
|
| + bool isClientLibrary(Source librarySource) {
|
| + if (librarySource.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.isClientLibrary(librarySource);
|
| + } else {
|
| + return super.isClientLibrary(librarySource);
|
| + }
|
| + }
|
| + bool isServerLibrary(Source librarySource) {
|
| + if (librarySource.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.isServerLibrary(librarySource);
|
| + } else {
|
| + return super.isServerLibrary(librarySource);
|
| + }
|
| + }
|
| + CompilationUnit parseCompilationUnit(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.parseCompilationUnit(source);
|
| + } else {
|
| + return super.parseCompilationUnit(source);
|
| + }
|
| + }
|
| + HtmlUnit parseHtmlUnit(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.parseHtmlUnit(source);
|
| + } else {
|
| + return super.parseHtmlUnit(source);
|
| + }
|
| + }
|
| + void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
|
| + if (elementMap.isEmpty) {
|
| + return;
|
| + }
|
| + Source source = new JavaIterator(elementMap.keys.toSet()).next();
|
| + if (source.isInSystemLibrary) {
|
| + _sdkAnalysisContext.recordLibraryElements(elementMap);
|
| + } else {
|
| + super.recordLibraryElements(elementMap);
|
| + }
|
| + }
|
| + CompilationUnit resolveCompilationUnit(Source source, LibraryElement library) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.resolveCompilationUnit(source, library);
|
| + } else {
|
| + return super.resolveCompilationUnit(source, library);
|
| + }
|
| + }
|
| + CompilationUnit resolveCompilationUnit2(Source unitSource, Source librarySource) {
|
| + if (unitSource.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.resolveCompilationUnit2(unitSource, librarySource);
|
| + } else {
|
| + return super.resolveCompilationUnit2(unitSource, librarySource);
|
| + }
|
| + }
|
| + HtmlUnit resolveHtmlUnit(Source unitSource) {
|
| + if (unitSource.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.resolveHtmlUnit(unitSource);
|
| + } else {
|
| + return super.resolveHtmlUnit(unitSource);
|
| + }
|
| + }
|
| + void setContents(Source source, String contents) {
|
| + if (source.isInSystemLibrary) {
|
| + _sdkAnalysisContext.setContents(source, contents);
|
| + } else {
|
| + super.setContents(source, contents);
|
| + }
|
| + }
|
| + void set sourceFactory(SourceFactory factory) {
|
| + super.sourceFactory = factory;
|
| + DartSdk sdk = factory.dartSdk;
|
| + if (sdk != null) {
|
| + _sdkAnalysisContext = sdk.context as InternalAnalysisContext;
|
| + if (_sdkAnalysisContext is DelegatingAnalysisContextImpl) {
|
| + _sdkAnalysisContext = null;
|
| + throw new IllegalStateException("The context provided by an SDK cannot itself be a delegating analysis context");
|
| + }
|
| + } else {
|
| + throw new IllegalStateException("SourceFactorys provided to DelegatingAnalysisContextImpls must have a DartSdk associated with the provided SourceFactory.");
|
| + }
|
| + }
|
| +}
|
| +/**
|
| + * Instances of the class `DelegatingAnalysisContextImpl` extend [AnalysisContextImpl
|
| + ] to delegate sources to the appropriate analysis context. For instance, if the
|
| + * source is in a system library then the analysis context from the [DartSdk] is used.
|
| + *
|
| + * @coverage dart.engine
|
| + */
|
| +class DelegatingAnalysisContextImpl2 extends AnalysisContextImpl2 {
|
| +
|
| + /**
|
| + * This references the [InternalAnalysisContext] held onto by the [DartSdk] which is
|
| + * used (instead of this [AnalysisContext]) for SDK sources. This field is set when
|
| + * #setSourceFactory(SourceFactory) is called, and references the analysis context in the
|
| + * [DartUriResolver] in the [SourceFactory], this analysis context assumes that there
|
| + * will be such a resolver.
|
| + */
|
| + InternalAnalysisContext _sdkAnalysisContext;
|
| + void addSourceInfo(Source source, SourceEntry info) {
|
| + if (source.isInSystemLibrary) {
|
| + _sdkAnalysisContext.addSourceInfo(source, info);
|
| + } else {
|
| + super.addSourceInfo(source, info);
|
| + }
|
| + }
|
| + List<AnalysisError> computeErrors(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeErrors(source);
|
| + } else {
|
| + return super.computeErrors(source);
|
| + }
|
| + }
|
| + List<Source> computeExportedLibraries(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeExportedLibraries(source);
|
| + } else {
|
| + return super.computeExportedLibraries(source);
|
| + }
|
| + }
|
| + HtmlElement computeHtmlElement(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeHtmlElement(source);
|
| + } else {
|
| + return super.computeHtmlElement(source);
|
| + }
|
| + }
|
| + List<Source> computeImportedLibraries(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeImportedLibraries(source);
|
| + } else {
|
| + return super.computeImportedLibraries(source);
|
| + }
|
| + }
|
| + SourceKind computeKindOf(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeKindOf(source);
|
| + } else {
|
| + return super.computeKindOf(source);
|
| + }
|
| + }
|
| + LibraryElement computeLibraryElement(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeLibraryElement(source);
|
| + } else {
|
| + return super.computeLibraryElement(source);
|
| + }
|
| + }
|
| + LineInfo computeLineInfo(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeLineInfo(source);
|
| + } else {
|
| + return super.computeLineInfo(source);
|
| + }
|
| + }
|
| + ResolvableCompilationUnit computeResolvableCompilationUnit(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.computeResolvableCompilationUnit(source);
|
| + } else {
|
| + return super.computeResolvableCompilationUnit(source);
|
| + }
|
| + }
|
| + AnalysisErrorInfo getErrors(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getErrors(source);
|
| + } else {
|
| + return super.getErrors(source);
|
| + }
|
| + }
|
| + HtmlElement getHtmlElement(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getHtmlElement(source);
|
| + } else {
|
| + return super.getHtmlElement(source);
|
| + }
|
| + }
|
| + List<Source> getHtmlFilesReferencing(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getHtmlFilesReferencing(source);
|
| + } else {
|
| + return super.getHtmlFilesReferencing(source);
|
| + }
|
| + }
|
| + SourceKind getKindOf(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getKindOf(source);
|
| + } else {
|
| + return super.getKindOf(source);
|
| + }
|
| + }
|
| + List<Source> getLibrariesContaining(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getLibrariesContaining(source);
|
| + } else {
|
| + return super.getLibrariesContaining(source);
|
| + }
|
| + }
|
| + List<Source> getLibrariesDependingOn(Source librarySource) {
|
| + if (librarySource.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getLibrariesDependingOn(librarySource);
|
| + } else {
|
| + return super.getLibrariesDependingOn(librarySource);
|
| + }
|
| + }
|
| + LibraryElement getLibraryElement(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getLibraryElement(source);
|
| + } else {
|
| + return super.getLibraryElement(source);
|
| + }
|
| + }
|
| + List<Source> get librarySources => ArrayUtils.addAll(super.librarySources, _sdkAnalysisContext.librarySources);
|
| + LineInfo getLineInfo(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getLineInfo(source);
|
| + } else {
|
| + return super.getLineInfo(source);
|
| + }
|
| + }
|
| + Namespace getPublicNamespace(LibraryElement library) {
|
| + Source source = library.source;
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getPublicNamespace(library);
|
| + } else {
|
| + return super.getPublicNamespace(library);
|
| + }
|
| + }
|
| + Namespace getPublicNamespace2(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getPublicNamespace2(source);
|
| + } else {
|
| + return super.getPublicNamespace2(source);
|
| + }
|
| + }
|
| + CompilationUnit getResolvedCompilationUnit(Source unitSource, LibraryElement library) {
|
| + if (unitSource.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getResolvedCompilationUnit(unitSource, library);
|
| + } else {
|
| + return super.getResolvedCompilationUnit(unitSource, library);
|
| + }
|
| + }
|
| + CompilationUnit getResolvedCompilationUnit2(Source unitSource, Source librarySource) {
|
| + if (unitSource.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.getResolvedCompilationUnit2(unitSource, librarySource);
|
| + } else {
|
| + return super.getResolvedCompilationUnit2(unitSource, librarySource);
|
| + }
|
| + }
|
| + bool isClientLibrary(Source librarySource) {
|
| + if (librarySource.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.isClientLibrary(librarySource);
|
| + } else {
|
| + return super.isClientLibrary(librarySource);
|
| + }
|
| + }
|
| + bool isServerLibrary(Source librarySource) {
|
| + if (librarySource.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.isServerLibrary(librarySource);
|
| + } else {
|
| + return super.isServerLibrary(librarySource);
|
| + }
|
| + }
|
| + CompilationUnit parseCompilationUnit(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.parseCompilationUnit(source);
|
| + } else {
|
| + return super.parseCompilationUnit(source);
|
| + }
|
| + }
|
| + HtmlUnit parseHtmlUnit(Source source) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.parseHtmlUnit(source);
|
| + } else {
|
| + return super.parseHtmlUnit(source);
|
| + }
|
| + }
|
| + void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
|
| + if (elementMap.isEmpty) {
|
| + return;
|
| + }
|
| + Source source = new JavaIterator(elementMap.keys.toSet()).next();
|
| + if (source.isInSystemLibrary) {
|
| + _sdkAnalysisContext.recordLibraryElements(elementMap);
|
| + } else {
|
| + super.recordLibraryElements(elementMap);
|
| + }
|
| + }
|
| + CompilationUnit resolveCompilationUnit(Source source, LibraryElement library) {
|
| + if (source.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.resolveCompilationUnit(source, library);
|
| + } else {
|
| + return super.resolveCompilationUnit(source, library);
|
| + }
|
| + }
|
| + CompilationUnit resolveCompilationUnit2(Source unitSource, Source librarySource) {
|
| + if (unitSource.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.resolveCompilationUnit2(unitSource, librarySource);
|
| + } else {
|
| + return super.resolveCompilationUnit2(unitSource, librarySource);
|
| + }
|
| + }
|
| + HtmlUnit resolveHtmlUnit(Source unitSource) {
|
| + if (unitSource.isInSystemLibrary) {
|
| + return _sdkAnalysisContext.resolveHtmlUnit(unitSource);
|
| + } else {
|
| + return super.resolveHtmlUnit(unitSource);
|
| + }
|
| + }
|
| + void setContents(Source source, String contents) {
|
| + if (source.isInSystemLibrary) {
|
| + _sdkAnalysisContext.setContents(source, contents);
|
| + } else {
|
| + super.setContents(source, contents);
|
| + }
|
| + }
|
| + void set sourceFactory(SourceFactory factory) {
|
| + super.sourceFactory = factory;
|
| + DartSdk sdk = factory.dartSdk;
|
| + if (sdk != null) {
|
| + _sdkAnalysisContext = sdk.context as InternalAnalysisContext;
|
| + if (_sdkAnalysisContext is DelegatingAnalysisContextImpl2) {
|
| + _sdkAnalysisContext = null;
|
| + throw new IllegalStateException("The context provided by an SDK cannot itself be a delegating analysis context");
|
| + }
|
| + } else {
|
| + throw new IllegalStateException("SourceFactorys provided to DelegatingAnalysisContextImpls must have a DartSdk associated with the provided SourceFactory.");
|
| + }
|
| + }
|
| +}
|
| +/**
|
| + * Instances of the class `InstrumentedAnalysisContextImpl` implement an
|
| + * [AnalysisContext] by recording instrumentation data and delegating to
|
| + * another analysis context to do the non-instrumentation work.
|
| + *
|
| + * @coverage dart.engine
|
| + */
|
| +class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
|
| +
|
| + /**
|
| + * Record an exception that was thrown during analysis.
|
| + *
|
| + * @param instrumentation the instrumentation builder being used to record the exception
|
| + * @param exception the exception being reported
|
| + */
|
| + static void recordAnalysisException(InstrumentationBuilder instrumentation, AnalysisException exception) {
|
| + instrumentation.record(exception);
|
| + }
|
| +
|
| + /**
|
| + * The unique identifier used to identify this analysis context in the instrumentation data.
|
| + */
|
| + String _contextId = UUID.randomUUID().toString();
|
| +
|
| + /**
|
| + * The analysis context to which all of the non-instrumentation work is delegated.
|
| + */
|
| + InternalAnalysisContext _basis;
|
| +
|
| + /**
|
| + * Create a new [InstrumentedAnalysisContextImpl] which wraps a new
|
| + * [AnalysisContextImpl] as the basis context.
|
| + */
|
| + InstrumentedAnalysisContextImpl() : this.con1(AnalysisEngine.instance.useExperimentalContext ? new DelegatingAnalysisContextImpl2() : new DelegatingAnalysisContextImpl());
|
| +
|
| + /**
|
| + * Create a new [InstrumentedAnalysisContextImpl] with a specified basis context, aka the
|
| + * context to wrap and instrument.
|
| + *
|
| + * @param context some [InstrumentedAnalysisContext] to wrap and instrument
|
| + */
|
| + InstrumentedAnalysisContextImpl.con1(InternalAnalysisContext context) {
|
| + _basis = context;
|
| + }
|
| + void addSourceInfo(Source source, SourceEntry info) {
|
| + _basis.addSourceInfo(source, info);
|
| + }
|
| + void applyChanges(ChangeSet changeSet) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-applyChanges");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + _basis.applyChanges(changeSet);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + String computeDocumentationComment(Element element) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeDocumentationComment");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.computeDocumentationComment(element);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + List<AnalysisError> computeErrors(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeErrors");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + List<AnalysisError> errors = _basis.computeErrors(source);
|
| + instrumentation.metric2("Errors-count", errors.length);
|
| + return errors;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + List<Source> computeExportedLibraries(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeExportedLibraries");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.computeExportedLibraries(source);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + HtmlElement computeHtmlElement(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeHtmlElement");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.computeHtmlElement(source);
|
| + } on AnalysisException catch (e) {
|
| + recordAnalysisException(instrumentation, e);
|
| + throw e;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + List<Source> computeImportedLibraries(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeImportedLibraries");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.computeImportedLibraries(source);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + SourceKind computeKindOf(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeKindOf");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.computeKindOf(source);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + LibraryElement computeLibraryElement(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeLibraryElement");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.computeLibraryElement(source);
|
| + } on AnalysisException catch (e) {
|
| + recordAnalysisException(instrumentation, e);
|
| + throw e;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + LineInfo computeLineInfo(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeLineInfo");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.computeLineInfo(source);
|
| + } on AnalysisException catch (e) {
|
| + recordAnalysisException(instrumentation, e);
|
| + throw e;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + ResolvableCompilationUnit computeResolvableCompilationUnit(Source source) => _basis.computeResolvableCompilationUnit(source);
|
| + ResolvableHtmlUnit computeResolvableHtmlUnit(Source source) => _basis.computeResolvableHtmlUnit(source);
|
| + AnalysisContext extractContext(SourceContainer container) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-extractContext");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + InstrumentedAnalysisContextImpl newContext = new InstrumentedAnalysisContextImpl();
|
| + _basis.extractContextInto(container, newContext._basis);
|
| + return newContext;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + InternalAnalysisContext extractContextInto(SourceContainer container, InternalAnalysisContext newContext) => _basis.extractContextInto(container, newContext);
|
| + AnalysisOptions get analysisOptions {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getAnalysisOptions");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.analysisOptions;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @return the underlying [AnalysisContext].
|
| + */
|
| + AnalysisContext get basis => _basis;
|
| + Element getElement(ElementLocation location) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getElement");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.getElement(location);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + AnalysisErrorInfo getErrors(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getErrors");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + AnalysisErrorInfo ret = _basis.getErrors(source);
|
| + if (ret != null) {
|
| + instrumentation.metric2("Errors-count", ret.errors.length);
|
| + }
|
| + return ret;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + HtmlElement getHtmlElement(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getHtmlElement");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.getHtmlElement(source);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + List<Source> getHtmlFilesReferencing(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getHtmlFilesReferencing");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + List<Source> ret = _basis.getHtmlFilesReferencing(source);
|
| + if (ret != null) {
|
| + instrumentation.metric2("Source-count", ret.length);
|
| + }
|
| + return ret;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + List<Source> get htmlSources {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getHtmlSources");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + List<Source> ret = _basis.htmlSources;
|
| + if (ret != null) {
|
| + instrumentation.metric2("Source-count", ret.length);
|
| + }
|
| + return ret;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + SourceKind getKindOf(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getKindOf");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.getKindOf(source);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + List<Source> get launchableClientLibrarySources {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLaunchableClientLibrarySources");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + List<Source> ret = _basis.launchableClientLibrarySources;
|
| + if (ret != null) {
|
| + instrumentation.metric2("Source-count", ret.length);
|
| + }
|
| + return ret;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + List<Source> get launchableServerLibrarySources {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLaunchableServerLibrarySources");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + List<Source> ret = _basis.launchableServerLibrarySources;
|
| + if (ret != null) {
|
| + instrumentation.metric2("Source-count", ret.length);
|
| + }
|
| + return ret;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + List<Source> getLibrariesContaining(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLibrariesContaining");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + List<Source> ret = _basis.getLibrariesContaining(source);
|
| + if (ret != null) {
|
| + instrumentation.metric2("Source-count", ret.length);
|
| + }
|
| + return ret;
|
| + } finally {
|
| + instrumentation.log2(2);
|
| + }
|
| + }
|
| + List<Source> getLibrariesDependingOn(Source librarySource) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLibrariesDependingOn");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + List<Source> ret = _basis.getLibrariesDependingOn(librarySource);
|
| + if (ret != null) {
|
| + instrumentation.metric2("Source-count", ret.length);
|
| + }
|
| + return ret;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + LibraryElement getLibraryElement(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLibraryElement");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.getLibraryElement(source);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + List<Source> get librarySources {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLibrarySources");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + List<Source> ret = _basis.librarySources;
|
| + if (ret != null) {
|
| + instrumentation.metric2("Source-count", ret.length);
|
| + }
|
| + return ret;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + LineInfo getLineInfo(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLineInfo");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.getLineInfo(source);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + Namespace getPublicNamespace(LibraryElement library) => _basis.getPublicNamespace(library);
|
| + Namespace getPublicNamespace2(Source source) => _basis.getPublicNamespace2(source);
|
| + CompilationUnit getResolvedCompilationUnit(Source unitSource, LibraryElement library) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getResolvedCompilationUnit");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.getResolvedCompilationUnit(unitSource, library);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + CompilationUnit getResolvedCompilationUnit2(Source unitSource, Source librarySource) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getResolvedCompilationUnit");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.getResolvedCompilationUnit2(unitSource, librarySource);
|
| + } finally {
|
| + instrumentation.log2(2);
|
| + }
|
| + }
|
| + SourceFactory get sourceFactory {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getSourceFactory");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.sourceFactory;
|
| + } finally {
|
| + instrumentation.log2(2);
|
| + }
|
| + }
|
| + AnalysisContentStatistics get statistics => _basis.statistics;
|
| + bool isClientLibrary(Source librarySource) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-isClientLibrary");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.isClientLibrary(librarySource);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + bool isServerLibrary(Source librarySource) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-isServerLibrary");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.isServerLibrary(librarySource);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + void mergeContext(AnalysisContext context) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-mergeContext");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + if (context is InstrumentedAnalysisContextImpl) {
|
| + context = ((context as InstrumentedAnalysisContextImpl))._basis;
|
| + }
|
| + _basis.mergeContext(context);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + CompilationUnit parseCompilationUnit(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-parseCompilationUnit");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.parseCompilationUnit(source);
|
| + } on AnalysisException catch (e) {
|
| + recordAnalysisException(instrumentation, e);
|
| + throw e;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + HtmlUnit parseHtmlUnit(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-parseHtmlUnit");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.parseHtmlUnit(source);
|
| + } on AnalysisException catch (e) {
|
| + recordAnalysisException(instrumentation, e);
|
| + throw e;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + List<ChangeNotice> performAnalysisTask() {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-performAnalysisTask");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + List<ChangeNotice> ret = _basis.performAnalysisTask();
|
| + if (ret != null) {
|
| + instrumentation.metric2("ChangeNotice-count", ret.length);
|
| + }
|
| + return ret;
|
| + } finally {
|
| + instrumentation.log2(2);
|
| + }
|
| + }
|
| + void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
|
| + _basis.recordLibraryElements(elementMap);
|
| + }
|
| + CompilationUnit resolveCompilationUnit(Source unitSource, LibraryElement library) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-resolveCompilationUnit");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.resolveCompilationUnit(unitSource, library);
|
| + } on AnalysisException catch (e) {
|
| + recordAnalysisException(instrumentation, e);
|
| + throw e;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + CompilationUnit resolveCompilationUnit2(Source unitSource, Source librarySource) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-resolveCompilationUnit");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.resolveCompilationUnit2(unitSource, librarySource);
|
| + } on AnalysisException catch (e) {
|
| + recordAnalysisException(instrumentation, e);
|
| + throw e;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + HtmlUnit resolveHtmlUnit(Source htmlSource) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-resolveHtmlUnit");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.resolveHtmlUnit(htmlSource);
|
| + } on AnalysisException catch (e) {
|
| + recordAnalysisException(instrumentation, e);
|
| + throw e;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + void set analysisOptions(AnalysisOptions options) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-setAnalysisOptions");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + _basis.analysisOptions = options;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + void set analysisPriorityOrder(List<Source> sources) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-setAnalysisPriorityOrder");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + _basis.analysisPriorityOrder = sources;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + void setContents(Source source, String contents) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-setContents");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + _basis.setContents(source, contents);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + void set sourceFactory(SourceFactory factory) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-setSourceFactory");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + _basis.sourceFactory = factory;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| + Iterable<Source> sourcesToResolve(List<Source> changedSources) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-sourcesToResolve");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.sourcesToResolve(changedSources);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| +}
|
| +/**
|
| + * The interface `InternalAnalysisContext` defines additional behavior for an analysis context
|
| + * that is required by internal users of the context.
|
| + */
|
| +abstract class InternalAnalysisContext implements AnalysisContext {
|
| +
|
| + /**
|
| + * Add the given source with the given information to this context.
|
| + *
|
| + * @param source the source to be added
|
| + * @param info the information about the source
|
| + */
|
| + void addSourceInfo(Source source, SourceEntry info);
|
| +
|
| + /**
|
| + * Return an array containing the sources of the libraries that are exported by the library with
|
| + * the given source. The array will be empty if the given source is invalid, if the given source
|
| + * does not represent a library, or if the library does not export any other libraries.
|
| + *
|
| + * @param source the source representing the library whose exports are to be returned
|
| + * @return the sources of the libraries that are exported by the given library
|
| + * @throws AnalysisException if the exported libraries could not be computed
|
| + */
|
| + List<Source> computeExportedLibraries(Source source);
|
| +
|
| + /**
|
| + * Return an array containing the sources of the libraries that are imported by the library with
|
| + * the given source. The array will be empty if the given source is invalid, if the given source
|
| + * does not represent a library, or if the library does not import any other libraries.
|
| + *
|
| + * @param source the source representing the library whose imports are to be returned
|
| + * @return the sources of the libraries that are imported by the given library
|
| + * @throws AnalysisException if the imported libraries could not be computed
|
| + */
|
| + List<Source> computeImportedLibraries(Source source);
|
| +
|
| + /**
|
| + * Return an AST structure corresponding to the given source, but ensure that the structure has
|
| + * not already been resolved and will not be resolved by any other threads or in any other
|
| + * library.
|
| + *
|
| + * @param source the compilation unit for which an AST structure should be returned
|
| + * @return the AST structure representing the content of the source
|
| + * @throws AnalysisException if the analysis could not be performed
|
| + */
|
| + ResolvableCompilationUnit computeResolvableCompilationUnit(Source source);
|
| +
|
| + /**
|
| + * Return an AST structure corresponding to the given source, but ensure that the structure has
|
| + * not already been resolved and will not be resolved by any other threads.
|
| + *
|
| + * @param source the compilation unit for which an AST structure should be returned
|
| + * @return the AST structure representing the content of the source
|
| + * @throws AnalysisException if the analysis could not be performed
|
| + */
|
| + ResolvableHtmlUnit computeResolvableHtmlUnit(Source source);
|
| +
|
| + /**
|
| + * Initialize the specified context by removing the specified sources from the receiver and adding
|
| + * them to the specified context.
|
| + *
|
| + * @param container the container containing sources that should be removed from this context and
|
| + * added to the returned context
|
| + * @param newContext the context to be initialized
|
| + * @return the analysis context that was initialized
|
| + */
|
| + InternalAnalysisContext extractContextInto(SourceContainer container, InternalAnalysisContext newContext);
|
| +
|
| + /**
|
| + * Return a namespace containing mappings for all of the public names defined by the given
|
| + * library.
|
| + *
|
| + * @param library the library whose public namespace is to be returned
|
| + * @return the public namespace of the given library
|
| + */
|
| + Namespace getPublicNamespace(LibraryElement library);
|
| +
|
| + /**
|
| + * Return a namespace containing mappings for all of the public names defined by the library
|
| + * defined by the given source.
|
| + *
|
| + * @param source the source defining the library whose public namespace is to be returned
|
| + * @return the public namespace corresponding to the library defined by the given source
|
| + * @throws AnalysisException if the public namespace could not be computed
|
| + */
|
| + Namespace getPublicNamespace2(Source source);
|
| +
|
| + /**
|
| + * Returns a statistics about this context.
|
| + */
|
| + AnalysisContentStatistics get statistics;
|
| +
|
| + /**
|
| + * Given a table mapping the source for the libraries represented by the corresponding elements to
|
| + * the elements representing the libraries, record those mappings.
|
| + *
|
| + * @param elementMap a table mapping the source for the libraries represented by the elements to
|
| + * the elements representing the libraries
|
| + */
|
| + void recordLibraryElements(Map<Source, LibraryElement> elementMap);
|
| +}
|
| +/**
|
| + * Instances of the class `RecordingErrorListener` implement an error listener that will
|
| + * record the errors that are reported to it in a way that is appropriate for caching those errors
|
| + * within an analysis context.
|
| + *
|
| + * @coverage dart.engine
|
| + */
|
| +class RecordingErrorListener implements AnalysisErrorListener {
|
| +
|
| + /**
|
| + * A HashMap of lists containing the errors that were collected, keyed by each [Source].
|
| + */
|
| + Map<Source, List<AnalysisError>> _errors = new Map<Source, List<AnalysisError>>();
|
| +
|
| + /**
|
| + * Add all of the errors recorded by the given listener to this listener.
|
| + *
|
| + * @param listener the listener that has recorded the errors to be added
|
| + */
|
| + void addAll(RecordingErrorListener listener) {
|
| + for (AnalysisError error in listener.errors) {
|
| + onError(error);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Answer the errors collected by the listener.
|
| + *
|
| + * @return an array of errors (not `null`, contains no `null`s)
|
| + */
|
| + List<AnalysisError> get errors {
|
| + Iterable<MapEntry<Source, List<AnalysisError>>> entrySet = getMapEntrySet(_errors);
|
| + int numEntries = entrySet.length;
|
| + if (numEntries == 0) {
|
| + return AnalysisError.NO_ERRORS;
|
| + }
|
| + List<AnalysisError> resultList = new List<AnalysisError>();
|
| + for (MapEntry<Source, List<AnalysisError>> entry in entrySet) {
|
| + resultList.addAll(entry.getValue());
|
| + }
|
| + return new List.from(resultList);
|
| + }
|
| +
|
| + /**
|
| + * Answer the errors collected by the listener for some passed [Source].
|
| + *
|
| + * @param source some [Source] for which the caller wants the set of [AnalysisError]s
|
| + * collected by this listener
|
| + * @return the errors collected by the listener for the passed [Source]
|
| + */
|
| + List<AnalysisError> getErrors2(Source source) {
|
| + List<AnalysisError> errorsForSource = _errors[source];
|
| + if (errorsForSource == null) {
|
| + return AnalysisError.NO_ERRORS;
|
| + } else {
|
| + return new List.from(errorsForSource);
|
| + }
|
| + }
|
| + void onError(AnalysisError event) {
|
| + Source source = event.source;
|
| + List<AnalysisError> errorsForSource = _errors[source];
|
| + if (_errors[source] == null) {
|
| + errorsForSource = new List<AnalysisError>();
|
| + _errors[source] = errorsForSource;
|
| + }
|
| + errorsForSource.add(event);
|
| + }
|
| +}
|
| +/**
|
| + * Instances of the class `ResolutionEraser` remove any resolution information from an AST
|
| + * structure when used to visit that structure.
|
| + */
|
| +class ResolutionEraser extends GeneralizingASTVisitor<Object> {
|
| + Object visitAssignmentExpression(AssignmentExpression node) {
|
| + node.staticElement = null;
|
| + node.propagatedElement = null;
|
| + return super.visitAssignmentExpression(node);
|
| + }
|
| + Object visitBinaryExpression(BinaryExpression node) {
|
| + node.staticElement = null;
|
| + node.propagatedElement = null;
|
| + return super.visitBinaryExpression(node);
|
| + }
|
| + Object visitCompilationUnit(CompilationUnit node) {
|
| + node.element = null;
|
| + return super.visitCompilationUnit(node);
|
| + }
|
| + Object visitConstructorDeclaration(ConstructorDeclaration node) {
|
| + node.element = null;
|
| + return super.visitConstructorDeclaration(node);
|
| + }
|
| + Object visitConstructorName(ConstructorName node) {
|
| + node.staticElement = null;
|
| + node.element = null;
|
| + return super.visitConstructorName(node);
|
| + }
|
| + Object visitDirective(Directive node) {
|
| + node.element = null;
|
| + return super.visitDirective(node);
|
| + }
|
| + Object visitExpression(Expression node) {
|
| + node.staticType = null;
|
| + node.propagatedType = null;
|
| + return super.visitExpression(node);
|
| + }
|
| + Object visitFunctionExpression(FunctionExpression node) {
|
| + node.element = null;
|
| + return super.visitFunctionExpression(node);
|
| + }
|
| + Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
|
| + node.staticElement = null;
|
| + node.propagatedElement = null;
|
| + return super.visitFunctionExpressionInvocation(node);
|
| + }
|
| + Object visitIndexExpression(IndexExpression node) {
|
| + node.staticElement = null;
|
| + node.propagatedElement = null;
|
| + return super.visitIndexExpression(node);
|
| + }
|
| + Object visitInstanceCreationExpression(InstanceCreationExpression node) {
|
| + node.staticElement = null;
|
| + node.element = null;
|
| + return super.visitInstanceCreationExpression(node);
|
| + }
|
| + Object visitPostfixExpression(PostfixExpression node) {
|
| + node.staticElement = null;
|
| + node.propagatedElement = null;
|
| + return super.visitPostfixExpression(node);
|
| + }
|
| + Object visitPrefixExpression(PrefixExpression node) {
|
| + node.staticElement = null;
|
| + node.propagatedElement = null;
|
| + return super.visitPrefixExpression(node);
|
| + }
|
| + Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
|
| + node.staticElement = null;
|
| + node.element = null;
|
| + return super.visitRedirectingConstructorInvocation(node);
|
| + }
|
| + Object visitSimpleIdentifier(SimpleIdentifier node) {
|
| + node.staticElement = null;
|
| + node.propagatedElement = null;
|
| + return super.visitSimpleIdentifier(node);
|
| + }
|
| + Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
|
| + node.staticElement = null;
|
| + node.element = null;
|
| + return super.visitSuperConstructorInvocation(node);
|
| + }
|
| +}
|
| +/**
|
| + * Instances of the class `ResolvableCompilationUnit` represent a compilation unit that is not
|
| + * referenced by any other objects and for which we have modification stamp information. It is used
|
| + * by the [LibraryResolver] to resolve a library.
|
| + */
|
| +class ResolvableCompilationUnit {
|
| +
|
| + /**
|
| + * The modification time of the source from which the AST was created.
|
| + */
|
| + int _modificationTime = 0;
|
| +
|
| + /**
|
| + * The AST that was created from the source.
|
| + */
|
| + CompilationUnit _unit;
|
| +
|
| + /**
|
| + * Initialize a newly created holder to hold the given values.
|
| + *
|
| + * @param modificationTime the modification time of the source from which the AST was created
|
| + * @param unit the AST that was created from the source
|
| + */
|
| + ResolvableCompilationUnit(int modificationTime, CompilationUnit unit) {
|
| + this._modificationTime = modificationTime;
|
| + this._unit = unit;
|
| + }
|
| +
|
| + /**
|
| + * Return the AST that was created from the source.
|
| + *
|
| + * @return the AST that was created from the source
|
| + */
|
| + CompilationUnit get compilationUnit => _unit;
|
| +
|
| + /**
|
| + * Return the modification time of the source from which the AST was created.
|
| + *
|
| + * @return the modification time of the source from which the AST was created
|
| + */
|
| + int get modificationTime => _modificationTime;
|
| +}
|
| +/**
|
| + * Instances of the class `ResolvableHtmlUnit` represent an HTML unit that is not referenced
|
| + * by any other objects and for which we have modification stamp information. It is used by the
|
| + * [ResolveHtmlTask] to resolve an HTML source.
|
| + */
|
| +class ResolvableHtmlUnit {
|
| +
|
| + /**
|
| + * The modification time of the source from which the AST was created.
|
| + */
|
| + int _modificationTime = 0;
|
| +
|
| + /**
|
| + * The AST that was created from the source.
|
| + */
|
| + HtmlUnit _unit;
|
| +
|
| + /**
|
| + * Initialize a newly created holder to hold the given values.
|
| + *
|
| + * @param modificationTime the modification time of the source from which the AST was created
|
| + * @param unit the AST that was created from the source
|
| + */
|
| + ResolvableHtmlUnit(int modificationTime, HtmlUnit unit) {
|
| + this._modificationTime = modificationTime;
|
| + this._unit = unit;
|
| + }
|
| +
|
| + /**
|
| + * Return the AST that was created from the source.
|
| + *
|
| + * @return the AST that was created from the source
|
| + */
|
| + HtmlUnit get compilationUnit => _unit;
|
| +
|
| + /**
|
| + * Return the modification time of the source from which the AST was created.
|
| + *
|
| + * @return the modification time of the source from which the AST was created
|
| + */
|
| + int get modificationTime => _modificationTime;
|
| +}
|
| +/**
|
| + * The abstract class `AnalysisTask` defines the behavior of objects used to perform an
|
| + * analysis task.
|
| + */
|
| +abstract class AnalysisTask {
|
| +
|
| + /**
|
| + * The context in which the task is to be performed.
|
| + */
|
| + InternalAnalysisContext _context;
|
| +
|
| + /**
|
| + * The exception that was thrown while performing this task, or `null` if the task completed
|
| + * successfully.
|
| + */
|
| + AnalysisException _thrownException;
|
| +
|
| + /**
|
| + * Initialize a newly created task to perform analysis within the given context.
|
| + *
|
| + * @param context the context in which the task is to be performed
|
| + */
|
| + AnalysisTask(InternalAnalysisContext context) {
|
| + this._context = context;
|
| + }
|
| +
|
| + /**
|
| + * Use the given visitor to visit this task.
|
| + *
|
| + * @param visitor the visitor that should be used to visit this task
|
| + * @return the value returned by the visitor
|
| + * @throws AnalysisException if the visitor throws the exception
|
| + */
|
| + accept(AnalysisTaskVisitor visitor);
|
| +
|
| + /**
|
| + * Return the exception that was thrown while performing this task, or `null` if the task
|
| + * completed successfully.
|
| + *
|
| + * @return the exception that was thrown while performing this task
|
| + */
|
| + AnalysisException get exception => _thrownException;
|
| +
|
| + /**
|
| + * Perform this analysis task and use the given visitor to visit this task after it has completed.
|
| + *
|
| + * @param visitor the visitor used to visit this task after it has completed
|
| + * @return the value returned by the visitor
|
| + * @throws AnalysisException if the visitor throws the exception
|
| + */
|
| + Object perform(AnalysisTaskVisitor visitor) {
|
| + try {
|
| + safelyPerform();
|
| + } on AnalysisException catch (exception) {
|
| + _thrownException = exception;
|
| + AnalysisEngine.instance.logger.logInformation2("Task failed: ${taskDescription}", exception);
|
| + }
|
| + return accept(visitor);
|
| + }
|
| + String toString() => taskDescription;
|
| +
|
| + /**
|
| + * Return the context in which the task is to be performed.
|
| + *
|
| + * @return the context in which the task is to be performed
|
| + */
|
| + InternalAnalysisContext get context => _context;
|
| +
|
| + /**
|
| + * Return a textual description of this task.
|
| + *
|
| + * @return a textual description of this task
|
| + */
|
| + String get taskDescription;
|
| +
|
| + /**
|
| + * Perform this analysis task, protected by an exception handler.
|
| + *
|
| + * @throws AnalysisException if an exception occurs while performing the task
|
| + */
|
| + void internalPerform();
|
| +
|
| + /**
|
| + * Perform this analysis task, ensuring that all exceptions are wrapped in an
|
| + * [AnalysisException].
|
| + *
|
| + * @throws AnalysisException if any exception occurs while performing the task
|
| + */
|
| + void safelyPerform() {
|
| + try {
|
| + internalPerform();
|
| + } on AnalysisException catch (exception) {
|
| + throw exception;
|
| + } catch (exception) {
|
| + throw new AnalysisException.con3(exception);
|
| + }
|
| + }
|
| +}
|
| +/**
|
| + * The interface `AnalysisTaskVisitor` defines the behavior of objects that can visit tasks.
|
| + * While tasks are not structured in any interesting way, this class provides the ability to
|
| + * dispatch to an appropriate method.
|
| + */
|
| +abstract class AnalysisTaskVisitor<E> {
|
| +
|
| + /**
|
| + * Visit a [ParseDartTask].
|
| + *
|
| + * @param task the task to be visited
|
| + * @return the result of visiting the task
|
| + * @throws AnalysisException if the visitor throws an exception for some reason
|
| + */
|
| + E visitParseDartTask(ParseDartTask task);
|
| +
|
| + /**
|
| + * Visit a [ParseHtmlTask].
|
| + *
|
| + * @param task the task to be visited
|
| + * @return the result of visiting the task
|
| + * @throws AnalysisException if the visitor throws an exception for some reason
|
| + */
|
| + E visitParseHtmlTask(ParseHtmlTask task);
|
| +
|
| + /**
|
| + * Visit a [ResolveDartLibraryTask].
|
| + *
|
| + * @param task the task to be visited
|
| + * @return the result of visiting the task
|
| + * @throws AnalysisException if the visitor throws an exception for some reason
|
| + */
|
| + E visitResolveDartLibraryTask(ResolveDartLibraryTask task);
|
| +
|
| + /**
|
| + * Visit a [ResolveDartUnitTask].
|
| + *
|
| + * @param task the task to be visited
|
| + * @return the result of visiting the task
|
| + * @throws AnalysisException if the visitor throws an exception for some reason
|
| + */
|
| + E visitResolveDartUnitTask(ResolveDartUnitTask task);
|
| +
|
| + /**
|
| + * Visit a [ResolveHtmlTask].
|
| + *
|
| + * @param task the task to be visited
|
| + * @return the result of visiting the task
|
| + * @throws AnalysisException if the visitor throws an exception for some reason
|
| + */
|
| + E visitResolveHtmlTask(ResolveHtmlTask task);
|
| +}
|
| +/**
|
| + * Instances of the class `ParseDartTask` parse a specific source as a Dart file.
|
| + */
|
| +class ParseDartTask extends AnalysisTask {
|
| +
|
| + /**
|
| + * The source to be parsed.
|
| + */
|
| + Source _source;
|
| +
|
| + /**
|
| + * The time at which the contents of the source were last modified.
|
| + */
|
| + int _modificationTime = -1;
|
| +
|
| + /**
|
| + * The line information that was produced.
|
| + */
|
| + LineInfo _lineInfo;
|
| +
|
| + /**
|
| + * The compilation unit that was produced by parsing the source.
|
| + */
|
| + CompilationUnit _unit;
|
| +
|
| + /**
|
| + * The errors that were produced by scanning and parsing the source.
|
| + */
|
| + List<AnalysisError> _errors = AnalysisError.NO_ERRORS;
|
| +
|
| + /**
|
| + * A flag indicating whether the source contains a 'part of' directive.
|
| + */
|
| + bool _hasPartOfDirective2 = false;
|
| +
|
| + /**
|
| + * A flag indicating whether the source contains a 'library' directive.
|
| + */
|
| + bool _hasLibraryDirective2 = false;
|
| +
|
| + /**
|
| + * A set containing the sources referenced by 'export' directives.
|
| + */
|
| + Set<Source> _exportedSources = new Set<Source>();
|
| +
|
| + /**
|
| + * A set containing the sources referenced by 'import' directives.
|
| + */
|
| + Set<Source> _importedSources = new Set<Source>();
|
| +
|
| + /**
|
| + * A set containing the sources referenced by 'part' directives.
|
| + */
|
| + Set<Source> _includedSources = new Set<Source>();
|
| +
|
| + /**
|
| + * Initialize a newly created task to perform analysis within the given context.
|
| + *
|
| + * @param context the context in which the task is to be performed
|
| + * @param source the source to be parsed
|
| + */
|
| + ParseDartTask(InternalAnalysisContext context, Source source) : super(context) {
|
| + this._source = source;
|
| + }
|
| + accept(AnalysisTaskVisitor visitor) => visitor.visitParseDartTask(this);
|
| +
|
| + /**
|
| + * Return the compilation unit that was produced by parsing the source, or `null` if the
|
| + * task has not yet been performed or if an exception occurred.
|
| + *
|
| + * @return the compilation unit that was produced by parsing the source
|
| + */
|
| + CompilationUnit get compilationUnit => _unit;
|
| +
|
| + /**
|
| + * Return the errors that were produced by scanning and parsing the source, or `null` if the
|
| + * task has not yet been performed or if an exception occurred.
|
| + *
|
| + * @return the errors that were produced by scanning and parsing the source
|
| + */
|
| + List<AnalysisError> get errors => _errors;
|
| +
|
| + /**
|
| + * Return an array containing the sources referenced by 'export' directives, or an empty array if
|
| + * the task has not yet been performed or if an exception occurred.
|
| + *
|
| + * @return an array containing the sources referenced by 'export' directives
|
| + */
|
| + List<Source> get exportedSources => toArray(_exportedSources);
|
| +
|
| + /**
|
| + * Return an array containing the sources referenced by 'import' directives, or an empty array if
|
| + * the task has not yet been performed or if an exception occurred.
|
| + *
|
| + * @return an array containing the sources referenced by 'import' directives
|
| + */
|
| + List<Source> get importedSources => toArray(_importedSources);
|
| +
|
| + /**
|
| + * Return an array containing the sources referenced by 'part' directives, or an empty array if
|
| + * the task has not yet been performed or if an exception occurred.
|
| + *
|
| + * @return an array containing the sources referenced by 'part' directives
|
| + */
|
| + List<Source> get includedSources => toArray(_includedSources);
|
| +
|
| + /**
|
| + * Return the line information that was produced, or `null` if the task has not yet been
|
| + * performed or if an exception occurred.
|
| + *
|
| + * @return the line information that was produced
|
| + */
|
| + LineInfo get lineInfo => _lineInfo;
|
| +
|
| + /**
|
| + * Return the time at which the contents of the source that was parsed were last modified, or a
|
| + * negative value if the task has not yet been performed or if an exception occurred.
|
| + *
|
| + * @return the time at which the contents of the source that was parsed were last modified
|
| + */
|
| + int get modificationTime => _modificationTime;
|
| +
|
| + /**
|
| + * Return the source that is to be parsed.
|
| + *
|
| + * @return the source to be parsed
|
| + */
|
| + Source get source => _source;
|
| +
|
| + /**
|
| + * Return `true` if the source contains a 'library' directive, or `false` if the task
|
| + * has not yet been performed or if an exception occurred.
|
| + *
|
| + * @return `true` if the source contains a 'library' directive
|
| + */
|
| + bool hasLibraryDirective() => _hasLibraryDirective2;
|
| +
|
| + /**
|
| + * Return `true` if the source contains a 'part of' directive, or `false` if the task
|
| + * has not yet been performed or if an exception occurred.
|
| + *
|
| + * @return `true` if the source contains a 'part of' directive
|
| + */
|
| + bool hasPartOfDirective() => _hasPartOfDirective2;
|
| + String get taskDescription => "parse as dart ${_source.fullName}";
|
| + void internalPerform() {
|
| + RecordingErrorListener errorListener = new RecordingErrorListener();
|
| + List<Token> token = [null];
|
| + Source_ContentReceiver receiver = new Source_ContentReceiver_10(this, errorListener, token);
|
| try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.parseHtmlUnit(source);
|
| - } on AnalysisException catch (e) {
|
| - recordAnalysisException(instrumentation, e);
|
| - throw e;
|
| - } finally {
|
| - instrumentation.log();
|
| + _source.getContents(receiver);
|
| + } catch (exception) {
|
| + _modificationTime = _source.modificationStamp;
|
| + throw new AnalysisException.con3(exception);
|
| }
|
| - }
|
| - List<ChangeNotice> performAnalysisTask() {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-performAnalysisTask");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - List<ChangeNotice> ret = _basis.performAnalysisTask();
|
| - if (ret != null) {
|
| - instrumentation.metric2("ChangeNotice-count", ret.length);
|
| + Parser parser = new Parser(_source, errorListener);
|
| + _unit = parser.parseCompilationUnit(token[0]);
|
| + _errors = errorListener.getErrors2(_source);
|
| + for (Directive directive in _unit.directives) {
|
| + if (directive is ExportDirective) {
|
| + Source exportSource = resolveSource(_source, directive as ExportDirective);
|
| + if (exportSource != null) {
|
| + javaSetAdd(_exportedSources, exportSource);
|
| + }
|
| + } else if (directive is ImportDirective) {
|
| + Source importSource = resolveSource(_source, directive as ImportDirective);
|
| + if (importSource != null) {
|
| + javaSetAdd(_importedSources, importSource);
|
| + }
|
| + } else if (directive is LibraryDirective) {
|
| + _hasLibraryDirective2 = true;
|
| + } else if (directive is PartDirective) {
|
| + Source partSource = resolveSource(_source, directive as PartDirective);
|
| + if (partSource != null) {
|
| + javaSetAdd(_includedSources, partSource);
|
| + }
|
| + } else if (directive is PartOfDirective) {
|
| + _hasPartOfDirective2 = true;
|
| }
|
| - return ret;
|
| - } finally {
|
| - instrumentation.log2(2);
|
| }
|
| + _unit.parsingErrors = _errors;
|
| + _unit.lineInfo = _lineInfo;
|
| }
|
| - void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
|
| - _basis.recordLibraryElements(elementMap);
|
| - }
|
| - CompilationUnit resolveCompilationUnit(Source unitSource, LibraryElement library) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-resolveCompilationUnit");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.resolveCompilationUnit(unitSource, library);
|
| - } on AnalysisException catch (e) {
|
| - recordAnalysisException(instrumentation, e);
|
| - throw e;
|
| - } finally {
|
| - instrumentation.log();
|
| +
|
| + /**
|
| + * Return the result of resolving the URI of the given URI-based directive against the URI of the
|
| + * given library, or `null` if the URI is not valid.
|
| + *
|
| + * @param librarySource the source representing the library containing the directive
|
| + * @param directive the directive which URI should be resolved
|
| + * @return the result of resolving the URI against the URI of the library
|
| + */
|
| + Source resolveSource(Source librarySource, UriBasedDirective directive) {
|
| + StringLiteral uriLiteral = directive.uri;
|
| + if (uriLiteral is StringInterpolation) {
|
| + return null;
|
| }
|
| - }
|
| - CompilationUnit resolveCompilationUnit2(Source unitSource, Source librarySource) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-resolveCompilationUnit");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.resolveCompilationUnit2(unitSource, librarySource);
|
| - } on AnalysisException catch (e) {
|
| - recordAnalysisException(instrumentation, e);
|
| - throw e;
|
| - } finally {
|
| - instrumentation.log();
|
| + String uriContent = uriLiteral.stringValue.trim();
|
| + if (uriContent == null) {
|
| + return null;
|
| }
|
| - }
|
| - HtmlUnit resolveHtmlUnit(Source htmlSource) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-resolveHtmlUnit");
|
| + uriContent = Uri.encodeFull(uriContent);
|
| try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.resolveHtmlUnit(htmlSource);
|
| - } on AnalysisException catch (e) {
|
| - recordAnalysisException(instrumentation, e);
|
| - throw e;
|
| - } finally {
|
| - instrumentation.log();
|
| + parseUriWithException(uriContent);
|
| + return context.sourceFactory.resolveUri(librarySource, uriContent);
|
| + } on URISyntaxException catch (exception) {
|
| + return null;
|
| }
|
| }
|
| - void set analysisOptions(AnalysisOptions options) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-setAnalysisOptions");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - _basis.analysisOptions = options;
|
| - } finally {
|
| - instrumentation.log();
|
| +
|
| + /**
|
| + * Efficiently convert the given set of sources to an array.
|
| + *
|
| + * @param sources the set to be converted
|
| + * @return an array containing all of the sources in the given set
|
| + */
|
| + List<Source> toArray(Set<Source> sources) {
|
| + int size = sources.length;
|
| + if (size == 0) {
|
| + return Source.EMPTY_ARRAY;
|
| }
|
| + return new List.from(sources);
|
| }
|
| - void set analysisPriorityOrder(List<Source> sources) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-setAnalysisPriorityOrder");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - _basis.analysisPriorityOrder = sources;
|
| - } finally {
|
| - instrumentation.log();
|
| - }
|
| +}
|
| +class Source_ContentReceiver_10 implements Source_ContentReceiver {
|
| + final ParseDartTask ParseDartTask_this;
|
| + RecordingErrorListener errorListener;
|
| + List<Token> token;
|
| + Source_ContentReceiver_10(this.ParseDartTask_this, this.errorListener, this.token);
|
| + void accept(CharBuffer contents, int modificationTime2) {
|
| + ParseDartTask_this._modificationTime = modificationTime2;
|
| + CharBufferScanner scanner = new CharBufferScanner(ParseDartTask_this._source, contents, errorListener);
|
| + token[0] = scanner.tokenize();
|
| + ParseDartTask_this._lineInfo = new LineInfo(scanner.lineStarts);
|
| }
|
| - void setContents(Source source, String contents) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-setContents");
|
| + void accept2(String contents, int modificationTime2) {
|
| + ParseDartTask_this._modificationTime = modificationTime2;
|
| + StringScanner scanner = new StringScanner(ParseDartTask_this._source, contents, errorListener);
|
| + token[0] = scanner.tokenize();
|
| + ParseDartTask_this._lineInfo = new LineInfo(scanner.lineStarts);
|
| + }
|
| +}
|
| +/**
|
| + * Instances of the class `ParseHtmlTask` parse a specific source as an HTML file.
|
| + */
|
| +class ParseHtmlTask extends AnalysisTask {
|
| +
|
| + /**
|
| + * The source to be parsed.
|
| + */
|
| + Source _source;
|
| +
|
| + /**
|
| + * The time at which the contents of the source were last modified.
|
| + */
|
| + int _modificationTime = -1;
|
| +
|
| + /**
|
| + * The line information that was produced.
|
| + */
|
| + LineInfo _lineInfo;
|
| +
|
| + /**
|
| + * The HTML unit that was produced by parsing the source.
|
| + */
|
| + HtmlUnit _unit;
|
| +
|
| + /**
|
| + * An array containing the sources of the libraries that are referenced within the HTML.
|
| + */
|
| + List<Source> _referencedLibraries = Source.EMPTY_ARRAY;
|
| +
|
| + /**
|
| + * The name of the 'src' attribute in a HTML tag.
|
| + */
|
| + static String _ATTRIBUTE_SRC = "src";
|
| +
|
| + /**
|
| + * The name of the 'type' attribute in a HTML tag.
|
| + */
|
| + static String _ATTRIBUTE_TYPE = "type";
|
| +
|
| + /**
|
| + * The name of the 'script' tag in an HTML file.
|
| + */
|
| + static String _TAG_SCRIPT = "script";
|
| +
|
| + /**
|
| + * The value of the 'type' attribute of a 'script' tag that indicates that the script is written
|
| + * in Dart.
|
| + */
|
| + static String _TYPE_DART = "application/dart";
|
| +
|
| + /**
|
| + * Initialize a newly created task to perform analysis within the given context.
|
| + *
|
| + * @param context the context in which the task is to be performed
|
| + * @param source the source to be parsed
|
| + */
|
| + ParseHtmlTask(InternalAnalysisContext context, Source source) : super(context) {
|
| + this._source = source;
|
| + }
|
| + accept(AnalysisTaskVisitor visitor) => visitor.visitParseHtmlTask(this);
|
| +
|
| + /**
|
| + * Return the HTML unit that was produced by parsing the source.
|
| + *
|
| + * @return the HTML unit that was produced by parsing the source
|
| + */
|
| + HtmlUnit get htmlUnit => _unit;
|
| +
|
| + /**
|
| + * Return the line information that was produced, or `null` if the task has not yet been
|
| + * performed or if an exception occurred.
|
| + *
|
| + * @return the line information that was produced
|
| + */
|
| + LineInfo get lineInfo => _lineInfo;
|
| +
|
| + /**
|
| + * Return the time at which the contents of the source that was parsed were last modified, or a
|
| + * negative value if the task has not yet been performed or if an exception occurred.
|
| + *
|
| + * @return the time at which the contents of the source that was parsed were last modified
|
| + */
|
| + int get modificationTime => _modificationTime;
|
| +
|
| + /**
|
| + * Return an array containing the sources of the libraries that are referenced within the HTML.
|
| + *
|
| + * @return the sources of the libraries that are referenced within the HTML
|
| + */
|
| + List<Source> get referencedLibraries => _referencedLibraries;
|
| +
|
| + /**
|
| + * Return the source that was or is to be parsed.
|
| + *
|
| + * @return the source was or is to be parsed
|
| + */
|
| + Source get source => _source;
|
| + String get taskDescription => "parse as html ${_source.fullName}";
|
| + void internalPerform() {
|
| + HtmlScanner scanner = new HtmlScanner(_source);
|
| try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - _basis.setContents(source, contents);
|
| - } finally {
|
| - instrumentation.log();
|
| + _source.getContents(scanner);
|
| + } catch (exception) {
|
| + throw new AnalysisException.con3(exception);
|
| }
|
| + HtmlScanResult scannerResult = scanner.result;
|
| + _modificationTime = scannerResult.modificationTime;
|
| + _lineInfo = new LineInfo(scannerResult.lineStarts);
|
| + HtmlParseResult result = new HtmlParser(_source).parse(scannerResult);
|
| + _unit = result.htmlUnit;
|
| + _referencedLibraries = librarySources;
|
| }
|
| - void set sourceFactory(SourceFactory factory) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-setSourceFactory");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - _basis.sourceFactory = factory;
|
| - } finally {
|
| - instrumentation.log();
|
| +
|
| + /**
|
| + * Return the sources of libraries that are referenced in the specified HTML file.
|
| + *
|
| + * @return the sources of libraries that are referenced in the HTML file
|
| + */
|
| + List<Source> get librarySources {
|
| + List<Source> libraries = new List<Source>();
|
| + _unit.accept(new RecursiveXmlVisitor_11(this, libraries));
|
| + if (libraries.isEmpty) {
|
| + return Source.EMPTY_ARRAY;
|
| }
|
| + return new List.from(libraries);
|
| }
|
| - Iterable<Source> sourcesToResolve(List<Source> changedSources) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-sourcesToResolve");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.sourcesToResolve(changedSources);
|
| - } finally {
|
| - instrumentation.log();
|
| +}
|
| +class RecursiveXmlVisitor_11 extends RecursiveXmlVisitor<Object> {
|
| + final ParseHtmlTask ParseHtmlTask_this;
|
| + List<Source> libraries;
|
| + RecursiveXmlVisitor_11(this.ParseHtmlTask_this, this.libraries) : super();
|
| + Object visitXmlTagNode(XmlTagNode node) {
|
| + if (javaStringEqualsIgnoreCase(node.tag.lexeme, ParseHtmlTask._TAG_SCRIPT)) {
|
| + bool isDartScript = false;
|
| + XmlAttributeNode scriptAttribute = null;
|
| + for (XmlAttributeNode attribute in node.attributes) {
|
| + if (javaStringEqualsIgnoreCase(attribute.name.lexeme, ParseHtmlTask._ATTRIBUTE_SRC)) {
|
| + scriptAttribute = attribute;
|
| + } else if (javaStringEqualsIgnoreCase(attribute.name.lexeme, ParseHtmlTask._ATTRIBUTE_TYPE)) {
|
| + if (javaStringEqualsIgnoreCase(attribute.text, ParseHtmlTask._TYPE_DART)) {
|
| + isDartScript = true;
|
| + }
|
| + }
|
| + }
|
| + if (isDartScript && scriptAttribute != null) {
|
| + try {
|
| + Uri uri = new Uri(path: scriptAttribute.text);
|
| + String fileName = uri.path;
|
| + Source librarySource = ParseHtmlTask_this.context.sourceFactory.resolveUri(ParseHtmlTask_this._source, fileName);
|
| + if (librarySource.exists()) {
|
| + libraries.add(librarySource);
|
| + }
|
| + } catch (exception) {
|
| + AnalysisEngine.instance.logger.logInformation2("Invalid URL ('${scriptAttribute.text}') in script tag in '${ParseHtmlTask_this._source.fullName}'", exception);
|
| + }
|
| + }
|
| }
|
| + return super.visitXmlTagNode(node);
|
| }
|
| }
|
| /**
|
| - * The interface `InternalAnalysisContext` defines additional behavior for an analysis context
|
| - * that is required by internal users of the context.
|
| + * Instances of the class `ResolveDartLibraryTask` parse a specific Dart library.
|
| */
|
| -abstract class InternalAnalysisContext implements AnalysisContext {
|
| +class ResolveDartLibraryTask extends AnalysisTask {
|
| +
|
| + /**
|
| + * The source representing the file whose compilation unit is to be returned.
|
| + */
|
| + Source _unitSource;
|
| +
|
| + /**
|
| + * The source representing the library to be resolved.
|
| + */
|
| + Source _librarySource;
|
|
|
| /**
|
| - * Add the given source with the given information to this context.
|
| - *
|
| - * @param source the source to be added
|
| - * @param info the information about the source
|
| + * The library resolver holding information about the libraries that were resolved.
|
| */
|
| - void addSourceInfo(Source source, SourceEntry info);
|
| + LibraryResolver _resolver;
|
|
|
| /**
|
| - * Return an array containing the sources of the libraries that are exported by the library with
|
| - * the given source. The array will be empty if the given source is invalid, if the given source
|
| - * does not represent a library, or if the library does not export any other libraries.
|
| + * Initialize a newly created task to perform analysis within the given context.
|
| *
|
| - * @param source the source representing the library whose exports are to be returned
|
| - * @return the sources of the libraries that are exported by the given library
|
| - * @throws AnalysisException if the exported libraries could not be computed
|
| + * @param context the context in which the task is to be performed
|
| + * @param unitSource the source representing the file whose compilation unit is to be returned
|
| + * @param librarySource the source representing the library to be resolved
|
| */
|
| - List<Source> computeExportedLibraries(Source source);
|
| + ResolveDartLibraryTask(InternalAnalysisContext context, Source unitSource, Source librarySource) : super(context) {
|
| + this._unitSource = unitSource;
|
| + this._librarySource = librarySource;
|
| + }
|
| + accept(AnalysisTaskVisitor visitor) => visitor.visitResolveDartLibraryTask(this);
|
|
|
| /**
|
| - * Return an array containing the sources of the libraries that are imported by the library with
|
| - * the given source. The array will be empty if the given source is invalid, if the given source
|
| - * does not represent a library, or if the library does not import any other libraries.
|
| + * Return the library resolver holding information about the libraries that were resolved.
|
| *
|
| - * @param source the source representing the library whose imports are to be returned
|
| - * @return the sources of the libraries that are imported by the given library
|
| - * @throws AnalysisException if the imported libraries could not be computed
|
| + * @return the library resolver holding information about the libraries that were resolved
|
| */
|
| - List<Source> computeImportedLibraries(Source source);
|
| + LibraryResolver get libraryResolver => _resolver;
|
|
|
| /**
|
| - * Return an AST structure corresponding to the given source, but ensure that the structure has
|
| - * not already been resolved and will not be resolved by any other threads or in any other
|
| - * library.
|
| + * Return the source representing the library to be resolved.
|
| *
|
| - * @param source the compilation unit for which an AST structure should be returned
|
| - * @return the AST structure representing the content of the source
|
| - * @throws AnalysisException if the analysis could not be performed
|
| + * @return the source representing the library to be resolved
|
| */
|
| - ResolvableCompilationUnit computeResolvableCompilationUnit(Source source);
|
| + Source get librarySource => _librarySource;
|
|
|
| /**
|
| - * Initialize the specified context by removing the specified sources from the receiver and adding
|
| - * them to the specified context.
|
| + * Return the source representing the file whose compilation unit is to be returned.
|
| *
|
| - * @param container the container containing sources that should be removed from this context and
|
| - * added to the returned context
|
| - * @param newContext the context to be initialized
|
| - * @return the analysis context that was initialized
|
| + * @return the source representing the file whose compilation unit is to be returned
|
| */
|
| - InternalAnalysisContext extractContextInto(SourceContainer container, InternalAnalysisContext newContext);
|
| + Source get unitSource => _unitSource;
|
| + String get taskDescription => "resolve library ${_librarySource.fullName}";
|
| + void internalPerform() {
|
| + _resolver = new LibraryResolver(context);
|
| + _resolver.resolveLibrary(_librarySource, true);
|
| + }
|
| +}
|
| +/**
|
| + * Instances of the class `ResolveDartUnitTask` resolve a single Dart file based on a existing
|
| + * element model.
|
| + */
|
| +class ResolveDartUnitTask extends AnalysisTask {
|
|
|
| /**
|
| - * Return a namespace containing mappings for all of the public names defined by the given
|
| - * library.
|
| - *
|
| - * @param library the library whose public namespace is to be returned
|
| - * @return the public namespace of the given library
|
| + * The source that is to be resolved.
|
| */
|
| - Namespace getPublicNamespace(LibraryElement library);
|
| + Source _source;
|
|
|
| /**
|
| - * Return a namespace containing mappings for all of the public names defined by the library
|
| - * defined by the given source.
|
| - *
|
| - * @param source the source defining the library whose public namespace is to be returned
|
| - * @return the public namespace corresponding to the library defined by the given source
|
| - * @throws AnalysisException if the public namespace could not be computed
|
| + * The element model for the library containing the source.
|
| */
|
| - Namespace getPublicNamespace2(Source source);
|
| + LibraryElement _libraryElement;
|
|
|
| /**
|
| - * Returns a statistics about this context.
|
| + * The time at which the contents of the source were last modified.
|
| */
|
| - AnalysisContentStatistics get statistics;
|
| + int _modificationTime = -1;
|
|
|
| /**
|
| - * Given a table mapping the source for the libraries represented by the corresponding elements to
|
| - * the elements representing the libraries, record those mappings.
|
| + * The compilation unit that was resolved by this task.
|
| + */
|
| + CompilationUnit _resolvedUnit;
|
| +
|
| + /**
|
| + * Initialize a newly created task to perform analysis within the given context.
|
| *
|
| - * @param elementMap a table mapping the source for the libraries represented by the elements to
|
| - * the elements representing the libraries
|
| + * @param context the context in which the task is to be performed
|
| + * @param source the source to be parsed
|
| + * @param libraryElement the element model for the library containing the source
|
| */
|
| - void recordLibraryElements(Map<Source, LibraryElement> elementMap);
|
| -}
|
| -/**
|
| - * Instances of the class `RecordingErrorListener` implement an error listener that will
|
| - * record the errors that are reported to it in a way that is appropriate for caching those errors
|
| - * within an analysis context.
|
| - *
|
| - * @coverage dart.engine
|
| - */
|
| -class RecordingErrorListener implements AnalysisErrorListener {
|
| + ResolveDartUnitTask(InternalAnalysisContext context, Source source, LibraryElement libraryElement) : super(context) {
|
| + this._source = source;
|
| + this._libraryElement = libraryElement;
|
| + }
|
| + accept(AnalysisTaskVisitor visitor) => visitor.visitResolveDartUnitTask(this);
|
|
|
| /**
|
| - * A HashMap of lists containing the errors that were collected, keyed by each [Source].
|
| + * Return the source for the library containing the source that is to be resolved.
|
| + *
|
| + * @return the source for the library containing the source that is to be resolved
|
| */
|
| - Map<Source, List<AnalysisError>> _errors = new Map<Source, List<AnalysisError>>();
|
| + Source get librarySource => _libraryElement.source;
|
|
|
| /**
|
| - * Add all of the errors recorded by the given listener to this listener.
|
| + * Return the time at which the contents of the source that was parsed were last modified, or a
|
| + * negative value if the task has not yet been performed or if an exception occurred.
|
| *
|
| - * @param listener the listener that has recorded the errors to be added
|
| + * @return the time at which the contents of the source that was parsed were last modified
|
| */
|
| - void addAll(RecordingErrorListener listener) {
|
| - for (AnalysisError error in listener.errors) {
|
| - onError(error);
|
| - }
|
| - }
|
| + int get modificationTime => _modificationTime;
|
|
|
| /**
|
| - * Answer the errors collected by the listener.
|
| + * Return the compilation unit that was resolved by this task.
|
| *
|
| - * @return an array of errors (not `null`, contains no `null`s)
|
| + * @return the compilation unit that was resolved by this task
|
| */
|
| - List<AnalysisError> get errors {
|
| - Iterable<MapEntry<Source, List<AnalysisError>>> entrySet = getMapEntrySet(_errors);
|
| - int numEntries = entrySet.length;
|
| - if (numEntries == 0) {
|
| - return AnalysisError.NO_ERRORS;
|
| - }
|
| - List<AnalysisError> resultList = new List<AnalysisError>();
|
| - for (MapEntry<Source, List<AnalysisError>> entry in entrySet) {
|
| - resultList.addAll(entry.getValue());
|
| + CompilationUnit get resolvedUnit => _resolvedUnit;
|
| +
|
| + /**
|
| + * Return the source that is to be resolved.
|
| + *
|
| + * @return the source to be resolved
|
| + */
|
| + Source get source => _source;
|
| + String get taskDescription => "resolve unit ${_libraryElement.source.fullName}";
|
| + void internalPerform() {
|
| + Source coreLibrarySource = _libraryElement.context.sourceFactory.forUri(DartSdk.DART_CORE);
|
| + LibraryElement coreElement = context.computeLibraryElement(coreLibrarySource);
|
| + TypeProvider typeProvider = new TypeProviderImpl(coreElement);
|
| + ResolvableCompilationUnit resolvableUnit = context.computeResolvableCompilationUnit(_source);
|
| + _modificationTime = resolvableUnit.modificationTime;
|
| + CompilationUnit unit = resolvableUnit.compilationUnit;
|
| + if (unit == null) {
|
| + throw new AnalysisException.con1("Internal error: computeResolvableCompilationUnit returned a value without a parsed Dart unit");
|
| + }
|
| + new DeclarationResolver().resolve(unit, find(_libraryElement, _source));
|
| + RecordingErrorListener errorListener = new RecordingErrorListener();
|
| + TypeResolverVisitor typeResolverVisitor = new TypeResolverVisitor.con2(_libraryElement, _source, typeProvider, errorListener);
|
| + unit.accept(typeResolverVisitor);
|
| + InheritanceManager inheritanceManager = new InheritanceManager(_libraryElement);
|
| + ResolverVisitor resolverVisitor = new ResolverVisitor.con2(_libraryElement, _source, typeProvider, inheritanceManager, errorListener);
|
| + unit.accept(resolverVisitor);
|
| + for (ProxyConditionalAnalysisError conditionalCode in resolverVisitor.proxyConditionalAnalysisErrors) {
|
| + if (conditionalCode.shouldIncludeErrorCode()) {
|
| + resolverVisitor.reportError(conditionalCode.analysisError);
|
| + }
|
| }
|
| - return new List.from(resultList);
|
| + ErrorReporter errorReporter = new ErrorReporter(errorListener, _source);
|
| + ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter, _libraryElement, typeProvider, inheritanceManager);
|
| + unit.accept(errorVerifier);
|
| + ConstantVerifier constantVerifier = new ConstantVerifier(errorReporter, typeProvider);
|
| + unit.accept(constantVerifier);
|
| + unit.resolutionErrors = errorListener.errors;
|
| + _resolvedUnit = unit;
|
| }
|
|
|
| /**
|
| - * Answer the errors collected by the listener for some passed [Source].
|
| + * Search the compilation units that are part of the given library and return the element
|
| + * representing the compilation unit with the given source. Return `null` if there is no
|
| + * such compilation unit.
|
| *
|
| - * @param source some [Source] for which the caller wants the set of [AnalysisError]s
|
| - * collected by this listener
|
| - * @return the errors collected by the listener for the passed [Source]
|
| + * @param libraryElement the element representing the library being searched through
|
| + * @param unitSource the source for the compilation unit whose element is to be returned
|
| + * @return the element representing the compilation unit
|
| */
|
| - List<AnalysisError> getErrors2(Source source) {
|
| - List<AnalysisError> errorsForSource = _errors[source];
|
| - if (errorsForSource == null) {
|
| - return AnalysisError.NO_ERRORS;
|
| - } else {
|
| - return new List.from(errorsForSource);
|
| + CompilationUnitElement find(LibraryElement libraryElement, Source unitSource) {
|
| + CompilationUnitElement element = libraryElement.definingCompilationUnit;
|
| + if (element.source == unitSource) {
|
| + return element;
|
| }
|
| - }
|
| - void onError(AnalysisError event) {
|
| - Source source = event.source;
|
| - List<AnalysisError> errorsForSource = _errors[source];
|
| - if (_errors[source] == null) {
|
| - errorsForSource = new List<AnalysisError>();
|
| - _errors[source] = errorsForSource;
|
| + for (CompilationUnitElement partElement in libraryElement.parts) {
|
| + if (partElement.source == unitSource) {
|
| + return partElement;
|
| + }
|
| }
|
| - errorsForSource.add(event);
|
| - }
|
| -}
|
| -/**
|
| - * Instances of the class `ResolutionEraser` remove any resolution information from an AST
|
| - * structure when used to visit that structure.
|
| - */
|
| -class ResolutionEraser extends GeneralizingASTVisitor<Object> {
|
| - Object visitAssignmentExpression(AssignmentExpression node) {
|
| - node.staticElement = null;
|
| - node.propagatedElement = null;
|
| - return super.visitAssignmentExpression(node);
|
| - }
|
| - Object visitBinaryExpression(BinaryExpression node) {
|
| - node.staticElement = null;
|
| - node.propagatedElement = null;
|
| - return super.visitBinaryExpression(node);
|
| - }
|
| - Object visitCompilationUnit(CompilationUnit node) {
|
| - node.element = null;
|
| - return super.visitCompilationUnit(node);
|
| - }
|
| - Object visitConstructorDeclaration(ConstructorDeclaration node) {
|
| - node.element = null;
|
| - return super.visitConstructorDeclaration(node);
|
| - }
|
| - Object visitConstructorName(ConstructorName node) {
|
| - node.staticElement = null;
|
| - node.element = null;
|
| - return super.visitConstructorName(node);
|
| - }
|
| - Object visitDirective(Directive node) {
|
| - node.element = null;
|
| - return super.visitDirective(node);
|
| - }
|
| - Object visitExpression(Expression node) {
|
| - node.staticType = null;
|
| - node.propagatedType = null;
|
| - return super.visitExpression(node);
|
| - }
|
| - Object visitFunctionExpression(FunctionExpression node) {
|
| - node.element = null;
|
| - return super.visitFunctionExpression(node);
|
| - }
|
| - Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
|
| - node.staticElement = null;
|
| - node.propagatedElement = null;
|
| - return super.visitFunctionExpressionInvocation(node);
|
| - }
|
| - Object visitIndexExpression(IndexExpression node) {
|
| - node.staticElement = null;
|
| - node.propagatedElement = null;
|
| - return super.visitIndexExpression(node);
|
| - }
|
| - Object visitInstanceCreationExpression(InstanceCreationExpression node) {
|
| - node.staticElement = null;
|
| - node.element = null;
|
| - return super.visitInstanceCreationExpression(node);
|
| - }
|
| - Object visitPostfixExpression(PostfixExpression node) {
|
| - node.staticElement = null;
|
| - node.propagatedElement = null;
|
| - return super.visitPostfixExpression(node);
|
| - }
|
| - Object visitPrefixExpression(PrefixExpression node) {
|
| - node.staticElement = null;
|
| - node.propagatedElement = null;
|
| - return super.visitPrefixExpression(node);
|
| - }
|
| - Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
|
| - node.staticElement = null;
|
| - node.element = null;
|
| - return super.visitRedirectingConstructorInvocation(node);
|
| - }
|
| - Object visitSimpleIdentifier(SimpleIdentifier node) {
|
| - node.staticElement = null;
|
| - node.propagatedElement = null;
|
| - return super.visitSimpleIdentifier(node);
|
| - }
|
| - Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
|
| - node.staticElement = null;
|
| - node.element = null;
|
| - return super.visitSuperConstructorInvocation(node);
|
| + return null;
|
| }
|
| }
|
| /**
|
| - * Instances of the class `ResolvableCompilationUnit` represent a compilation unit that is not
|
| - * referenced by any other objects and for which we have modification stamp information. It is used
|
| - * by the [LibraryResolver] to resolve a library.
|
| + * Instances of the class `ResolveHtmlTask` resolve a specific source as an HTML file.
|
| */
|
| -class ResolvableCompilationUnit {
|
| +class ResolveHtmlTask extends AnalysisTask {
|
|
|
| /**
|
| - * The modification time of the source from which the AST was created.
|
| + * The source to be resolved.
|
| */
|
| - int _modificationStamp = 0;
|
| + Source _source;
|
|
|
| /**
|
| - * The AST that was created from the source.
|
| + * The time at which the contents of the source were last modified.
|
| */
|
| - CompilationUnit _unit;
|
| + int _modificationTime = -1;
|
|
|
| /**
|
| - * Initialize a newly created holder to hold the given values.
|
| + * The element produced by resolving the source.
|
| + */
|
| + HtmlElement _element = null;
|
| +
|
| + /**
|
| + * The resolution errors that were discovered while resolving the source.
|
| + */
|
| + List<AnalysisError> _resolutionErrors = AnalysisError.NO_ERRORS;
|
| +
|
| + /**
|
| + * Initialize a newly created task to perform analysis within the given context.
|
| *
|
| - * @param modificationStamp the modification time of the source from which the AST was created
|
| - * @param unit the AST that was created from the source
|
| + * @param context the context in which the task is to be performed
|
| + * @param source the source to be resolved
|
| */
|
| - ResolvableCompilationUnit(int modificationStamp, CompilationUnit unit) {
|
| - this._modificationStamp = modificationStamp;
|
| - this._unit = unit;
|
| + ResolveHtmlTask(InternalAnalysisContext context, Source source) : super(context) {
|
| + this._source = source;
|
| }
|
| + accept(AnalysisTaskVisitor visitor) => visitor.visitResolveHtmlTask(this);
|
| + HtmlElement get element => _element;
|
|
|
| /**
|
| - * Return the AST that was created from the source.
|
| + * Return the time at which the contents of the source that was parsed were last modified, or a
|
| + * negative value if the task has not yet been performed or if an exception occurred.
|
| *
|
| - * @return the AST that was created from the source
|
| + * @return the time at which the contents of the source that was parsed were last modified
|
| */
|
| - CompilationUnit get compilationUnit => _unit;
|
| + int get modificationTime => _modificationTime;
|
| + List<AnalysisError> get resolutionErrors => _resolutionErrors;
|
|
|
| /**
|
| - * Return the modification time of the source from which the AST was created.
|
| + * Return the source that was or is to be resolved.
|
| *
|
| - * @return the modification time of the source from which the AST was created
|
| + * @return the source was or is to be resolved
|
| */
|
| - int get modificationStamp => _modificationStamp;
|
| + Source get source => _source;
|
| + String get taskDescription => "resolve as html ${_source.fullName}";
|
| + void internalPerform() {
|
| + ResolvableHtmlUnit resolvableHtmlUnit = context.computeResolvableHtmlUnit(_source);
|
| + HtmlUnit unit = resolvableHtmlUnit.compilationUnit;
|
| + if (unit == null) {
|
| + throw new AnalysisException.con1("Internal error: computeResolvableHtmlUnit returned a value without a parsed HTML unit");
|
| + }
|
| + _modificationTime = resolvableHtmlUnit.modificationTime;
|
| + HtmlUnitBuilder builder = new HtmlUnitBuilder(context);
|
| + _element = builder.buildHtmlElement2(_source, _modificationTime, unit);
|
| + _resolutionErrors = builder.errorListener.getErrors2(_source);
|
| + }
|
| }
|
| /**
|
| * The interface `Logger` defines the behavior of objects that can be used to receive
|
|
|