| Index: pkg/analyzer/lib/src/generated/engine.dart
|
| diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
|
| index 99970733b873f4accf239c68ee3e23674fbc62fd..4cf91cef7db24ff9d0327f57598cbd8e38742feb 100644
|
| --- a/pkg/analyzer/lib/src/generated/engine.dart
|
| +++ b/pkg/analyzer/lib/src/generated/engine.dart
|
| @@ -127,6 +127,13 @@ class AnalysisEngine {
|
| */
|
| abstract class AnalysisContentStatistics {
|
| /**
|
| + * Return the statistics for each kind of cached data.
|
| + *
|
| + * @return the statistics for each kind of cached data
|
| + */
|
| + List<AnalysisContentStatistics_CacheRow> get cacheRows;
|
| +
|
| + /**
|
| * Return the exceptions that caused some entries to have a state of [CacheState#ERROR].
|
| *
|
| * @return the exceptions that caused some entries to have a state of [CacheState#ERROR]
|
| @@ -134,11 +141,11 @@ abstract class AnalysisContentStatistics {
|
| List<AnalysisException> get exceptions;
|
|
|
| /**
|
| - * Return the statistics for each kind of cached data.
|
| + * Return an array containing all of the sources in the cache.
|
| *
|
| - * @return the statistics for each kind of cached data
|
| + * @return an array containing all of the sources in the cache
|
| */
|
| - List<AnalysisContentStatistics_CacheRow> get cacheRows;
|
| + List<Source> get sources;
|
| }
|
|
|
| /**
|
| @@ -281,6 +288,18 @@ abstract class AnalysisContext {
|
| LineInfo computeLineInfo(Source source);
|
|
|
| /**
|
| + * Return `true` if the given source exists.
|
| + *
|
| + * This method should be used rather than the method [Source#exists] because contexts can
|
| + * have local overrides of the content of a source that the source is not aware of and a source
|
| + * with local content is considered to exist even if there is no file on disk.
|
| + *
|
| + * @param source the source whose modification stamp is to be returned
|
| + * @return `true` if the source exists
|
| + */
|
| + bool exists(Source source);
|
| +
|
| + /**
|
| * Create a new context in which analysis can be performed. Any sources in the specified container
|
| * will be removed from this context and added to the newly created context.
|
| *
|
| @@ -300,6 +319,43 @@ abstract class AnalysisContext {
|
| AnalysisOptions get analysisOptions;
|
|
|
| /**
|
| + * Return the element model corresponding to the compilation unit defined by the given source in
|
| + * the library defined by the given source, or `null` if the element model does not
|
| + * currently exist or if the library cannot be analyzed for some reason.
|
| + *
|
| + * @param unitSource the source of the compilation unit
|
| + * @param librarySource the source of the defining compilation unit of the library containing the
|
| + * compilation unit
|
| + * @return the element model corresponding to the compilation unit defined by the given source
|
| + */
|
| + CompilationUnitElement getCompilationUnitElement(Source unitSource, Source librarySource);
|
| +
|
| + /**
|
| + * Get the contents and timestamp of the given source.
|
| + *
|
| + * This method should be used rather than the method [Source#getContents] because contexts
|
| + * can have local overrides of the content of a source that the source is not aware of.
|
| + *
|
| + * @param source the source whose content is to be returned
|
| + * @return the contents and timestamp of the source
|
| + * @throws Exception if the contents of the source could not be accessed
|
| + */
|
| + TimestampedData<String> getContents(Source source);
|
| +
|
| + /**
|
| + * Get the contents of the given source and pass it to the given content receiver.
|
| + *
|
| + * This method should be used rather than the method [Source#getContentsToReceiver]
|
| + * because contexts can have local overrides of the content of a source that the source is not
|
| + * aware of.
|
| + *
|
| + * @param source the source whose content is to be returned
|
| + * @param receiver the content receiver to which the content of the source will be passed
|
| + * @throws Exception if the contents of the source could not be accessed
|
| + */
|
| + void getContents2(Source source, Source_ContentReceiver receiver);
|
| +
|
| + /**
|
| * Return the element referenced by the given location, or `null` if the element is not
|
| * immediately available or if there is no element with the given location. The latter condition
|
| * can occur, for example, if the location describes an element from a different context or if the
|
| @@ -438,6 +494,21 @@ abstract class AnalysisContext {
|
| LineInfo getLineInfo(Source source);
|
|
|
| /**
|
| + * Return the modification stamp for the given source. A modification stamp is a non-negative
|
| + * integer with the property that if the contents of the source have not been modified since the
|
| + * last time the modification stamp was accessed then the same value will be returned, but if the
|
| + * contents of the source have been modified one or more times (even if the net change is zero)
|
| + * the stamps will be different.
|
| + *
|
| + * This method should be used rather than the method [Source#getModificationStamp] because
|
| + * contexts can have local overrides of the content of a source that the source is not aware of.
|
| + *
|
| + * @param source the source whose modification stamp is to be returned
|
| + * @return the modification stamp for the source
|
| + */
|
| + int getModificationStamp(Source source);
|
| +
|
| + /**
|
| * Return an array containing all of the sources known to this context and their resolution state
|
| * is not valid or flush. So, these sources are not safe to update during refactoring, because we
|
| * may be don't know all the references in them.
|
| @@ -642,15 +713,6 @@ abstract class AnalysisContext {
|
| * context
|
| */
|
| void set sourceFactory(SourceFactory factory);
|
| -
|
| - /**
|
| - * Given a collection of sources with content that has changed, return an [Iterable]
|
| - * identifying the sources that need to be resolved.
|
| - *
|
| - * @param changedSources an array of sources (not `null`, contains no `null`s)
|
| - * @return An iterable returning the sources to be resolved
|
| - */
|
| - Iterable<Source> sourcesToResolve(List<Source> changedSources);
|
| }
|
|
|
| /**
|
| @@ -715,6 +777,13 @@ class AnalysisException extends JavaException {
|
| */
|
| abstract class AnalysisOptions {
|
| /**
|
| + * Return `true` if analysis is to analyze Angular.
|
| + *
|
| + * @return `true` if analysis is to analyze Angular
|
| + */
|
| + bool get analyzeAngular;
|
| +
|
| + /**
|
| * Return `true` if analysis is to parse and analyze function bodies.
|
| *
|
| * @return `true` if analysis is to parse and analyzer function bodies
|
| @@ -736,6 +805,14 @@ abstract class AnalysisOptions {
|
| bool get dart2jsHint;
|
|
|
| /**
|
| + * Return `true` if errors, warnings and hints should be generated for sources in the SDK.
|
| + * The default value is `false`.
|
| + *
|
| + * @return `true` if errors, warnings and hints should be generated for the SDK
|
| + */
|
| + bool get generateSdkErrors;
|
| +
|
| + /**
|
| * Return `true` if analysis is to generate hint results (e.g. type inference based
|
| * information and pub best practices).
|
| *
|
| @@ -756,13 +833,6 @@ abstract class AnalysisOptions {
|
| * @return `true` if analysis is to parse comments
|
| */
|
| bool get preserveComments;
|
| -
|
| - /**
|
| - * Return `true` if analysis is to analyze Angular.
|
| - *
|
| - * @return `true` if analysis is to analyze Angular
|
| - */
|
| - bool get analyzeAngular;
|
| }
|
|
|
| /**
|
| @@ -970,6 +1040,34 @@ class ChangeSet {
|
| }
|
|
|
| /**
|
| + * Instances of the class `ObsoleteSourceAnalysisException` represent an analysis attempt that
|
| + * failed because a source was deleted between the time the analysis started and the time the
|
| + * results of the analysis were ready to be recorded.
|
| + */
|
| +class ObsoleteSourceAnalysisException extends AnalysisException {
|
| + /**
|
| + * The source that was removed while it was being analyzed.
|
| + */
|
| + Source _source;
|
| +
|
| + /**
|
| + * Initialize a newly created exception to represent the removal of the given source.
|
| + *
|
| + * @param source the source that was removed while it was being analyzed
|
| + */
|
| + ObsoleteSourceAnalysisException(Source source) : super.con1("The source '${source.fullName}' was removed while it was being analyzed") {
|
| + this._source = source;
|
| + }
|
| +
|
| + /**
|
| + * Return the source that was removed while it was being analyzed.
|
| + *
|
| + * @return the source that was removed
|
| + */
|
| + Source get source => _source;
|
| +}
|
| +
|
| +/**
|
| * Instances of the class `AnalysisCache` implement an LRU cache of information related to
|
| * analysis.
|
| */
|
| @@ -1163,17 +1261,6 @@ class AnalysisCache {
|
| }
|
|
|
| /**
|
| - * Information about Angular application.
|
| - */
|
| -class AngularApplicationInfo {
|
| - final Source entryPoint;
|
| -
|
| - final List<AngularElement> elements;
|
| -
|
| - AngularApplicationInfo(this.entryPoint, this.elements);
|
| -}
|
| -
|
| -/**
|
| * Instances of the class `CacheRetentionPolicy` define the behavior of objects that determine
|
| * how important it is for data to be retained in the analysis cache.
|
| */
|
| @@ -1337,11 +1424,26 @@ abstract class DartEntry implements SourceEntry {
|
| static final DataDescriptor<SourceKind> SOURCE_KIND = new DataDescriptor<SourceKind>("DartEntry.SOURCE_KIND");
|
|
|
| /**
|
| + * The data descriptor representing the token stream.
|
| + */
|
| + static final DataDescriptor<List<AnalysisError>> SCAN_ERRORS = new DataDescriptor<List<AnalysisError>>("DartEntry.SCAN_ERRORS");
|
| +
|
| + /**
|
| + * The data descriptor representing the token stream.
|
| + */
|
| + static final DataDescriptor<Token> TOKEN_STREAM = new DataDescriptor<Token>("DartEntry.TOKEN_STREAM");
|
| +
|
| + /**
|
| * The data descriptor representing the errors resulting from verifying the source.
|
| */
|
| static final DataDescriptor<List<AnalysisError>> VERIFICATION_ERRORS = new DataDescriptor<List<AnalysisError>>("DartEntry.VERIFICATION_ERRORS");
|
|
|
| /**
|
| + * The data descriptor representing the errors reported during Angular resolution.
|
| + */
|
| + static final DataDescriptor<List<AnalysisError>> ANGULAR_ERRORS = new DataDescriptor<List<AnalysisError>>("DartEntry.ANGULAR_ERRORS");
|
| +
|
| + /**
|
| * Return all of the errors associated with the compilation unit that are currently cached.
|
| *
|
| * @return all of the errors associated with the compilation unit
|
| @@ -1412,6 +1514,27 @@ abstract class DartEntry implements SourceEntry {
|
| */
|
| class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| /**
|
| + * The state of the cached token stream.
|
| + */
|
| + CacheState _tokenStreamState = CacheState.INVALID;
|
| +
|
| + /**
|
| + * The head of the token stream, or `null` if the token stream is not currently cached.
|
| + */
|
| + Token _tokenStream;
|
| +
|
| + /**
|
| + * The state of the cached scan errors.
|
| + */
|
| + CacheState _scanErrorsState = CacheState.INVALID;
|
| +
|
| + /**
|
| + * The errors produced while scanning the compilation unit, or `null` if the errors are not
|
| + * currently cached.
|
| + */
|
| + List<AnalysisError> _scanErrors = AnalysisError.NO_ERRORS;
|
| +
|
| + /**
|
| * The state of the cached source kind.
|
| */
|
| CacheState _sourceKindState = CacheState.INVALID;
|
| @@ -1444,8 +1567,8 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| CacheState _parseErrorsState = CacheState.INVALID;
|
|
|
| /**
|
| - * The errors produced while scanning and parsing the compilation unit, or `null` if the
|
| - * errors are not currently cached.
|
| + * The errors produced while parsing the compilation unit, or `null` if the errors are not
|
| + * currently cached.
|
| */
|
| List<AnalysisError> _parseErrors = AnalysisError.NO_ERRORS;
|
|
|
| @@ -1530,6 +1653,12 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| int _bitmask = 0;
|
|
|
| /**
|
| + * The error produced while performing Angular resolution, or an empty array if there are no
|
| + * errors if the error are not currently cached.
|
| + */
|
| + List<AnalysisError> _angularErrors = AnalysisError.NO_ERRORS;
|
| +
|
| + /**
|
| * The index of the bit in the [bitmask] indicating that this library is launchable: that
|
| * the file has a main method.
|
| */
|
| @@ -1556,6 +1685,10 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| * Flush any AST structures being maintained by this entry.
|
| */
|
| void flushAstStructures() {
|
| + if (identical(_tokenStreamState, CacheState.VALID)) {
|
| + _tokenStreamState = CacheState.FLUSHED;
|
| + _tokenStream = null;
|
| + }
|
| if (identical(_parsedUnitState, CacheState.VALID)) {
|
| _parsedUnitState = CacheState.FLUSHED;
|
| _parsedUnitAccessed = false;
|
| @@ -1566,23 +1699,16 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
|
|
| List<AnalysisError> get allErrors {
|
| List<AnalysisError> errors = new List<AnalysisError>();
|
| - for (AnalysisError error in _parseErrors) {
|
| - errors.add(error);
|
| - }
|
| + ListUtilities.addAll(errors, _scanErrors);
|
| + ListUtilities.addAll(errors, _parseErrors);
|
| DartEntryImpl_ResolutionState state = _resolutionState;
|
| while (state != null) {
|
| - for (AnalysisError error in state._resolutionErrors) {
|
| - errors.add(error);
|
| - }
|
| - for (AnalysisError error in state._verificationErrors) {
|
| - errors.add(error);
|
| - }
|
| - for (AnalysisError error in state._hints) {
|
| - errors.add(error);
|
| - }
|
| + ListUtilities.addAll(errors, state._resolutionErrors);
|
| + ListUtilities.addAll(errors, state._verificationErrors);
|
| + ListUtilities.addAll(errors, state._hints);
|
| state = state._nextState;
|
| }
|
| - ;
|
| + ListUtilities.addAll(errors, _angularErrors);
|
| if (errors.length == 0) {
|
| return AnalysisError.NO_ERRORS;
|
| }
|
| @@ -1673,8 +1799,12 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| return _parsedUnitState;
|
| } else if (identical(descriptor, DartEntry.PUBLIC_NAMESPACE)) {
|
| return _publicNamespaceState;
|
| + } else if (identical(descriptor, DartEntry.SCAN_ERRORS)) {
|
| + return _scanErrorsState;
|
| } else if (identical(descriptor, DartEntry.SOURCE_KIND)) {
|
| return _sourceKindState;
|
| + } else if (identical(descriptor, DartEntry.TOKEN_STREAM)) {
|
| + return _tokenStreamState;
|
| } else {
|
| return super.getState(descriptor);
|
| }
|
| @@ -1707,7 +1837,9 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| }
|
|
|
| Object getValue(DataDescriptor descriptor) {
|
| - if (identical(descriptor, DartEntry.CONTAINING_LIBRARIES)) {
|
| + if (identical(descriptor, DartEntry.ANGULAR_ERRORS)) {
|
| + return _angularErrors;
|
| + } else if (identical(descriptor, DartEntry.CONTAINING_LIBRARIES)) {
|
| return new List.from(_containingLibraries);
|
| } else if (identical(descriptor, DartEntry.ELEMENT)) {
|
| return _element;
|
| @@ -1728,8 +1860,12 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| return _parsedUnit;
|
| } else if (identical(descriptor, DartEntry.PUBLIC_NAMESPACE)) {
|
| return _publicNamespace;
|
| + } else if (identical(descriptor, DartEntry.SCAN_ERRORS)) {
|
| + return _scanErrors;
|
| } else if (identical(descriptor, DartEntry.SOURCE_KIND)) {
|
| return _sourceKind;
|
| + } else if (identical(descriptor, DartEntry.TOKEN_STREAM)) {
|
| + return _tokenStream;
|
| }
|
| return super.getValue(descriptor);
|
| }
|
| @@ -1787,8 +1923,12 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| return identical(_parsedUnitState, CacheState.INVALID);
|
| } else if (identical(descriptor, DartEntry.PUBLIC_NAMESPACE)) {
|
| return identical(_publicNamespaceState, CacheState.INVALID);
|
| + } else if (identical(descriptor, DartEntry.SCAN_ERRORS)) {
|
| + return identical(_scanErrorsState, CacheState.INVALID);
|
| } else if (identical(descriptor, DartEntry.SOURCE_KIND)) {
|
| return identical(_sourceKindState, CacheState.INVALID);
|
| + } else if (identical(descriptor, DartEntry.TOKEN_STREAM)) {
|
| + return identical(_tokenStreamState, CacheState.INVALID);
|
| } else if (identical(descriptor, DartEntry.RESOLUTION_ERRORS) || identical(descriptor, DartEntry.RESOLVED_UNIT) || identical(descriptor, DartEntry.VERIFICATION_ERRORS) || identical(descriptor, DartEntry.HINTS)) {
|
| DartEntryImpl_ResolutionState state = _resolutionState;
|
| while (state != null) {
|
| @@ -1810,6 +1950,10 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
|
|
| void invalidateAllInformation() {
|
| super.invalidateAllInformation();
|
| + _scanErrors = AnalysisError.NO_ERRORS;
|
| + _scanErrorsState = CacheState.INVALID;
|
| + _tokenStream = null;
|
| + _tokenStreamState = CacheState.INVALID;
|
| _sourceKind = SourceKind.UNKNOWN;
|
| _sourceKindState = CacheState.INVALID;
|
| _parseErrors = AnalysisError.NO_ERRORS;
|
| @@ -1902,7 +2046,6 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| * as being in error.
|
| */
|
| void recordParseError() {
|
| - setState(SourceEntry.LINE_INFO, CacheState.ERROR);
|
| _sourceKind = SourceKind.UNKNOWN;
|
| _sourceKindState = CacheState.ERROR;
|
| _parseErrors = AnalysisError.NO_ERRORS;
|
| @@ -1919,9 +2062,6 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| * the current thread.
|
| */
|
| void recordParseInProcess() {
|
| - if (getState(SourceEntry.LINE_INFO) != CacheState.VALID) {
|
| - setState(SourceEntry.LINE_INFO, CacheState.IN_PROCESS);
|
| - }
|
| if (_sourceKindState != CacheState.VALID) {
|
| _sourceKindState = CacheState.IN_PROCESS;
|
| }
|
| @@ -1989,6 +2129,52 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| }
|
|
|
| /**
|
| + * Record that an error occurred while attempting to scan or parse the entry represented by this
|
| + * entry. This will set the state of all information, including any resolution-based information,
|
| + * as being in error.
|
| + */
|
| + void recordScanError() {
|
| + setState(SourceEntry.LINE_INFO, CacheState.ERROR);
|
| + _scanErrors = AnalysisError.NO_ERRORS;
|
| + _scanErrorsState = CacheState.ERROR;
|
| + _tokenStream = null;
|
| + _tokenStreamState = CacheState.ERROR;
|
| + recordParseError();
|
| + }
|
| +
|
| + /**
|
| + * Record that the scan-related information for the associated source is about to be computed by
|
| + * the current thread.
|
| + */
|
| + void recordScanInProcess() {
|
| + if (getState(SourceEntry.LINE_INFO) != CacheState.VALID) {
|
| + setState(SourceEntry.LINE_INFO, CacheState.IN_PROCESS);
|
| + }
|
| + if (_scanErrorsState != CacheState.VALID) {
|
| + _scanErrorsState = CacheState.IN_PROCESS;
|
| + }
|
| + if (_tokenStreamState != CacheState.VALID) {
|
| + _tokenStreamState = CacheState.IN_PROCESS;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Record that an in-process scan has stopped without recording results because the results were
|
| + * invalidated before they could be recorded.
|
| + */
|
| + void recordScanNotInProcess() {
|
| + if (identical(getState(SourceEntry.LINE_INFO), CacheState.IN_PROCESS)) {
|
| + setState(SourceEntry.LINE_INFO, CacheState.INVALID);
|
| + }
|
| + if (identical(_scanErrorsState, CacheState.IN_PROCESS)) {
|
| + _scanErrorsState = CacheState.INVALID;
|
| + }
|
| + if (identical(_tokenStreamState, CacheState.IN_PROCESS)) {
|
| + _tokenStreamState = CacheState.INVALID;
|
| + }
|
| + }
|
| +
|
| + /**
|
| * Remove the given library from the list of libraries that contain this part. This method should
|
| * only be invoked on entries that represent a part.
|
| *
|
| @@ -2039,30 +2225,6 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| _containingLibraries.add(librarySource);
|
| }
|
|
|
| - /**
|
| - * Set the results of parsing the compilation unit at the given time to the given values.
|
| - *
|
| - * @param modificationStamp the earliest time at which the source was last modified before the
|
| - * parsing was started
|
| - * @param lineInfo the line information resulting from parsing the compilation unit
|
| - * @param unit the AST structure resulting from parsing the compilation unit
|
| - * @param errors the parse errors resulting from parsing the compilation unit
|
| - */
|
| - void setParseResults(int modificationStamp, LineInfo lineInfo, CompilationUnit unit, List<AnalysisError> errors) {
|
| - if (getState(SourceEntry.LINE_INFO) != CacheState.VALID) {
|
| - setValue(SourceEntry.LINE_INFO, lineInfo);
|
| - }
|
| - if (_parsedUnitState != CacheState.VALID) {
|
| - _parsedUnit = unit;
|
| - _parsedUnitAccessed = false;
|
| - _parsedUnitState = CacheState.VALID;
|
| - }
|
| - if (_parseErrorsState != CacheState.VALID) {
|
| - _parseErrors = errors == null ? AnalysisError.NO_ERRORS : errors;
|
| - _parseErrorsState = CacheState.VALID;
|
| - }
|
| - }
|
| -
|
| void setState(DataDescriptor descriptor, CacheState state) {
|
| if (identical(descriptor, DartEntry.ELEMENT)) {
|
| _element = updatedValue(state, _element, null);
|
| @@ -2095,9 +2257,15 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| } else if (identical(descriptor, DartEntry.PUBLIC_NAMESPACE)) {
|
| _publicNamespace = updatedValue(state, _publicNamespace, null);
|
| _publicNamespaceState = state;
|
| + } else if (identical(descriptor, DartEntry.SCAN_ERRORS)) {
|
| + _scanErrors = updatedValue(state, _scanErrors, AnalysisError.NO_ERRORS);
|
| + _scanErrorsState = state;
|
| } else if (identical(descriptor, DartEntry.SOURCE_KIND)) {
|
| _sourceKind = updatedValue(state, _sourceKind, SourceKind.UNKNOWN);
|
| _sourceKindState = state;
|
| + } else if (identical(descriptor, DartEntry.TOKEN_STREAM)) {
|
| + _tokenStream = updatedValue(state, _tokenStream, null);
|
| + _tokenStreamState = state;
|
| } else {
|
| super.setState(descriptor, state);
|
| }
|
| @@ -2132,7 +2300,9 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| }
|
|
|
| void setValue(DataDescriptor descriptor, Object value) {
|
| - if (identical(descriptor, DartEntry.ELEMENT)) {
|
| + if (identical(descriptor, DartEntry.ANGULAR_ERRORS)) {
|
| + _angularErrors = value == null ? AnalysisError.NO_ERRORS : (value as List<AnalysisError>);
|
| + } else if (identical(descriptor, DartEntry.ELEMENT)) {
|
| _element = value as LibraryElement;
|
| _elementState = CacheState.VALID;
|
| } else if (identical(descriptor, DartEntry.EXPORTED_LIBRARIES)) {
|
| @@ -2160,9 +2330,15 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| } else if (identical(descriptor, DartEntry.PUBLIC_NAMESPACE)) {
|
| _publicNamespace = value as Namespace;
|
| _publicNamespaceState = CacheState.VALID;
|
| + } else if (identical(descriptor, DartEntry.SCAN_ERRORS)) {
|
| + _scanErrors = value == null ? AnalysisError.NO_ERRORS : (value as List<AnalysisError>);
|
| + _scanErrorsState = CacheState.VALID;
|
| } else if (identical(descriptor, DartEntry.SOURCE_KIND)) {
|
| _sourceKind = value as SourceKind;
|
| _sourceKindState = CacheState.VALID;
|
| + } else if (identical(descriptor, DartEntry.TOKEN_STREAM)) {
|
| + _tokenStream = value as Token;
|
| + _tokenStreamState = CacheState.VALID;
|
| } else {
|
| super.setValue(descriptor, value);
|
| }
|
| @@ -2197,6 +2373,10 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| void copyFrom(SourceEntryImpl entry) {
|
| super.copyFrom(entry);
|
| DartEntryImpl other = entry as DartEntryImpl;
|
| + _scanErrorsState = other._scanErrorsState;
|
| + _scanErrors = other._scanErrors;
|
| + _tokenStreamState = other._tokenStreamState;
|
| + _tokenStream = other._tokenStream;
|
| _sourceKindState = other._sourceKindState;
|
| _sourceKind = other._sourceKind;
|
| _parsedUnitState = other._parsedUnitState;
|
| @@ -2219,13 +2399,18 @@ class DartEntryImpl extends SourceEntryImpl implements DartEntry {
|
| _clientServerState = other._clientServerState;
|
| _launchableState = other._launchableState;
|
| _bitmask = other._bitmask;
|
| + _angularErrors = other._angularErrors;
|
| }
|
|
|
| - bool hasErrorState() => super.hasErrorState() || identical(_sourceKindState, CacheState.ERROR) || identical(_parsedUnitState, CacheState.ERROR) || identical(_parseErrorsState, CacheState.ERROR) || identical(_importedLibrariesState, CacheState.ERROR) || identical(_exportedLibrariesState, CacheState.ERROR) || identical(_includedPartsState, CacheState.ERROR) || identical(_elementState, CacheState.ERROR) || identical(_publicNamespaceState, CacheState.ERROR) || identical(_clientServerState, CacheState.ERROR) || identical(_launchableState, CacheState.ERROR) || _resolutionState.hasErrorState();
|
| + bool hasErrorState() => super.hasErrorState() || identical(_scanErrorsState, CacheState.ERROR) || identical(_tokenStreamState, CacheState.ERROR) || identical(_sourceKindState, CacheState.ERROR) || identical(_parsedUnitState, CacheState.ERROR) || identical(_parseErrorsState, CacheState.ERROR) || identical(_importedLibrariesState, CacheState.ERROR) || identical(_exportedLibrariesState, CacheState.ERROR) || identical(_includedPartsState, CacheState.ERROR) || identical(_elementState, CacheState.ERROR) || identical(_publicNamespaceState, CacheState.ERROR) || identical(_clientServerState, CacheState.ERROR) || identical(_launchableState, CacheState.ERROR) || _resolutionState.hasErrorState();
|
|
|
| void writeOn(JavaStringBuilder builder) {
|
| builder.append("Dart: ");
|
| super.writeOn(builder);
|
| + builder.append("; tokenStream = ");
|
| + builder.append(_tokenStreamState);
|
| + builder.append("; scanErrors = ");
|
| + builder.append(_scanErrorsState);
|
| builder.append("; sourceKind = ");
|
| builder.append(_sourceKindState);
|
| builder.append("; parsedUnit = ");
|
| @@ -2529,7 +2714,7 @@ abstract class HtmlEntry implements SourceEntry {
|
| * The data descriptor representing the information about an Angular application this source is
|
| * used in.
|
| */
|
| - static final DataDescriptor<AngularApplicationInfo> ANGULAR_APPLICATION = new DataDescriptor<AngularApplicationInfo>("HtmlEntry.ANGULAR_APPLICATION");
|
| + static final DataDescriptor<AngularApplication> ANGULAR_APPLICATION = new DataDescriptor<AngularApplication>("HtmlEntry.ANGULAR_APPLICATION");
|
|
|
| /**
|
| * The data descriptor representing the information about an Angular component this source is used
|
| @@ -2541,7 +2726,7 @@ abstract class HtmlEntry implements SourceEntry {
|
| * The data descriptor representing the information about an Angular application this source is
|
| * entry point for.
|
| */
|
| - static final DataDescriptor<AngularApplicationInfo> ANGULAR_ENTRY = new DataDescriptor<AngularApplicationInfo>("HtmlEntry.ANGULAR_ENTRY");
|
| + static final DataDescriptor<AngularApplication> ANGULAR_ENTRY = new DataDescriptor<AngularApplication>("HtmlEntry.ANGULAR_ENTRY");
|
|
|
| /**
|
| * The data descriptor representing the errors reported during Angular resolution.
|
| @@ -2678,17 +2863,17 @@ class HtmlEntryImpl extends SourceEntryImpl implements HtmlEntry {
|
| /**
|
| * Information about the Angular Application this unit is used in.
|
| */
|
| - AngularApplicationInfo _angularApplication;
|
| + AngularApplication _angularApplication;
|
|
|
| /**
|
| * The state of the [angularEntry].
|
| */
|
| - CacheState _angularEntryState = CacheState.VALID;
|
| + CacheState _angularEntryState = CacheState.INVALID;
|
|
|
| /**
|
| * Information about the Angular Application this unit is entry point for.
|
| */
|
| - AngularApplicationInfo _angularEntry = null;
|
| + AngularApplication _angularEntry = null;
|
|
|
| /**
|
| * The state of the [angularComponent].
|
| @@ -2855,6 +3040,8 @@ class HtmlEntryImpl extends SourceEntryImpl implements HtmlEntry {
|
| * Invalidate all of the resolution information associated with the HTML file.
|
| */
|
| void invalidateAllResolutionInformation() {
|
| + _angularEntry = null;
|
| + _angularEntryState = CacheState.INVALID;
|
| _angularErrors = AnalysisError.NO_ERRORS;
|
| _angularErrorsState = CacheState.INVALID;
|
| _element = null;
|
| @@ -2930,13 +3117,13 @@ class HtmlEntryImpl extends SourceEntryImpl implements HtmlEntry {
|
|
|
| void setValue(DataDescriptor descriptor, Object value) {
|
| if (identical(descriptor, HtmlEntry.ANGULAR_APPLICATION)) {
|
| - _angularApplication = value as AngularApplicationInfo;
|
| + _angularApplication = value as AngularApplication;
|
| _angularApplicationState = CacheState.VALID;
|
| } else if (identical(descriptor, HtmlEntry.ANGULAR_COMPONENT)) {
|
| _angularComponent = value as AngularComponentElement;
|
| _angularComponentState = CacheState.VALID;
|
| } else if (identical(descriptor, HtmlEntry.ANGULAR_ENTRY)) {
|
| - _angularEntry = value as AngularApplicationInfo;
|
| + _angularEntry = value as AngularApplication;
|
| _angularEntryState = CacheState.VALID;
|
| } else if (identical(descriptor, HtmlEntry.ANGULAR_ERRORS)) {
|
| _angularErrors = value as List<AnalysisError>;
|
| @@ -3293,8 +3480,14 @@ abstract class SourceEntryImpl implements SourceEntry {
|
| class AnalysisContentStatisticsImpl implements AnalysisContentStatistics {
|
| Map<String, AnalysisContentStatistics_CacheRow> _dataMap = new Map<String, AnalysisContentStatistics_CacheRow>();
|
|
|
| + List<Source> _sources = new List<Source>();
|
| +
|
| Set<AnalysisException> _exceptions = new Set<AnalysisException>();
|
|
|
| + void addSource(Source source) {
|
| + _sources.add(source);
|
| + }
|
| +
|
| List<AnalysisContentStatistics_CacheRow> get cacheRows {
|
| Iterable<AnalysisContentStatistics_CacheRow> items = _dataMap.values;
|
| return new List.from(items);
|
| @@ -3302,14 +3495,16 @@ class AnalysisContentStatisticsImpl implements AnalysisContentStatistics {
|
|
|
| List<AnalysisException> get exceptions => new List.from(_exceptions);
|
|
|
| - void putCacheItem(DartEntry dartEntry, DataDescriptor descriptor) {
|
| - putCacheItem3(dartEntry, descriptor, dartEntry.getState(descriptor));
|
| - }
|
| + List<Source> get sources => new List.from(_sources);
|
|
|
| - void putCacheItem2(DartEntry dartEntry, Source librarySource, DataDescriptor descriptor) {
|
| + void putCacheItem(DartEntry dartEntry, Source librarySource, DataDescriptor descriptor) {
|
| putCacheItem3(dartEntry, descriptor, dartEntry.getState2(descriptor, librarySource));
|
| }
|
|
|
| + void putCacheItem2(SourceEntry dartEntry, DataDescriptor descriptor) {
|
| + putCacheItem3(dartEntry, descriptor, dartEntry.getState(descriptor));
|
| + }
|
| +
|
| void putCacheItem3(SourceEntry dartEntry, DataDescriptor rowDesc, CacheState state) {
|
| String rowName = rowDesc.toString();
|
| AnalysisContentStatisticsImpl_CacheRowImpl row = _dataMap[rowName] as AnalysisContentStatisticsImpl_CacheRowImpl;
|
| @@ -3395,6 +3590,11 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| AnalysisOptionsImpl _options = new AnalysisOptionsImpl();
|
|
|
| /**
|
| + * A cache of content used to override the default content of a source.
|
| + */
|
| + ContentCache _contentCache = new ContentCache();
|
| +
|
| + /**
|
| * The source factory used to create the sources that can be analyzed in this context.
|
| */
|
| SourceFactory _sourceFactory;
|
| @@ -3450,6 +3650,11 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| WorkManager _workManager = new WorkManager();
|
|
|
| /**
|
| + * The set of [AngularApplication] in this context.
|
| + */
|
| + Set<AngularApplication> _angularApplications = new Set();
|
| +
|
| + /**
|
| * Initialize a newly created analysis context.
|
| */
|
| AnalysisContextImpl() : super() {
|
| @@ -3560,24 +3765,34 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| SourceEntry sourceEntry = getReadableSourceEntry(source);
|
| if (sourceEntry is DartEntry) {
|
| List<AnalysisError> errors = new List<AnalysisError>();
|
| - DartEntry dartEntry = sourceEntry;
|
| - 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));
|
| - ListUtilities.addAll(errors, getDartVerificationData(source, source, dartEntry, DartEntry.VERIFICATION_ERRORS));
|
| - if (enableHints) {
|
| - ListUtilities.addAll(errors, getDartHintData(source, source, dartEntry, DartEntry.HINTS));
|
| - }
|
| - } else {
|
| - List<Source> libraries = getLibrariesContaining(source);
|
| - for (Source librarySource in libraries) {
|
| - ListUtilities.addAll(errors, getDartResolutionData(source, librarySource, dartEntry, DartEntry.RESOLUTION_ERRORS));
|
| - ListUtilities.addAll(errors, getDartVerificationData(source, librarySource, dartEntry, DartEntry.VERIFICATION_ERRORS));
|
| + try {
|
| + DartEntry dartEntry = sourceEntry;
|
| + ListUtilities.addAll(errors, getDartScanData(source, dartEntry, DartEntry.SCAN_ERRORS));
|
| + dartEntry = getReadableDartEntry(source);
|
| + 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));
|
| + dartEntry = getReadableDartEntry(source);
|
| + ListUtilities.addAll(errors, getDartVerificationData(source, source, dartEntry, DartEntry.VERIFICATION_ERRORS));
|
| if (enableHints) {
|
| - ListUtilities.addAll(errors, getDartHintData(source, librarySource, dartEntry, DartEntry.HINTS));
|
| + dartEntry = getReadableDartEntry(source);
|
| + ListUtilities.addAll(errors, getDartHintData(source, source, dartEntry, DartEntry.HINTS));
|
| + }
|
| + } else {
|
| + List<Source> libraries = getLibrariesContaining(source);
|
| + for (Source librarySource in libraries) {
|
| + ListUtilities.addAll(errors, getDartResolutionData(source, librarySource, dartEntry, DartEntry.RESOLUTION_ERRORS));
|
| + dartEntry = getReadableDartEntry(source);
|
| + ListUtilities.addAll(errors, getDartVerificationData(source, librarySource, dartEntry, DartEntry.VERIFICATION_ERRORS));
|
| + if (enableHints) {
|
| + dartEntry = getReadableDartEntry(source);
|
| + ListUtilities.addAll(errors, getDartHintData(source, librarySource, dartEntry, DartEntry.HINTS));
|
| + }
|
| }
|
| }
|
| + } on ObsoleteSourceAnalysisException catch (exception) {
|
| + AnalysisEngine.instance.logger.logInformation3("Could not compute errors", exception);
|
| }
|
| if (errors.isEmpty) {
|
| return AnalysisError.NO_ERRORS;
|
| @@ -3585,7 +3800,11 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| return new List.from(errors);
|
| } else if (sourceEntry is HtmlEntry) {
|
| HtmlEntry htmlEntry = sourceEntry;
|
| - return getHtmlResolutionData2(source, htmlEntry, HtmlEntry.RESOLUTION_ERRORS);
|
| + try {
|
| + return getHtmlResolutionData2(source, htmlEntry, HtmlEntry.RESOLUTION_ERRORS);
|
| + } on ObsoleteSourceAnalysisException catch (exception) {
|
| + AnalysisEngine.instance.logger.logInformation3("Could not compute errors", exception);
|
| + }
|
| }
|
| return AnalysisError.NO_ERRORS;
|
| }
|
| @@ -3614,10 +3833,14 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
|
|
| LineInfo computeLineInfo(Source 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);
|
| + try {
|
| + if (sourceEntry is HtmlEntry) {
|
| + return getHtmlParseData(source, SourceEntry.LINE_INFO, null);
|
| + } else if (sourceEntry is DartEntry) {
|
| + return getDartScanData2(source, SourceEntry.LINE_INFO, null);
|
| + }
|
| + } on ObsoleteSourceAnalysisException catch (exception) {
|
| + AnalysisEngine.instance.logger.logInformation3("Could not compute ${SourceEntry.LINE_INFO.toString()}", exception);
|
| }
|
| return null;
|
| }
|
| @@ -3668,6 +3891,16 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| return new ResolvableHtmlUnit(htmlEntry.modificationTime, unit);
|
| }
|
|
|
| + bool exists(Source source) {
|
| + if (source == null) {
|
| + return false;
|
| + }
|
| + if (_contentCache.getContents(source) != null) {
|
| + return true;
|
| + }
|
| + return source.exists();
|
| + }
|
| +
|
| AnalysisContext extractContext(SourceContainer container) => extractContextInto(container, AnalysisEngine.instance.createAnalysisContext() as InternalAnalysisContext);
|
|
|
| InternalAnalysisContext extractContextInto(SourceContainer container, InternalAnalysisContext newContext) {
|
| @@ -3687,6 +3920,41 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
|
|
| AnalysisOptions get analysisOptions => _options;
|
|
|
| + CompilationUnitElement getCompilationUnitElement(Source unitSource, Source librarySource) {
|
| + LibraryElement libraryElement = getLibraryElement(librarySource);
|
| + if (libraryElement != null) {
|
| + // try defining unit
|
| + CompilationUnitElement definingUnit = libraryElement.definingCompilationUnit;
|
| + if (definingUnit.source == unitSource) {
|
| + return definingUnit;
|
| + }
|
| + // try parts
|
| + for (CompilationUnitElement partUnit in libraryElement.parts) {
|
| + if (partUnit.source == unitSource) {
|
| + return partUnit;
|
| + }
|
| + }
|
| + }
|
| + return null;
|
| + }
|
| +
|
| + TimestampedData<String> getContents(Source source) {
|
| + String contents = _contentCache.getContents(source);
|
| + if (contents != null) {
|
| + return new TimestampedData<String>(_contentCache.getModificationStamp(source), contents);
|
| + }
|
| + return source.contents;
|
| + }
|
| +
|
| + void getContents2(Source source, Source_ContentReceiver receiver) {
|
| + String contents = _contentCache.getContents(source);
|
| + if (contents != null) {
|
| + receiver.accept(contents, _contentCache.getModificationStamp(source));
|
| + return;
|
| + }
|
| + source.getContentsToReceiver(receiver);
|
| + }
|
| +
|
| Element getElement(ElementLocation location) {
|
| // TODO(brianwilkerson) This should not be a "get" method.
|
| try {
|
| @@ -3848,6 +4116,14 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| return null;
|
| }
|
|
|
| + int getModificationStamp(Source source) {
|
| + int stamp = _contentCache.getModificationStamp(source);
|
| + if (stamp != null) {
|
| + return stamp;
|
| + }
|
| + return source.modificationStamp;
|
| + }
|
| +
|
| Namespace getPublicNamespace(LibraryElement library) {
|
| // TODO(brianwilkerson) Rename this to not start with 'get'. Note that this is not part of the
|
| // API of the interface.
|
| @@ -3981,32 +4257,41 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| AnalysisContentStatisticsImpl statistics = new AnalysisContentStatisticsImpl();
|
| {
|
| for (MapEntry<Source, SourceEntry> mapEntry in _cache.entrySet()) {
|
| + statistics.addSource(mapEntry.getKey());
|
| SourceEntry entry = mapEntry.getValue();
|
| if (entry is DartEntry) {
|
| Source source = mapEntry.getKey();
|
| DartEntry dartEntry = entry;
|
| SourceKind kind = dartEntry.getValue(DartEntry.SOURCE_KIND);
|
| // get library independent values
|
| - statistics.putCacheItem(dartEntry, DartEntry.PARSE_ERRORS);
|
| - statistics.putCacheItem(dartEntry, DartEntry.PARSED_UNIT);
|
| - statistics.putCacheItem(dartEntry, DartEntry.SOURCE_KIND);
|
| - statistics.putCacheItem(dartEntry, SourceEntry.LINE_INFO);
|
| + statistics.putCacheItem2(dartEntry, SourceEntry.LINE_INFO);
|
| + statistics.putCacheItem2(dartEntry, DartEntry.PARSE_ERRORS);
|
| + statistics.putCacheItem2(dartEntry, DartEntry.PARSED_UNIT);
|
| + statistics.putCacheItem2(dartEntry, DartEntry.SOURCE_KIND);
|
| 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);
|
| + statistics.putCacheItem2(dartEntry, DartEntry.ELEMENT);
|
| + statistics.putCacheItem2(dartEntry, DartEntry.EXPORTED_LIBRARIES);
|
| + statistics.putCacheItem2(dartEntry, DartEntry.IMPORTED_LIBRARIES);
|
| + statistics.putCacheItem2(dartEntry, DartEntry.INCLUDED_PARTS);
|
| + statistics.putCacheItem2(dartEntry, DartEntry.IS_CLIENT);
|
| + statistics.putCacheItem2(dartEntry, DartEntry.IS_LAUNCHABLE);
|
| }
|
| // get library-specific values
|
| List<Source> librarySources = getLibrariesContaining(source);
|
| for (Source librarySource in librarySources) {
|
| - statistics.putCacheItem2(dartEntry, librarySource, DartEntry.HINTS);
|
| - statistics.putCacheItem2(dartEntry, librarySource, DartEntry.RESOLUTION_ERRORS);
|
| - statistics.putCacheItem2(dartEntry, librarySource, DartEntry.RESOLVED_UNIT);
|
| - statistics.putCacheItem2(dartEntry, librarySource, DartEntry.VERIFICATION_ERRORS);
|
| + statistics.putCacheItem(dartEntry, librarySource, DartEntry.HINTS);
|
| + statistics.putCacheItem(dartEntry, librarySource, DartEntry.RESOLUTION_ERRORS);
|
| + statistics.putCacheItem(dartEntry, librarySource, DartEntry.RESOLVED_UNIT);
|
| + statistics.putCacheItem(dartEntry, librarySource, DartEntry.VERIFICATION_ERRORS);
|
| }
|
| + } else if (entry is HtmlEntry) {
|
| + HtmlEntry htmlEntry = entry;
|
| + statistics.putCacheItem2(htmlEntry, SourceEntry.LINE_INFO);
|
| + statistics.putCacheItem2(htmlEntry, HtmlEntry.PARSE_ERRORS);
|
| + statistics.putCacheItem2(htmlEntry, HtmlEntry.PARSED_UNIT);
|
| + statistics.putCacheItem2(htmlEntry, HtmlEntry.RESOLUTION_ERRORS);
|
| + statistics.putCacheItem2(htmlEntry, HtmlEntry.RESOLVED_UNIT);
|
| + statistics.putCacheItem2(htmlEntry, HtmlEntry.HINTS);
|
| }
|
| }
|
| }
|
| @@ -4018,6 +4303,19 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| return new TypeProviderImpl(computeLibraryElement(coreSource));
|
| }
|
|
|
| + TimestampedData<CompilationUnit> internalParseCompilationUnit(Source source) {
|
| + DartEntry dartEntry = getReadableDartEntry(source);
|
| + if (dartEntry == null) {
|
| + throw new AnalysisException.con1("internalParseCompilationUnit invoked for non-Dart file: ${source.fullName}");
|
| + }
|
| + dartEntry = cacheDartParseData(source, dartEntry, DartEntry.PARSED_UNIT);
|
| + CompilationUnit unit = dartEntry.anyParsedCompilationUnit;
|
| + if (unit == null) {
|
| + throw new AnalysisException.con2("internalParseCompilationUnit could not cache a parsed unit: ${source.fullName}", dartEntry.exception);
|
| + }
|
| + return new TimestampedData<CompilationUnit>(dartEntry.modificationTime, unit);
|
| + }
|
| +
|
| TimestampedData<CompilationUnit> internalResolveCompilationUnit(Source unitSource, LibraryElement libraryElement) {
|
| DartEntry dartEntry = getReadableDartEntry(unitSource);
|
| if (dartEntry == null) {
|
| @@ -4028,6 +4326,15 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| return new TimestampedData<CompilationUnit>(dartEntry.modificationTime, dartEntry.getValue2(DartEntry.RESOLVED_UNIT, librarySource));
|
| }
|
|
|
| + TimestampedData<Token> internalScanTokenStream(Source source) {
|
| + DartEntry dartEntry = getReadableDartEntry(source);
|
| + if (dartEntry == null) {
|
| + throw new AnalysisException.con1("internalScanTokenStream invoked for non-Dart file: ${source.fullName}");
|
| + }
|
| + dartEntry = cacheDartScanData(source, dartEntry, DartEntry.TOKEN_STREAM);
|
| + return new TimestampedData<Token>(dartEntry.modificationTime, dartEntry.getValue(DartEntry.TOKEN_STREAM));
|
| + }
|
| +
|
| bool isClientLibrary(Source librarySource) {
|
| SourceEntry sourceEntry = getReadableSourceEntry(librarySource);
|
| if (sourceEntry is DartEntry) {
|
| @@ -4090,6 +4397,8 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| int performStart = JavaSystem.currentTimeMillis();
|
| try {
|
| task.perform(_resultRecorder);
|
| + } on ObsoleteSourceAnalysisException catch (exception) {
|
| + AnalysisEngine.instance.logger.logInformation3("Could not perform analysis task: ${taskDescriptor}", exception);
|
| } on AnalysisException catch (exception) {
|
| if (exception.cause is! JavaIOException) {
|
| AnalysisEngine.instance.logger.logError2("Internal error while performing the task: ${task}", exception);
|
| @@ -4189,7 +4498,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| void setChangedContents(Source source, String contents, int offset, int oldLength, int newLength) {
|
| {
|
| _recentTasks.clear();
|
| - String originalContents = _sourceFactory.setContents(source, contents);
|
| + String originalContents = _contentCache.setContents(source, contents);
|
| if (contents != null) {
|
| if (contents != originalContents) {
|
| if (_options.incremental) {
|
| @@ -4207,7 +4516,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| void setContents(Source source, String contents) {
|
| {
|
| _recentTasks.clear();
|
| - String originalContents = _sourceFactory.setContents(source, contents);
|
| + String originalContents = _contentCache.setContents(source, contents);
|
| if (contents != null) {
|
| if (contents != originalContents) {
|
| _incrementalAnalysisCache = IncrementalAnalysisCache.clear(_incrementalAnalysisCache, source);
|
| @@ -4236,16 +4545,6 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
| }
|
|
|
| - 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 librarySources;
|
| - }
|
| -
|
| /**
|
| * 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.
|
| @@ -4294,7 +4593,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| List<AnalysisError> errors = errorListener.getErrors2(source);
|
| LineInfo lineInfo = getLineInfo(source);
|
| DartEntry dartEntry = _cache.get(source) as DartEntry;
|
| - int sourceTime = source.modificationStamp;
|
| + int sourceTime = getModificationStamp(source);
|
| if (dartEntry.modificationTime != sourceTime) {
|
| // The source has changed without the context being notified. Simulate notification.
|
| sourceChanged(source);
|
| @@ -4338,7 +4637,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| DartEntry dartEntry = getReadableDartEntry(source);
|
| if (dartEntry != null) {
|
| int resultTime = library.getModificationTime(source);
|
| - writer.println(" ${debuggingString(source)}; sourceTime = ${source.modificationStamp}, resultTime = ${resultTime}, cacheTime = ${dartEntry.modificationTime}");
|
| + writer.println(" ${debuggingString(source)}; sourceTime = ${getModificationStamp(source)}, resultTime = ${resultTime}, cacheTime = ${dartEntry.modificationTime}");
|
| DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| if (thrownException == null || resultTime >= 0) {
|
| //
|
| @@ -4361,7 +4660,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| unitEntry = dartCopy;
|
| }
|
| } else {
|
| - writer.println(" ${debuggingString(source)}; sourceTime = ${source.modificationStamp}, no entry");
|
| + writer.println(" ${debuggingString(source)}; sourceTime = ${getModificationStamp(source)}, no entry");
|
| }
|
| }
|
| }
|
| @@ -4429,7 +4728,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| // source didn't represent a Dart file, but check to be safe.
|
| throw new AnalysisException.con1("Internal error: attempting to resolve non-Dart file as a Dart file: ${source.fullName}");
|
| }
|
| - int sourceTime = source.modificationStamp;
|
| + int sourceTime = getModificationStamp(source);
|
| int resultTime = library.getModificationTime(source);
|
| if (sourceTime != resultTime) {
|
| // The source has changed without the context being notified. Simulate notification.
|
| @@ -4508,8 +4807,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * @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
|
| + * @throws AnalysisException if data could not be returned because the source could not be parsed
|
| */
|
| DartEntry cacheDartParseData(Source source, DartEntry dartEntry, DataDescriptor descriptor) {
|
| if (identical(descriptor, DartEntry.PARSED_UNIT)) {
|
| @@ -4565,17 +4863,53 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
|
|
| /**
|
| - * Given a source for a Dart file and the library that contains it, return a cache entry in which
|
| - * the state of the data represented by the given descriptor is either [CacheState#VALID] or
|
| - * [CacheState#ERROR]. This method assumes that the data can be produced by verifying the
|
| - * source in the given library if the data is not already cached.
|
| + * Given a source for a Dart file, return a cache entry in which the state of the data represented
|
| + * by the given descriptor is either [CacheState#VALID] or [CacheState#ERROR]. This
|
| + * method assumes that the data can be produced by scanning the source 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 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 parsed
|
| + * @throws AnalysisException if data could not be returned because the source could not be scanned
|
| + */
|
| + DartEntry cacheDartScanData(Source source, DartEntry dartEntry, DataDescriptor descriptor) {
|
| + //
|
| + // Check to see whether we already have the information being requested.
|
| + //
|
| + CacheState state = dartEntry.getState(descriptor);
|
| + while (state != CacheState.ERROR && state != CacheState.VALID) {
|
| + //
|
| + // If not, compute the information. Unless the modification date of the source continues to
|
| + // change, this loop will eventually terminate.
|
| + //
|
| + // TODO(brianwilkerson) Convert this to get the contents from the cache. (I'm not sure how
|
| + // that would work in an asynchronous environment.)
|
| + try {
|
| + dartEntry = new ScanDartTask(this, source, getContents(source)).perform(_resultRecorder) as DartEntry;
|
| + } on AnalysisException catch (exception) {
|
| + throw exception;
|
| + } on JavaException catch (exception) {
|
| + throw new AnalysisException.con3(exception);
|
| + }
|
| + state = dartEntry.getState(descriptor);
|
| + }
|
| + return dartEntry;
|
| + }
|
| +
|
| + /**
|
| + * Given a source for a Dart file and the library that contains it, return a cache entry in which
|
| + * the state of the data represented by the given descriptor is either [CacheState#VALID] or
|
| + * [CacheState#ERROR]. This method assumes that the data can be produced by verifying the
|
| + * source in the given library if the data 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 cacheDartVerificationData(Source unitSource, Source librarySource, DartEntry dartEntry, DataDescriptor descriptor) {
|
| //
|
| @@ -4712,12 +5046,12 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| String name = source.shortName;
|
| if (AnalysisEngine.isHtmlFileName(name)) {
|
| HtmlEntryImpl htmlEntry = new HtmlEntryImpl();
|
| - htmlEntry.modificationTime = source.modificationStamp;
|
| + htmlEntry.modificationTime = getModificationStamp(source);
|
| _cache.put(source, htmlEntry);
|
| return htmlEntry;
|
| } else {
|
| DartEntryImpl dartEntry = new DartEntryImpl();
|
| - dartEntry.modificationTime = source.modificationStamp;
|
| + dartEntry.modificationTime = getModificationStamp(source);
|
| _cache.put(source, dartEntry);
|
| return dartEntry;
|
| }
|
| @@ -4730,7 +5064,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * @param source the source for which a debugging string is to be produced
|
| * @return debugging information about the given source
|
| */
|
| - String debuggingString(Source source) => "'${source.fullName}' [${source.modificationStamp}]";
|
| + String debuggingString(Source source) => "'${source.fullName}' [${getModificationStamp(source)}]";
|
|
|
| /**
|
| * Return an array containing all of the change notices that are waiting to be returned. If there
|
| @@ -4787,7 +5121,12 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| if (dartEntry == null) {
|
| return defaultValue;
|
| }
|
| - return getDartDependencyData(source, dartEntry, descriptor);
|
| + try {
|
| + return getDartDependencyData(source, dartEntry, descriptor);
|
| + } on ObsoleteSourceAnalysisException catch (exception) {
|
| + AnalysisEngine.instance.logger.logInformation3("Could not compute ${descriptor.toString()}", exception);
|
| + return defaultValue;
|
| + }
|
| }
|
|
|
| /**
|
| @@ -4847,7 +5186,12 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| if (dartEntry == null) {
|
| return defaultValue;
|
| }
|
| - return getDartParseData(source, dartEntry, descriptor);
|
| + try {
|
| + return getDartParseData(source, dartEntry, descriptor);
|
| + } on ObsoleteSourceAnalysisException catch (exception) {
|
| + AnalysisEngine.instance.logger.logInformation3("Could not compute ${descriptor.toString()}", exception);
|
| + return defaultValue;
|
| + }
|
| }
|
|
|
| /**
|
| @@ -4892,7 +5236,53 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| if (dartEntry == null) {
|
| return defaultValue;
|
| }
|
| - return getDartResolutionData(unitSource, librarySource, dartEntry, descriptor);
|
| + try {
|
| + return getDartResolutionData(unitSource, librarySource, dartEntry, descriptor);
|
| + } on ObsoleteSourceAnalysisException catch (exception) {
|
| + AnalysisEngine.instance.logger.logInformation3("Could not compute ${descriptor.toString()}", exception);
|
| + return defaultValue;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * 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 scanning 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 scanned
|
| + */
|
| + Object getDartScanData(Source source, DartEntry dartEntry, DataDescriptor descriptor) {
|
| + dartEntry = cacheDartScanData(source, dartEntry, descriptor);
|
| + return dartEntry.getValue(descriptor);
|
| + }
|
| +
|
| + /**
|
| + * 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 scanning 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 scanned
|
| + */
|
| + Object getDartScanData2(Source source, DataDescriptor descriptor, Object defaultValue) {
|
| + DartEntry dartEntry = getReadableDartEntry(source);
|
| + if (dartEntry == null) {
|
| + return defaultValue;
|
| + }
|
| + try {
|
| + return getDartScanData(source, dartEntry, descriptor);
|
| + } on ObsoleteSourceAnalysisException catch (exception) {
|
| + AnalysisEngine.instance.logger.logInformation3("Could not compute ${descriptor.toString()}", exception);
|
| + return defaultValue;
|
| + }
|
| }
|
|
|
| /**
|
| @@ -4955,7 +5345,12 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| if (htmlEntry == null) {
|
| return defaultValue;
|
| }
|
| - return getHtmlResolutionData2(source, htmlEntry, descriptor);
|
| + try {
|
| + return getHtmlResolutionData2(source, htmlEntry, descriptor);
|
| + } on ObsoleteSourceAnalysisException catch (exception) {
|
| + AnalysisEngine.instance.logger.logInformation3("Could not compute ${descriptor.toString()}", exception);
|
| + return defaultValue;
|
| + }
|
| }
|
|
|
| /**
|
| @@ -4987,6 +5382,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| AnalysisTask get nextAnalysisTask {
|
| {
|
| bool hintsEnabled = _options.hint;
|
| + bool sdkErrorsEnabled = _options.generateSdkErrors;
|
| //
|
| // Look for incremental analysis
|
| //
|
| @@ -4999,7 +5395,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| // Look for a priority source that needs to be analyzed.
|
| //
|
| for (Source source in _priorityOrder) {
|
| - AnalysisTask task = getNextAnalysisTask2(source, _cache.get(source), true, hintsEnabled);
|
| + AnalysisTask task = getNextAnalysisTask2(source, _cache.get(source), true, hintsEnabled, sdkErrorsEnabled);
|
| if (task != null) {
|
| return task;
|
| }
|
| @@ -5009,7 +5405,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| //
|
| Source source = _workManager.nextSource;
|
| while (source != null) {
|
| - AnalysisTask task = getNextAnalysisTask2(source, _cache.get(source), false, hintsEnabled);
|
| + AnalysisTask task = getNextAnalysisTask2(source, _cache.get(source), false, hintsEnabled, sdkErrorsEnabled);
|
| if (task != null) {
|
| return task;
|
| }
|
| @@ -5042,11 +5438,29 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * @param sourceEntry the cache entry associated with the source
|
| * @param isPriority `true` if the source is a priority source
|
| * @param hintsEnabled `true` if hints are currently enabled
|
| + * @param sdkErrorsEnabled `true` if errors, warnings and hints should be generated for
|
| + * sources in the SDK
|
| * @return the next task that needs to be performed for the given source
|
| */
|
| - AnalysisTask getNextAnalysisTask2(Source source, SourceEntry sourceEntry, bool isPriority, bool hintsEnabled) {
|
| + AnalysisTask getNextAnalysisTask2(Source source, SourceEntry sourceEntry, bool isPriority, bool hintsEnabled, bool sdkErrorsEnabled) {
|
| if (sourceEntry is DartEntry) {
|
| DartEntry dartEntry = sourceEntry;
|
| + CacheState scanErrorsState = dartEntry.getState(DartEntry.SCAN_ERRORS);
|
| + if (identical(scanErrorsState, CacheState.INVALID) || (isPriority && identical(scanErrorsState, CacheState.FLUSHED))) {
|
| + // TODO(brianwilkerson) Convert this to get the contents from the cache or to asynchronously
|
| + // request the contents if they are not in the cache.
|
| + try {
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.setState(DartEntry.SCAN_ERRORS, CacheState.IN_PROCESS);
|
| + _cache.put(source, dartCopy);
|
| + return new ScanDartTask(this, source, getContents(source));
|
| + } on JavaException catch (exception) {
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.recordScanError();
|
| + dartCopy.exception = new AnalysisException.con3(exception);
|
| + _cache.put(source, dartCopy);
|
| + }
|
| + }
|
| CacheState parseErrorsState = dartEntry.getState(DartEntry.PARSE_ERRORS);
|
| if (identical(parseErrorsState, CacheState.INVALID) || (isPriority && identical(parseErrorsState, CacheState.FLUSHED))) {
|
| DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| @@ -5096,25 +5510,27 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| //return new ResolveDartUnitTask(this, source, libraryElement);
|
| return new ResolveDartLibraryTask(this, source, librarySource);
|
| }
|
| - CacheState verificationErrorsState = dartEntry.getState2(DartEntry.VERIFICATION_ERRORS, librarySource);
|
| - if (identical(verificationErrorsState, CacheState.INVALID) || (isPriority && identical(verificationErrorsState, CacheState.FLUSHED))) {
|
| - LibraryElement libraryElement = libraryEntry.getValue(DartEntry.ELEMENT);
|
| - if (libraryElement != null) {
|
| - DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| - dartCopy.setState2(DartEntry.VERIFICATION_ERRORS, librarySource, CacheState.IN_PROCESS);
|
| - _cache.put(source, dartCopy);
|
| - return new GenerateDartErrorsTask(this, source, libraryElement);
|
| - }
|
| - }
|
| - if (hintsEnabled) {
|
| - CacheState hintsState = dartEntry.getState2(DartEntry.HINTS, librarySource);
|
| - if (identical(hintsState, CacheState.INVALID) || (isPriority && identical(hintsState, CacheState.FLUSHED))) {
|
| + if (sdkErrorsEnabled || !source.isInSystemLibrary) {
|
| + CacheState verificationErrorsState = dartEntry.getState2(DartEntry.VERIFICATION_ERRORS, librarySource);
|
| + if (identical(verificationErrorsState, CacheState.INVALID) || (isPriority && identical(verificationErrorsState, CacheState.FLUSHED))) {
|
| LibraryElement libraryElement = libraryEntry.getValue(DartEntry.ELEMENT);
|
| if (libraryElement != null) {
|
| DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| - dartCopy.setState2(DartEntry.HINTS, librarySource, CacheState.IN_PROCESS);
|
| + dartCopy.setState2(DartEntry.VERIFICATION_ERRORS, librarySource, CacheState.IN_PROCESS);
|
| _cache.put(source, dartCopy);
|
| - return new GenerateDartHintsTask(this, libraryElement);
|
| + return new GenerateDartErrorsTask(this, source, libraryElement);
|
| + }
|
| + }
|
| + if (hintsEnabled) {
|
| + CacheState hintsState = dartEntry.getState2(DartEntry.HINTS, librarySource);
|
| + if (identical(hintsState, CacheState.INVALID) || (isPriority && identical(hintsState, CacheState.FLUSHED))) {
|
| + LibraryElement libraryElement = libraryEntry.getValue(DartEntry.ELEMENT);
|
| + if (libraryElement != null) {
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.setState2(DartEntry.HINTS, librarySource, CacheState.IN_PROCESS);
|
| + _cache.put(source, dartCopy);
|
| + return new GenerateDartHintsTask(this, libraryElement);
|
| + }
|
| }
|
| }
|
| }
|
| @@ -5145,29 +5561,26 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| _cache.put(source, htmlCopy);
|
| return new ResolveHtmlTask(this, source);
|
| }
|
| + // Angular support
|
| if (_options.analyzeAngular) {
|
| + // try to resolve as an Angular entry point
|
| + CacheState angularEntryState = htmlEntry.getState(HtmlEntry.ANGULAR_ENTRY);
|
| + if (identical(angularEntryState, CacheState.INVALID)) {
|
| + HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| + htmlCopy.setState(HtmlEntry.ANGULAR_ENTRY, CacheState.IN_PROCESS);
|
| + _cache.put(source, htmlCopy);
|
| + return new ResolveAngularEntryHtmlTask(this, source);
|
| + }
|
| + // try to resolve as an Angular application part
|
| CacheState angularErrorsState = htmlEntry.getState(HtmlEntry.ANGULAR_ERRORS);
|
| if (identical(angularErrorsState, CacheState.INVALID)) {
|
| - AngularApplicationInfo entryInfo = htmlEntry.getValue(HtmlEntry.ANGULAR_ENTRY);
|
| - if (entryInfo != null) {
|
| - HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| - htmlCopy.setState(HtmlEntry.ANGULAR_ERRORS, CacheState.IN_PROCESS);
|
| - _cache.put(source, htmlCopy);
|
| - return new ResolveAngularEntryHtmlTask(this, source, entryInfo);
|
| - }
|
| - AngularApplicationInfo applicationInfo = htmlEntry.getValue(HtmlEntry.ANGULAR_APPLICATION);
|
| - if (applicationInfo != null) {
|
| - AngularComponentElement component = htmlEntry.getValue(HtmlEntry.ANGULAR_COMPONENT);
|
| - if (component != null) {
|
| - HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| - htmlCopy.setState(HtmlEntry.ANGULAR_ERRORS, CacheState.IN_PROCESS);
|
| - _cache.put(source, htmlCopy);
|
| - return new ResolveAngularComponentTemplateTask(this, source, component, applicationInfo);
|
| - }
|
| - }
|
| + AngularApplication application = htmlEntry.getValue(HtmlEntry.ANGULAR_APPLICATION);
|
| + // try to resolve as an Angular template
|
| + AngularComponentElement component = htmlEntry.getValue(HtmlEntry.ANGULAR_COMPONENT);
|
| HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| - htmlCopy.setValue(HtmlEntry.ANGULAR_ERRORS, AnalysisError.NO_ERRORS);
|
| + htmlCopy.setState(HtmlEntry.ANGULAR_ERRORS, CacheState.IN_PROCESS);
|
| _cache.put(source, htmlCopy);
|
| + return new ResolveAngularComponentTemplateTask(this, source, component, application);
|
| }
|
| }
|
| }
|
| @@ -5282,6 +5695,11 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| void getSourcesNeedingProcessing2(Source source, SourceEntry sourceEntry, bool isPriority, bool hintsEnabled, Set<Source> sources) {
|
| if (sourceEntry is DartEntry) {
|
| DartEntry dartEntry = sourceEntry;
|
| + CacheState scanErrorsState = dartEntry.getState(DartEntry.SCAN_ERRORS);
|
| + if (identical(scanErrorsState, CacheState.INVALID) || (isPriority && identical(scanErrorsState, CacheState.FLUSHED))) {
|
| + sources.add(source);
|
| + return;
|
| + }
|
| CacheState parseErrorsState = dartEntry.getState(DartEntry.PARSE_ERRORS);
|
| if (identical(parseErrorsState, CacheState.INVALID) || (isPriority && identical(parseErrorsState, CacheState.FLUSHED))) {
|
| sources.add(source);
|
| @@ -5342,15 +5760,16 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| sources.add(source);
|
| return;
|
| }
|
| + // Angular
|
| if (_options.analyzeAngular) {
|
| CacheState angularErrorsState = htmlEntry.getState(HtmlEntry.ANGULAR_ERRORS);
|
| if (identical(angularErrorsState, CacheState.INVALID)) {
|
| - AngularApplicationInfo entryInfo = htmlEntry.getValue(HtmlEntry.ANGULAR_ENTRY);
|
| + AngularApplication entryInfo = htmlEntry.getValue(HtmlEntry.ANGULAR_ENTRY);
|
| if (entryInfo != null) {
|
| sources.add(source);
|
| return;
|
| }
|
| - AngularApplicationInfo applicationInfo = htmlEntry.getValue(HtmlEntry.ANGULAR_APPLICATION);
|
| + AngularApplication applicationInfo = htmlEntry.getValue(HtmlEntry.ANGULAR_APPLICATION);
|
| if (applicationInfo != null) {
|
| AngularComponentElement component = htmlEntry.getValue(HtmlEntry.ANGULAR_COMPONENT);
|
| if (component != null) {
|
| @@ -5388,6 +5807,55 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
|
|
| /**
|
| + * In response to a change to Angular entry point [HtmlElement], invalidate any results that
|
| + * depend on it.
|
| + *
|
| + * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
|
| + *
|
| + * <b>Note:</b> Any cache entries that were accessed before this method was invoked must be
|
| + * re-accessed after this method returns.
|
| + *
|
| + * @param entryCopy the [HtmlEntryImpl] of the (maybe) Angular entry point being invalidated
|
| + */
|
| + void invalidateAngularResolution(HtmlEntryImpl entryCopy) {
|
| + AngularApplication application = entryCopy.getValue(HtmlEntry.ANGULAR_ENTRY);
|
| + if (application == null) {
|
| + return;
|
| + }
|
| + _angularApplications.remove(application);
|
| + // invalidate Entry
|
| + entryCopy.setState(HtmlEntry.ANGULAR_ENTRY, CacheState.INVALID);
|
| + // reset HTML sources
|
| + List<AngularElement> oldAngularElements = application.elements;
|
| + for (AngularElement angularElement in oldAngularElements) {
|
| + if (angularElement is AngularHasTemplateElement) {
|
| + AngularHasTemplateElement hasTemplate = angularElement;
|
| + Source templateSource = hasTemplate.templateSource;
|
| + if (templateSource != null) {
|
| + HtmlEntry htmlEntry = getReadableHtmlEntry(templateSource);
|
| + HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| + htmlCopy.setValue(HtmlEntry.ANGULAR_APPLICATION, null);
|
| + htmlCopy.setValue(HtmlEntry.ANGULAR_COMPONENT, null);
|
| + htmlCopy.setState(HtmlEntry.ANGULAR_ERRORS, CacheState.INVALID);
|
| + _cache.put(templateSource, htmlCopy);
|
| + _workManager.add(templateSource, SourcePriority.HTML);
|
| + }
|
| + }
|
| + }
|
| + // reset Dart sources
|
| + List<Source> oldElementSources = application.elementSources;
|
| + for (Source elementSource in oldElementSources) {
|
| + DartEntry dartEntry = getReadableDartEntry(elementSource);
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.setValue(DartEntry.ANGULAR_ERRORS, AnalysisError.NO_ERRORS);
|
| + _cache.put(elementSource, dartCopy);
|
| + // notify about (disappeared) Angular errors
|
| + ChangeNoticeImpl notice = getNotice(elementSource);
|
| + notice.setErrors(dartCopy.allErrors, dartEntry.getValue(SourceEntry.LINE_INFO));
|
| + }
|
| + }
|
| +
|
| + /**
|
| * 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.
|
| *
|
| @@ -5431,6 +5899,18 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
| }
|
| }
|
| + // invalidate Angular applications
|
| + List<AngularApplication> angularApplicationsCopy = [];
|
| + for (AngularApplication application in angularApplicationsCopy) {
|
| + if (application.dependsOn(librarySource)) {
|
| + Source entryPointSource = application.entryPoint;
|
| + HtmlEntry entry = getReadableHtmlEntry(entryPointSource);
|
| + HtmlEntryImpl entryCopy = entry.writableCopy;
|
| + invalidateAngularResolution(entryCopy);
|
| + _cache.put(entryPointSource, entryCopy);
|
| + _workManager.add(entryPointSource, SourcePriority.HTML);
|
| + }
|
| + }
|
| }
|
|
|
| /**
|
| @@ -5486,59 +5966,49 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
|
|
| /**
|
| - * Updates [HtmlEntry]s that correspond to the previously known and new Angular components.
|
| - *
|
| - * @param library the [Library] that was resolved
|
| - * @param dartCopy the [DartEntryImpl] to record new Angular components
|
| + * Updates [HtmlEntry]s that correspond to the previously known and new Angular application
|
| + * information.
|
| */
|
| - void recordAngularComponents(HtmlEntryImpl entry, AngularApplicationInfo app) {
|
| - if (!_options.analyzeAngular) {
|
| - return;
|
| - }
|
| - // reset old Angular errors
|
| - AngularApplicationInfo oldApp = entry.getValue(HtmlEntry.ANGULAR_ENTRY);
|
| - if (oldApp != null) {
|
| - List<AngularElement> oldAngularElements = oldApp.elements;
|
| - for (AngularElement angularElement in oldAngularElements) {
|
| - if (angularElement is AngularComponentElement) {
|
| - AngularComponentElement component = angularElement;
|
| - Source templateSource = component.templateSource;
|
| - if (templateSource != null) {
|
| - HtmlEntry htmlEntry = getReadableHtmlEntry(templateSource);
|
| - HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| - htmlCopy.setValue(HtmlEntry.ANGULAR_APPLICATION, null);
|
| - htmlCopy.setValue(HtmlEntry.ANGULAR_COMPONENT, null);
|
| - htmlCopy.setValue(HtmlEntry.ANGULAR_ERRORS, AnalysisError.NO_ERRORS);
|
| - _cache.put(templateSource, htmlCopy);
|
| - // notify about (disappeared) HTML errors
|
| - ChangeNoticeImpl notice = getNotice(templateSource);
|
| - notice.setErrors(htmlCopy.allErrors, computeLineInfo(templateSource));
|
| - }
|
| - }
|
| - }
|
| - }
|
| - // prepare for new Angular analysis
|
| - if (app != null) {
|
| - List<AngularElement> newAngularElements = app.elements;
|
| + void recordAngularEntryPoint(HtmlEntryImpl entry, ResolveAngularEntryHtmlTask task) {
|
| + AngularApplication application = task.application;
|
| + if (application != null) {
|
| + _angularApplications.add(application);
|
| + // if this is an entry point, then we already resolved it
|
| + entry.setValue(HtmlEntry.ANGULAR_ERRORS, task.entryErrors);
|
| + // schedule HTML templates analysis
|
| + List<AngularElement> newAngularElements = application.elements;
|
| for (AngularElement angularElement in newAngularElements) {
|
| - if (angularElement is AngularComponentElement) {
|
| - AngularComponentElement component = angularElement;
|
| - Source templateSource = component.templateSource;
|
| + if (angularElement is AngularHasTemplateElement) {
|
| + AngularHasTemplateElement hasTemplate = angularElement;
|
| + Source templateSource = hasTemplate.templateSource;
|
| if (templateSource != null) {
|
| HtmlEntry htmlEntry = getReadableHtmlEntry(templateSource);
|
| HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| - htmlCopy.setValue(HtmlEntry.ANGULAR_APPLICATION, app);
|
| - htmlCopy.setValue(HtmlEntry.ANGULAR_COMPONENT, component);
|
| + htmlCopy.setValue(HtmlEntry.ANGULAR_APPLICATION, application);
|
| + if (hasTemplate is AngularComponentElement) {
|
| + AngularComponentElement component = hasTemplate;
|
| + htmlCopy.setValue(HtmlEntry.ANGULAR_COMPONENT, component);
|
| + }
|
| htmlCopy.setState(HtmlEntry.ANGULAR_ERRORS, CacheState.INVALID);
|
| _cache.put(templateSource, htmlCopy);
|
| _workManager.add(templateSource, SourcePriority.HTML);
|
| }
|
| }
|
| }
|
| + // update Dart sources errors
|
| + List<Source> newElementSources = application.elementSources;
|
| + for (Source elementSource in newElementSources) {
|
| + DartEntry dartEntry = getReadableDartEntry(elementSource);
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.setValue(DartEntry.ANGULAR_ERRORS, task.getErrors(elementSource));
|
| + _cache.put(elementSource, dartCopy);
|
| + // notify about Dart errors
|
| + ChangeNoticeImpl notice = getNotice(elementSource);
|
| + notice.setErrors(dartCopy.allErrors, computeLineInfo(elementSource));
|
| + }
|
| }
|
| - // remember Angular application
|
| - entry.setValue(HtmlEntry.ANGULAR_ENTRY, app);
|
| - entry.setState(HtmlEntry.ANGULAR_ERRORS, CacheState.INVALID);
|
| + // remember Angular entry point
|
| + entry.setValue(HtmlEntry.ANGULAR_ENTRY, application);
|
| }
|
|
|
| /**
|
| @@ -5591,13 +6061,15 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| DartEntry dartEntry = null;
|
| {
|
| SourceEntry sourceEntry = _cache.get(source);
|
| - if (sourceEntry is! DartEntry) {
|
| + if (sourceEntry == null) {
|
| + throw new ObsoleteSourceAnalysisException(source);
|
| + } else if (sourceEntry is! DartEntry) {
|
| // This shouldn't be possible because we should never have performed the task if the source
|
| // didn't represent a Dart file, but check to be safe.
|
| throw new AnalysisException.con1("Internal error: attempting to verify non-Dart file as a Dart file: ${source.fullName}");
|
| }
|
| dartEntry = sourceEntry as DartEntry;
|
| - int sourceTime = source.modificationStamp;
|
| + int sourceTime = getModificationStamp(source);
|
| int resultTime = task.modificationTime;
|
| if (sourceTime == resultTime) {
|
| if (dartEntry.modificationTime != sourceTime) {
|
| @@ -5670,7 +6142,9 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| // We don't have any information about which sources to mark as invalid other than the library
|
| // source.
|
| SourceEntry sourceEntry = _cache.get(librarySource);
|
| - if (sourceEntry is! DartEntry) {
|
| + if (sourceEntry == null) {
|
| + throw new ObsoleteSourceAnalysisException(librarySource);
|
| + } else if (sourceEntry is! DartEntry) {
|
| // This shouldn't be possible because we should never have performed the task if the source
|
| // didn't represent a Dart file, but check to be safe.
|
| throw new AnalysisException.con1("Internal error: attempting to generate hints for non-Dart file as a Dart file: ${librarySource.fullName}");
|
| @@ -5699,7 +6173,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| if (unitSource == librarySource) {
|
| libraryEntry = dartEntry;
|
| }
|
| - int sourceTime = unitSource.modificationStamp;
|
| + int sourceTime = getModificationStamp(unitSource);
|
| int resultTime = results.modificationTime;
|
| if (sourceTime == resultTime) {
|
| if (dartEntry.modificationTime != sourceTime) {
|
| @@ -5790,13 +6264,15 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| DartEntry dartEntry = null;
|
| {
|
| SourceEntry sourceEntry = _cache.get(source);
|
| - if (sourceEntry is! DartEntry) {
|
| + if (sourceEntry == null) {
|
| + throw new ObsoleteSourceAnalysisException(source);
|
| + } else if (sourceEntry is! DartEntry) {
|
| // This shouldn't be possible because we should never have performed the task if the source
|
| // didn't represent a Dart file, but check to be safe.
|
| throw new AnalysisException.con1("Internal error: attempting to parse non-Dart file as a Dart file: ${source.fullName}");
|
| }
|
| dartEntry = sourceEntry as DartEntry;
|
| - int sourceTime = source.modificationStamp;
|
| + int sourceTime = getModificationStamp(source);
|
| int resultTime = task.modificationTime;
|
| if (sourceTime == resultTime) {
|
| if (dartEntry.modificationTime != sourceTime) {
|
| @@ -5809,10 +6285,9 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
| 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);
|
| + dartCopy.removeContainingLibrary(source);
|
| _workManager.add(source, SourcePriority.NORMAL_PART);
|
| } else {
|
| dartCopy.setValue(DartEntry.SOURCE_KIND, SourceKind.LIBRARY);
|
| @@ -5823,7 +6298,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| dartCopy.setValue(DartEntry.PARSE_ERRORS, task.errors);
|
| _cache.storedAst(source);
|
| ChangeNoticeImpl notice = getNotice(source);
|
| - notice.setErrors(dartEntry.allErrors, lineInfo);
|
| + notice.setErrors(dartCopy.allErrors, dartCopy.getValue(SourceEntry.LINE_INFO));
|
| // Verify that the incrementally parsed and resolved unit in the incremental cache
|
| // is structurally equivalent to the fully parsed unit
|
| _incrementalAnalysisCache = IncrementalAnalysisCache.verifyStructure(_incrementalAnalysisCache, source, task.compilationUnit);
|
| @@ -5882,13 +6357,15 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| HtmlEntry htmlEntry = null;
|
| {
|
| SourceEntry sourceEntry = _cache.get(source);
|
| - if (sourceEntry is! HtmlEntry) {
|
| + if (sourceEntry == null) {
|
| + throw new ObsoleteSourceAnalysisException(source);
|
| + } else if (sourceEntry is! HtmlEntry) {
|
| // This shouldn't be possible because we should never have performed the task if the source
|
| // didn't represent an HTML file, but check to be safe.
|
| throw new AnalysisException.con1("Internal error: attempting to parse non-HTML file as a HTML file: ${source.fullName}");
|
| }
|
| htmlEntry = sourceEntry as HtmlEntry;
|
| - int sourceTime = source.modificationStamp;
|
| + int sourceTime = getModificationStamp(source);
|
| int resultTime = task.modificationTime;
|
| if (sourceTime == resultTime) {
|
| if (htmlEntry.modificationTime != sourceTime) {
|
| @@ -5909,7 +6386,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| htmlCopy.setValue(HtmlEntry.REFERENCED_LIBRARIES, task.referencedLibraries);
|
| _cache.storedAst(source);
|
| ChangeNoticeImpl notice = getNotice(source);
|
| - notice.setErrors(htmlEntry.allErrors, lineInfo);
|
| + notice.setErrors(htmlCopy.allErrors, lineInfo);
|
| } else {
|
| htmlCopy.recordParseError();
|
| _cache.removedAst(source);
|
| @@ -5972,13 +6449,15 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| HtmlEntry htmlEntry = null;
|
| {
|
| SourceEntry sourceEntry = _cache.get(source);
|
| - if (sourceEntry is! HtmlEntry) {
|
| + if (sourceEntry == null) {
|
| + throw new ObsoleteSourceAnalysisException(source);
|
| + } else if (sourceEntry is! HtmlEntry) {
|
| // This shouldn't be possible because we should never have performed the task if the source
|
| // didn't represent an HTML file, but check to be safe.
|
| throw new AnalysisException.con1("Internal error: attempting to resolve non-HTML file as an HTML file: ${source.fullName}");
|
| }
|
| htmlEntry = sourceEntry as HtmlEntry;
|
| - int sourceTime = source.modificationStamp;
|
| + int sourceTime = getModificationStamp(source);
|
| int resultTime = task.modificationTime;
|
| if (sourceTime == resultTime) {
|
| if (htmlEntry.modificationTime != sourceTime) {
|
| @@ -5992,6 +6471,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| if (thrownException == null) {
|
| htmlCopy.setValue(HtmlEntry.ANGULAR_ERRORS, task.resolutionErrors);
|
| + // notify about errors
|
| ChangeNoticeImpl notice = getNotice(source);
|
| notice.htmlUnit = task.resolvedUnit;
|
| notice.setErrors(htmlCopy.allErrors, htmlCopy.getValue(SourceEntry.LINE_INFO));
|
| @@ -6052,13 +6532,15 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| HtmlEntry htmlEntry = null;
|
| {
|
| SourceEntry sourceEntry = _cache.get(source);
|
| - if (sourceEntry is! HtmlEntry) {
|
| + if (sourceEntry == null) {
|
| + throw new ObsoleteSourceAnalysisException(source);
|
| + } else if (sourceEntry is! HtmlEntry) {
|
| // This shouldn't be possible because we should never have performed the task if the source
|
| // didn't represent an HTML file, but check to be safe.
|
| throw new AnalysisException.con1("Internal error: attempting to resolve non-HTML file as an HTML file: ${source.fullName}");
|
| }
|
| htmlEntry = sourceEntry as HtmlEntry;
|
| - int sourceTime = source.modificationStamp;
|
| + int sourceTime = getModificationStamp(source);
|
| int resultTime = task.modificationTime;
|
| if (sourceTime == resultTime) {
|
| if (htmlEntry.modificationTime != sourceTime) {
|
| @@ -6071,7 +6553,9 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
| HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
|
| if (thrownException == null) {
|
| - htmlCopy.setValue(HtmlEntry.ANGULAR_ERRORS, task.resolutionErrors);
|
| + htmlCopy.setValue(HtmlEntry.RESOLVED_UNIT, task.resolvedUnit);
|
| + recordAngularEntryPoint(htmlCopy, task);
|
| + _cache.storedAst(source);
|
| ChangeNoticeImpl notice = getNotice(source);
|
| notice.htmlUnit = task.resolvedUnit;
|
| notice.setErrors(htmlCopy.allErrors, htmlCopy.getValue(SourceEntry.LINE_INFO));
|
| @@ -6133,13 +6617,15 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| DartEntry dartEntry = null;
|
| {
|
| SourceEntry sourceEntry = _cache.get(source);
|
| - if (sourceEntry is! DartEntry) {
|
| + if (sourceEntry == null) {
|
| + throw new ObsoleteSourceAnalysisException(source);
|
| + } else if (sourceEntry is! DartEntry) {
|
| // This shouldn't be possible because we should never have performed the task if the source
|
| // didn't represent a Dart file, but check to be safe.
|
| throw new AnalysisException.con1("Internal error: attempting to resolve Dart dependencies in a non-Dart file: ${source.fullName}");
|
| }
|
| dartEntry = sourceEntry as DartEntry;
|
| - int sourceTime = source.modificationStamp;
|
| + int sourceTime = getModificationStamp(source);
|
| int resultTime = task.modificationTime;
|
| if (sourceTime == resultTime) {
|
| if (dartEntry.modificationTime != sourceTime) {
|
| @@ -6222,13 +6708,15 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| DartEntry dartEntry = null;
|
| {
|
| SourceEntry sourceEntry = _cache.get(unitSource);
|
| - if (sourceEntry is! DartEntry) {
|
| + if (sourceEntry == null) {
|
| + throw new ObsoleteSourceAnalysisException(unitSource);
|
| + } else if (sourceEntry is! DartEntry) {
|
| // This shouldn't be possible because we should never have performed the task if the source
|
| // didn't represent a Dart file, but check to be safe.
|
| throw new AnalysisException.con1("Internal error: attempting to resolve non-Dart file as a Dart file: ${unitSource.fullName}");
|
| }
|
| dartEntry = sourceEntry as DartEntry;
|
| - int sourceTime = unitSource.modificationStamp;
|
| + int sourceTime = getModificationStamp(unitSource);
|
| int resultTime = task.modificationTime;
|
| if (sourceTime == resultTime) {
|
| if (dartEntry.modificationTime != sourceTime) {
|
| @@ -6299,13 +6787,15 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| HtmlEntry htmlEntry = null;
|
| {
|
| SourceEntry sourceEntry = _cache.get(source);
|
| - if (sourceEntry is! HtmlEntry) {
|
| + if (sourceEntry == null) {
|
| + throw new ObsoleteSourceAnalysisException(source);
|
| + } else if (sourceEntry is! HtmlEntry) {
|
| // This shouldn't be possible because we should never have performed the task if the source
|
| // didn't represent an HTML file, but check to be safe.
|
| throw new AnalysisException.con1("Internal error: attempting to resolve non-HTML file as an HTML file: ${source.fullName}");
|
| }
|
| htmlEntry = sourceEntry as HtmlEntry;
|
| - int sourceTime = source.modificationStamp;
|
| + int sourceTime = getModificationStamp(source);
|
| int resultTime = task.modificationTime;
|
| if (sourceTime == resultTime) {
|
| if (htmlEntry.modificationTime != sourceTime) {
|
| @@ -6331,7 +6821,6 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| _cache.removedAst(source);
|
| }
|
| htmlCopy.exception = thrownException;
|
| - recordAngularComponents(htmlCopy, task.angularApplication);
|
| _cache.put(source, htmlCopy);
|
| htmlEntry = htmlCopy;
|
| } else {
|
| @@ -6371,6 +6860,90 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
|
|
| /**
|
| + * Record the results produced by performing a [ScanDartTask]. 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 recordScanDartTaskResults(ScanDartTask task) {
|
| + Source source = task.source;
|
| + AnalysisException thrownException = task.exception;
|
| + DartEntry dartEntry = null;
|
| + {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry == null) {
|
| + throw new ObsoleteSourceAnalysisException(source);
|
| + } else if (sourceEntry is! DartEntry) {
|
| + // This shouldn't be possible because we should never have performed the task if the source
|
| + // didn't represent a Dart file, but check to be safe.
|
| + throw new AnalysisException.con1("Internal error: attempting to parse non-Dart file as a Dart file: ${source.fullName}");
|
| + }
|
| + dartEntry = sourceEntry as DartEntry;
|
| + int sourceTime = getModificationStamp(source);
|
| + int resultTime = task.modificationTime;
|
| + if (sourceTime == resultTime) {
|
| + if (dartEntry.modificationTime != sourceTime) {
|
| + // The source has changed without the context being notified. Simulate notification.
|
| + 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);
|
| + dartCopy.setValue(DartEntry.TOKEN_STREAM, task.tokenStream);
|
| + dartCopy.setValue(DartEntry.SCAN_ERRORS, task.errors);
|
| + _cache.storedAst(source);
|
| + _workManager.add(source, SourcePriority.NORMAL_PART);
|
| + ChangeNoticeImpl notice = getNotice(source);
|
| + notice.setErrors(dartEntry.allErrors, lineInfo);
|
| + } else {
|
| + removeFromParts(source, dartEntry);
|
| + dartCopy.recordScanError();
|
| + _cache.removedAst(source);
|
| + }
|
| + dartCopy.exception = thrownException;
|
| + _cache.put(source, dartCopy);
|
| + dartEntry = dartCopy;
|
| + } else {
|
| + logInformation2("Scan results discarded for ${debuggingString(source)}; sourceTime = ${sourceTime}, resultTime = ${resultTime}, cacheTime = ${dartEntry.modificationTime}", thrownException);
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + if (thrownException == null || resultTime >= 0) {
|
| + //
|
| + // The analysis was performed on out-of-date sources. Mark the cache so that the sources
|
| + // will be re-analyzed using the up-to-date sources.
|
| + //
|
| + // dartCopy.recordScanNotInProcess();
|
| + removeFromParts(source, dartEntry);
|
| + dartCopy.invalidateAllInformation();
|
| + dartCopy.modificationTime = sourceTime;
|
| + _cache.removedAst(source);
|
| + _workManager.add(source, SourcePriority.UNKNOWN);
|
| + } else {
|
| + //
|
| + // We could not determine whether the sources were up-to-date or out-of-date. Mark the
|
| + // cache so that we won't attempt to re-analyze the sources until there's a good chance
|
| + // that we'll be able to do so without error.
|
| + //
|
| + dartCopy.recordScanError();
|
| + }
|
| + dartCopy.exception = thrownException;
|
| + _cache.put(source, dartCopy);
|
| + dartEntry = dartCopy;
|
| + }
|
| + }
|
| + if (thrownException != null) {
|
| + throw thrownException;
|
| + }
|
| + return dartEntry;
|
| + }
|
| +
|
| + /**
|
| * Remove the given library from the list of containing libraries for all of the parts referenced
|
| * by the given entry.
|
| *
|
| @@ -6427,7 +7000,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| } else {
|
| SourceEntryImpl sourceCopy = sourceEntry.writableCopy;
|
| int oldTime = sourceCopy.modificationTime;
|
| - sourceCopy.modificationTime = source.modificationStamp;
|
| + sourceCopy.modificationTime = getModificationStamp(source);
|
| // TODO(brianwilkerson) Understand why we're not invalidating the cache.
|
| _cache.put(source, sourceCopy);
|
| logInformation("Added new source: ${debuggingString(source)} (previously modified at ${oldTime})");
|
| @@ -6447,7 +7020,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| */
|
| void sourceChanged(Source source) {
|
| SourceEntry sourceEntry = _cache.get(source);
|
| - if (sourceEntry == null || sourceEntry.modificationTime == source.modificationStamp) {
|
| + if (sourceEntry == null || sourceEntry.modificationTime == getModificationStamp(source)) {
|
| // Either we have removed this source, in which case we don't care that it is changed, or we
|
| // have already invalidated the cache and don't need to invalidate it again.
|
| if (sourceEntry == null) {
|
| @@ -6460,7 +7033,8 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| if (sourceEntry is HtmlEntry) {
|
| HtmlEntryImpl htmlCopy = sourceEntry.writableCopy;
|
| int oldTime = htmlCopy.modificationTime;
|
| - htmlCopy.modificationTime = source.modificationStamp;
|
| + htmlCopy.modificationTime = getModificationStamp(source);
|
| + invalidateAngularResolution(htmlCopy);
|
| htmlCopy.invalidateAllInformation();
|
| _cache.put(source, htmlCopy);
|
| _cache.removedAst(source);
|
| @@ -6482,9 +7056,9 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| // for (Source library : containingLibraries) {
|
| invalidateLibraryResolution(library, writer);
|
| }
|
| - removeFromParts(source, sourceEntry);
|
| - DartEntryImpl dartCopy = sourceEntry.writableCopy;
|
| - dartCopy.modificationTime = source.modificationStamp;
|
| + removeFromParts(source, _cache.get(source) as DartEntry);
|
| + DartEntryImpl dartCopy = (_cache.get(source) as DartEntry).writableCopy;
|
| + dartCopy.modificationTime = getModificationStamp(source);
|
| dartCopy.invalidateAllInformation();
|
| _cache.put(source, dartCopy);
|
| _cache.removedAst(source);
|
| @@ -6502,7 +7076,10 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| PrintStringWriter writer = new PrintStringWriter();
|
| writer.println("Removed source: ${debuggingString(source)}");
|
| SourceEntry sourceEntry = _cache.get(source);
|
| - if (sourceEntry is DartEntry) {
|
| + if (sourceEntry is HtmlEntry) {
|
| + HtmlEntryImpl htmlCopy = sourceEntry.writableCopy;
|
| + invalidateAngularResolution(htmlCopy);
|
| + } else if (sourceEntry is DartEntry) {
|
| Set<Source> libraries = new Set<Source>();
|
| for (Source librarySource in getLibrariesContaining(source)) {
|
| libraries.add(librarySource);
|
| @@ -6537,13 +7114,13 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
|
| Source source = entry.getKey();
|
| SourceEntry sourceEntry = entry.getValue();
|
| - int sourceTime = source.modificationStamp;
|
| + int sourceTime = getModificationStamp(source);
|
| if (sourceTime != sourceEntry.modificationTime) {
|
| sourceChanged(source);
|
| inconsistentCount++;
|
| }
|
| if (sourceEntry.exception != null) {
|
| - if (!source.exists()) {
|
| + if (!exists(source)) {
|
| missingSources.add(source);
|
| }
|
| }
|
| @@ -6599,6 +7176,8 @@ class AnalysisContextImpl_AnalysisTaskResultRecorder implements AnalysisTaskVisi
|
| SourceEntry visitResolveDartUnitTask(ResolveDartUnitTask task) => AnalysisContextImpl_this.recordResolveDartUnitTaskResults(task);
|
|
|
| SourceEntry visitResolveHtmlTask(ResolveHtmlTask task) => AnalysisContextImpl_this.recordResolveHtmlTaskResults(task);
|
| +
|
| + SourceEntry visitScanDartTask(ScanDartTask task) => AnalysisContextImpl_this.recordScanDartTaskResults(task);
|
| }
|
|
|
| class AnalysisContextImpl_ContextRetentionPolicy implements CacheRetentionPolicy {
|
| @@ -6674,6 +7253,12 @@ class AnalysisOptionsImpl implements AnalysisOptions {
|
| bool dart2jsHint = true;
|
|
|
| /**
|
| + * A flag indicating whether errors, warnings and hints should be generated for sources in the
|
| + * SDK.
|
| + */
|
| + bool _generateSdkErrors = false;
|
| +
|
| + /**
|
| * A flag indicating whether analysis is to generate hint results (e.g. type inference based
|
| * information and pub best practices).
|
| */
|
| @@ -6690,7 +7275,7 @@ class AnalysisOptionsImpl implements AnalysisOptions {
|
| bool preserveComments = true;
|
|
|
| /**
|
| - * A flag indicating whether analysis is to parse comments.
|
| + * A flag indicating whether analysis is to analyze Angular.
|
| */
|
| bool analyzeAngular = true;
|
|
|
| @@ -6710,7 +7295,19 @@ class AnalysisOptionsImpl implements AnalysisOptions {
|
| dart2jsHint = options.dart2jsHint;
|
| hint = options.hint;
|
| incremental = options.incremental;
|
| - analyzeAngular = options.analyzeAngular;
|
| + }
|
| +
|
| + bool get generateSdkErrors => _generateSdkErrors;
|
| +
|
| + /**
|
| + * Set whether errors, warnings and hints should be generated for sources in the SDK to match the
|
| + * given value.
|
| + *
|
| + * @param generate `true` if errors, warnings and hints should be generated for sources in
|
| + * the SDK
|
| + */
|
| + void set generateSdkErrors(bool generate) {
|
| + _generateSdkErrors = generate;
|
| }
|
| }
|
|
|
| @@ -6776,7 +7373,7 @@ class ChangeNoticeImpl implements ChangeNotice {
|
| this._errors = errors;
|
| this._lineInfo = lineInfo;
|
| if (lineInfo == null) {
|
| - AnalysisEngine.instance.logger.logError2("No line info: ${source}", new JavaException());
|
| + AnalysisEngine.instance.logger.logInformation3("No line info: ${source}", new JavaException());
|
| }
|
| }
|
|
|
| @@ -7326,15 +7923,7 @@ class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
| }
|
|
|
| - List<Source> computeExportedLibraries(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeExportedLibraries");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.computeExportedLibraries(source);
|
| - } finally {
|
| - instrumentation.log();
|
| - }
|
| - }
|
| + List<Source> computeExportedLibraries(Source source) => _basis.computeExportedLibraries(source);
|
|
|
| HtmlElement computeHtmlElement(Source source) {
|
| InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeHtmlElement");
|
| @@ -7349,15 +7938,7 @@ class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
| }
|
|
|
| - List<Source> computeImportedLibraries(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeImportedLibraries");
|
| - try {
|
| - instrumentation.metric3("contextId", _contextId);
|
| - return _basis.computeImportedLibraries(source);
|
| - } finally {
|
| - instrumentation.log();
|
| - }
|
| - }
|
| + List<Source> computeImportedLibraries(Source source) => _basis.computeImportedLibraries(source);
|
|
|
| SourceKind computeKindOf(Source source) {
|
| InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-computeKindOf");
|
| @@ -7401,6 +7982,16 @@ class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
|
|
|
| ResolvableHtmlUnit computeResolvableHtmlUnit(Source source) => _basis.computeResolvableHtmlUnit(source);
|
|
|
| + bool exists(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-exists");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.exists(source);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| +
|
| AnalysisContext extractContext(SourceContainer container) {
|
| InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-extractContext");
|
| try {
|
| @@ -7430,6 +8021,22 @@ class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
|
| */
|
| AnalysisContext get basis => _basis;
|
|
|
| + CompilationUnitElement getCompilationUnitElement(Source unitSource, Source librarySource) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getCompilationUnitElement");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.getCompilationUnitElement(unitSource, librarySource);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| +
|
| + TimestampedData<String> getContents(Source source) => _basis.getContents(source);
|
| +
|
| + void getContents2(Source source, Source_ContentReceiver receiver) {
|
| + _basis.getContents2(source, receiver);
|
| + }
|
| +
|
| Element getElement(ElementLocation location) {
|
| InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getElement");
|
| try {
|
| @@ -7582,11 +8189,21 @@ class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
| }
|
|
|
| - LineInfo getLineInfo(Source source) {
|
| - InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLineInfo");
|
| + LineInfo getLineInfo(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLineInfo");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.getLineInfo(source);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| +
|
| + int getModificationStamp(Source source) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getModificationStamp");
|
| try {
|
| instrumentation.metric3("contextId", _contextId);
|
| - return _basis.getLineInfo(source);
|
| + return _basis.getModificationStamp(source);
|
| } finally {
|
| instrumentation.log();
|
| }
|
| @@ -7596,7 +8213,15 @@ class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
|
|
|
| Namespace getPublicNamespace2(Source source) => _basis.getPublicNamespace2(source);
|
|
|
| - List<Source> get refactoringUnsafeSources => _basis.refactoringUnsafeSources;
|
| + List<Source> get refactoringUnsafeSources {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getRefactoringUnsafeSources");
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.refactoringUnsafeSources;
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
|
|
| CompilationUnit getResolvedCompilationUnit(Source unitSource, LibraryElement library) {
|
| InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getResolvedCompilationUnit");
|
| @@ -7642,8 +8267,12 @@ class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
|
|
|
| TypeProvider get typeProvider => _basis.typeProvider;
|
|
|
| + TimestampedData<CompilationUnit> internalParseCompilationUnit(Source source) => _basis.internalParseCompilationUnit(source);
|
| +
|
| TimestampedData<CompilationUnit> internalResolveCompilationUnit(Source unitSource, LibraryElement libraryElement) => _basis.internalResolveCompilationUnit(unitSource, libraryElement);
|
|
|
| + TimestampedData<Token> internalScanTokenStream(Source source) => _basis.internalScanTokenStream(source);
|
| +
|
| bool isClientLibrary(Source librarySource) {
|
| InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-isClientLibrary");
|
| try {
|
| @@ -7809,16 +8438,6 @@ class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
|
| 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();
|
| - }
|
| - }
|
| }
|
|
|
| /**
|
| @@ -7932,6 +8551,15 @@ abstract class InternalAnalysisContext implements AnalysisContext {
|
| TypeProvider get typeProvider;
|
|
|
| /**
|
| + * Return a time-stamped parsed AST for the given source.
|
| + *
|
| + * @param source the source of the compilation unit for which an AST is to be returned
|
| + * @return a time-stamped AST for the source
|
| + * @throws AnalysisException if the source could not be parsed
|
| + */
|
| + TimestampedData<CompilationUnit> internalParseCompilationUnit(Source source);
|
| +
|
| + /**
|
| * Return a time-stamped fully-resolved compilation unit for the given source in the given
|
| * library.
|
| *
|
| @@ -7945,6 +8573,15 @@ abstract class InternalAnalysisContext implements AnalysisContext {
|
| TimestampedData<CompilationUnit> internalResolveCompilationUnit(Source unitSource, LibraryElement libraryElement);
|
|
|
| /**
|
| + * Return a time-stamped token stream for the given source.
|
| + *
|
| + * @param source the source of the compilation unit for which a token stream is to be returned
|
| + * @return a time-stamped token stream for the source
|
| + * @throws AnalysisException if the token stream could not be computed
|
| + */
|
| + TimestampedData<Token> internalScanTokenStream(Source source);
|
| +
|
| + /**
|
| * Given a table mapping the source for the libraries represented by the corresponding elements to
|
| * the elements representing the libraries, record those mappings.
|
| *
|
| @@ -8467,21 +9104,6 @@ class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
|
| }
|
|
|
| /**
|
| - * Returns the array of all top-level Angular elements that could be used in the application with
|
| - * this entry point. Maybe `null` of not an Angular entry point.
|
| - */
|
| - static List<AngularElement> getAngularElements(AnalysisContext context, ht.HtmlUnit unit) {
|
| - if (hasAngularAnnotation(unit)) {
|
| - CompilationUnit dartUnit = getDartUnit(context, unit);
|
| - if (dartUnit != null) {
|
| - LibraryElement libraryElement = dartUnit.element.library;
|
| - return getAngularElements2(libraryElement);
|
| - }
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - /**
|
| * @return `true` if the given [HtmlUnit] has <code>ng-app</code> annotation.
|
| */
|
| static bool hasAngularAnnotation(ht.HtmlUnit htmlUnit) {
|
| @@ -8519,11 +9141,15 @@ class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
|
| * @return the array of all top-level Angular elements that could be used in this library
|
| */
|
| static void addAngularElements2(Set<AngularElement> angularElements, LibraryElement library, Set<LibraryElement> visited) {
|
| + if (library == null) {
|
| + return;
|
| + }
|
| if (!visited.add(library)) {
|
| return;
|
| }
|
| // add Angular elements from current library
|
| for (CompilationUnitElement unit in library.units) {
|
| + angularElements.addAll(unit.angularViews);
|
| for (ClassElement type in unit.types) {
|
| addAngularElements(angularElements, type);
|
| }
|
| @@ -8543,9 +9169,9 @@ class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
|
| * @param libraryElement the [LibraryElement] to analyze
|
| * @return the array of all top-level Angular elements that could be used in this library
|
| */
|
| - static List<AngularElement> getAngularElements2(LibraryElement libraryElement) {
|
| + static List<AngularElement> getAngularElements(Set<LibraryElement> libraries, LibraryElement libraryElement) {
|
| Set<AngularElement> angularElements = new Set();
|
| - addAngularElements2(angularElements, libraryElement, new Set());
|
| + addAngularElements2(angularElements, libraryElement, libraries);
|
| return new List.from(angularElements);
|
| }
|
|
|
| @@ -8564,11 +9190,19 @@ class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
|
| return null;
|
| }
|
|
|
| + static Set<Source> getLibrarySources(Set<LibraryElement> libraries) {
|
| + Set<Source> sources = new Set();
|
| + for (LibraryElement library in libraries) {
|
| + sources.add(library.source);
|
| + }
|
| + return sources;
|
| + }
|
| +
|
| InternalAnalysisContext _context;
|
|
|
| TypeProvider _typeProvider;
|
|
|
| - AnalysisErrorListener _errorListener;
|
| + AngularHtmlUnitResolver_FilteringAnalysisErrorListener _errorListener;
|
|
|
| Source _source;
|
|
|
| @@ -8601,17 +9235,17 @@ class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
|
| AngularHtmlUnitResolver(InternalAnalysisContext context, AnalysisErrorListener errorListener, Source source, LineInfo lineInfo, ht.HtmlUnit unit) {
|
| this._context = context;
|
| this._typeProvider = context.typeProvider;
|
| - this._errorListener = errorListener;
|
| + this._errorListener = new AngularHtmlUnitResolver_FilteringAnalysisErrorListener(errorListener);
|
| this._source = source;
|
| this._lineInfo = lineInfo;
|
| this._unit = unit;
|
| }
|
|
|
| /**
|
| - * The [AngularApplicationInfo] for the Web application with this entry point, may be
|
| + * The [AngularApplication] for the Web application with this entry point, may be
|
| * `null` if not an entry point.
|
| */
|
| - AngularApplicationInfo calculateAngularApplication() {
|
| + AngularApplication calculateAngularApplication() {
|
| // check if Angular at all
|
| if (!hasAngularAnnotation(_unit)) {
|
| return null;
|
| @@ -8623,36 +9257,50 @@ class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
|
| }
|
| // prepare accessible Angular elements
|
| LibraryElement libraryElement = dartUnit.element.library;
|
| - List<AngularElement> angularElements = getAngularElements2(libraryElement);
|
| - // resolve template URIs
|
| + Set<LibraryElement> libraries = new Set();
|
| + List<AngularElement> angularElements = getAngularElements(libraries, libraryElement);
|
| + // resolve AngularComponentElement template URIs
|
| // TODO(scheglov) resolve to HtmlElement to allow F3 ?
|
| + Set<Source> angularElementsSources = new Set();
|
| for (AngularElement angularElement in angularElements) {
|
| - if (angularElement is AngularComponentElement) {
|
| - AngularComponentElement component = angularElement;
|
| - String templateUri = component.templateUri;
|
| + if (angularElement is AngularHasTemplateElement) {
|
| + AngularHasTemplateElement hasTemplate = angularElement;
|
| + angularElementsSources.add(angularElement.source);
|
| + String templateUri = hasTemplate.templateUri;
|
| if (templateUri == null) {
|
| continue;
|
| }
|
| try {
|
| Source templateSource = _source.resolveRelative(parseUriWithException(templateUri));
|
| - if (templateSource == null || !templateSource.exists()) {
|
| + if (!_context.exists(templateSource)) {
|
| templateSource = _context.sourceFactory.resolveUri(_source, "package:${templateUri}");
|
| - if (templateSource == null || !templateSource.exists()) {
|
| - reportError7(component.templateUriOffset, templateUri.length, AngularCode.URI_DOES_NOT_EXIST, [templateUri]);
|
| + if (!_context.exists(templateSource)) {
|
| + _errorListener.onError(new AnalysisError.con2(angularElement.source, hasTemplate.templateUriOffset, templateUri.length, AngularCode.URI_DOES_NOT_EXIST, [templateUri]));
|
| continue;
|
| }
|
| }
|
| if (!AnalysisEngine.isHtmlFileName(templateUri)) {
|
| continue;
|
| }
|
| - (component as AngularComponentElementImpl).templateSource = templateSource;
|
| + if (hasTemplate is AngularComponentElementImpl) {
|
| + hasTemplate.templateSource = templateSource;
|
| + }
|
| + if (hasTemplate is AngularViewElementImpl) {
|
| + hasTemplate.templateSource = templateSource;
|
| + }
|
| } on URISyntaxException catch (exception) {
|
| - reportError7(component.templateUriOffset, templateUri.length, AngularCode.INVALID_URI, [templateUri]);
|
| + _errorListener.onError(new AnalysisError.con2(angularElement.source, hasTemplate.templateUriOffset, templateUri.length, AngularCode.INVALID_URI, [templateUri]));
|
| }
|
| }
|
| }
|
| + // create AngularApplication
|
| + AngularApplication application = new AngularApplication(_source, getLibrarySources(libraries), angularElements, new List.from(angularElementsSources));
|
| + // set AngularApplication for each AngularElement
|
| + for (AngularElement angularElement in angularElements) {
|
| + (angularElement as AngularElementImpl).application = application;
|
| + }
|
| // done
|
| - return new AngularApplicationInfo(_source, angularElements);
|
| + return application;
|
| }
|
|
|
| /**
|
| @@ -8661,7 +9309,7 @@ class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
|
| * @param application the Angular application we are resolving for
|
| * @param component the [AngularComponentElement] to resolve template for, not `null`
|
| */
|
| - void resolveComponentTemplate(AngularApplicationInfo application, AngularComponentElement component) {
|
| + void resolveComponentTemplate(AngularApplication application, AngularComponentElement component) {
|
| _isAngular = true;
|
| resolveInternal(application.elements, component);
|
| }
|
| @@ -8669,7 +9317,7 @@ class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
|
| /**
|
| * Resolves [source] as an Angular application entry point.
|
| */
|
| - void resolveEntryPoint(AngularApplicationInfo application) {
|
| + void resolveEntryPoint(AngularApplication application) {
|
| resolveInternal(application.elements, null);
|
| }
|
|
|
| @@ -8935,9 +9583,10 @@ class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
|
| }
|
|
|
| /**
|
| - * Defines variable for the given [AngularElement].
|
| + * Defines variable for the given [AngularElement] with type of the enclosing
|
| + * [ClassElement].
|
| */
|
| - void defineTopElementVariable(AngularElement element) {
|
| + void defineTopVariable_forClassElement(AngularElement element) {
|
| ClassElement classElement = element.enclosingElement as ClassElement;
|
| InterfaceType type = classElement.type;
|
| LocalVariableElementImpl variable = createLocalVariable2(type, element.name);
|
| @@ -8946,6 +9595,16 @@ class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
|
| }
|
|
|
| /**
|
| + * Defines variable for the given [AngularScopePropertyElement].
|
| + */
|
| + void defineTopVariable_forScopeProperty(AngularScopePropertyElement element) {
|
| + Type2 type = element.type;
|
| + LocalVariableElementImpl variable = createLocalVariable2(type, element.name);
|
| + defineTopVariable(variable);
|
| + variable.toolkitObjects = <AngularElement> [element];
|
| + }
|
| +
|
| + /**
|
| * Parse the value of the given token for embedded expressions, and add any embedded expressions
|
| * that are found to the given list of expressions.
|
| *
|
| @@ -9048,13 +9707,6 @@ class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
|
| for (AngularElement angularElement in angularElements) {
|
| _injectedLibraries.add(angularElement.library);
|
| }
|
| - // add accessible processors
|
| - for (AngularElement angularElement in angularElements) {
|
| - NgProcessor processor = createProcessor(angularElement);
|
| - if (processor != null) {
|
| - _processors.add(processor);
|
| - }
|
| - }
|
| // prepare Dart library
|
| createLibraryElement();
|
| (_unit.element as HtmlElementImpl).angularCompilationUnit = _unitElement;
|
| @@ -9062,12 +9714,22 @@ class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
|
| createResolver();
|
| // maybe resolving component template
|
| if (component != null) {
|
| - defineTopElementVariable(component);
|
| + defineTopVariable_forClassElement(component);
|
| + for (AngularScopePropertyElement scopeProperty in component.scopeProperties) {
|
| + defineTopVariable_forScopeProperty(scopeProperty);
|
| + }
|
| + }
|
| + // add processors
|
| + for (AngularElement angularElement in angularElements) {
|
| + NgProcessor processor = createProcessor(angularElement);
|
| + if (processor != null) {
|
| + _processors.add(processor);
|
| + }
|
| }
|
| // define filters
|
| for (AngularElement angularElement in angularElements) {
|
| if (angularElement is AngularFilterElement) {
|
| - defineTopElementVariable(angularElement);
|
| + defineTopVariable_forClassElement(angularElement);
|
| }
|
| }
|
| // run this HTML visitor
|
| @@ -9112,6 +9774,22 @@ class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
|
| }
|
| }
|
|
|
| +class AngularHtmlUnitResolver_FilteringAnalysisErrorListener implements AnalysisErrorListener {
|
| + AnalysisErrorListener _listener;
|
| +
|
| + AngularHtmlUnitResolver_FilteringAnalysisErrorListener(AnalysisErrorListener listener) {
|
| + this._listener = listener;
|
| + }
|
| +
|
| + void onError(AnalysisError error) {
|
| + ErrorCode errorCode = error.errorCode;
|
| + if (identical(errorCode, StaticWarningCode.UNDEFINED_GETTER) || identical(errorCode, StaticWarningCode.UNDEFINED_IDENTIFIER) || identical(errorCode, StaticTypeWarningCode.UNDEFINED_GETTER)) {
|
| + return;
|
| + }
|
| + _listener.onError(error);
|
| + }
|
| +}
|
| +
|
| class AngularHtmlUnitResolver_FoundAppError extends Error {
|
| }
|
|
|
| @@ -9345,19 +10023,32 @@ class NgDirectiveElementProcessor extends NgDirectiveProcessor {
|
| }
|
|
|
| void apply(AngularHtmlUnitResolver resolver, ht.XmlTagNode node) {
|
| + String selectorAttributeName = null;
|
| + {
|
| + AngularSelectorElement selector = _element.selector;
|
| + if (selector is HasAttributeSelectorElementImpl) {
|
| + selectorAttributeName = selector.name;
|
| + // resolve attribute expression
|
| + ht.XmlAttributeNode attribute = node.getAttribute(selectorAttributeName);
|
| + if (attribute != null) {
|
| + attribute.element = selector;
|
| + }
|
| + }
|
| + }
|
| + //
|
| for (AngularPropertyElement property in _element.properties) {
|
| // prepare attribute name
|
| String name = property.name;
|
| if (name == ".") {
|
| - AngularSelectorElement selector = _element.selector;
|
| - if (selector is HasAttributeSelectorElementImpl) {
|
| - name = selector.name;
|
| - }
|
| + name = selectorAttributeName;
|
| }
|
| // resolve attribute expression
|
| ht.XmlAttributeNode attribute = node.getAttribute(name);
|
| if (attribute != null) {
|
| - attribute.element = property;
|
| + // if not resolved as the selector, resolve as a property
|
| + if (name != selectorAttributeName) {
|
| + attribute.element = property;
|
| + }
|
| // resolve if binding
|
| if (property.propertyKind != AngularPropertyKind.ATTR) {
|
| resolver.pushNameScope();
|
| @@ -9695,6 +10386,15 @@ abstract class AnalysisTaskVisitor<E> {
|
| * @throws AnalysisException if the visitor throws an exception for some reason
|
| */
|
| E visitResolveHtmlTask(ResolveHtmlTask task);
|
| +
|
| + /**
|
| + * Visit a [ScanDartTask].
|
| + *
|
| + * @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 visitScanDartTask(ScanDartTask task);
|
| }
|
|
|
| /**
|
| @@ -9979,11 +10679,6 @@ class ParseDartTask extends AnalysisTask {
|
| int _modificationTime = -1;
|
|
|
| /**
|
| - * The line information that was produced.
|
| - */
|
| - LineInfo _lineInfo;
|
| -
|
| - /**
|
| * The compilation unit that was produced by parsing the source.
|
| */
|
| CompilationUnit _unit;
|
| @@ -10030,14 +10725,6 @@ class ParseDartTask extends AnalysisTask {
|
| List<AnalysisError> get errors => _errors;
|
|
|
| /**
|
| - * 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.
|
| *
|
| @@ -10070,19 +10757,12 @@ class ParseDartTask extends AnalysisTask {
|
|
|
| void internalPerform() {
|
| RecordingErrorListener errorListener = new RecordingErrorListener();
|
| - List<Token> token = [null];
|
| - //
|
| - // Scan the contents of the file.
|
| - //
|
| - Source_ContentReceiver receiver = new Source_ContentReceiver_ParseDartTask_internalPerform(this, errorListener, token);
|
| - try {
|
| - source.getContents(receiver);
|
| - } on JavaException catch (exception) {
|
| - _modificationTime = source.modificationStamp;
|
| - throw new AnalysisException.con3(exception);
|
| - }
|
| - if (token[0] == null) {
|
| - throw new AnalysisException.con1("Could not get contents for '${source.fullName}'");
|
| + InternalAnalysisContext context = this.context;
|
| + TimestampedData<Token> data = context.internalScanTokenStream(source);
|
| + _modificationTime = data.modificationTime;
|
| + Token token = data.data;
|
| + if (token == null) {
|
| + throw new AnalysisException.con1("Could not get token stream for ${source.fullName}");
|
| }
|
| //
|
| // Then parse the token stream.
|
| @@ -10091,7 +10771,7 @@ class ParseDartTask extends AnalysisTask {
|
| try {
|
| Parser parser = new Parser(source, errorListener);
|
| parser.parseFunctionBodies = context.analysisOptions.analyzeFunctionBodies;
|
| - _unit = parser.parseCompilationUnit(token[0]);
|
| + _unit = parser.parseCompilationUnit(token);
|
| _errors = errorListener.getErrors2(source);
|
| for (Directive directive in _unit.directives) {
|
| if (directive is LibraryDirective) {
|
| @@ -10100,36 +10780,13 @@ class ParseDartTask extends AnalysisTask {
|
| _hasPartOfDirective2 = true;
|
| }
|
| }
|
| - _unit.lineInfo = _lineInfo;
|
| + _unit.lineInfo = context.getLineInfo(source);
|
| } finally {
|
| timeCounterParse.stop();
|
| }
|
| }
|
| }
|
|
|
| -class Source_ContentReceiver_ParseDartTask_internalPerform implements Source_ContentReceiver {
|
| - final ParseDartTask ParseDartTask_this;
|
| -
|
| - RecordingErrorListener errorListener;
|
| -
|
| - List<Token> token;
|
| -
|
| - Source_ContentReceiver_ParseDartTask_internalPerform(this.ParseDartTask_this, this.errorListener, this.token);
|
| -
|
| - void accept(String contents, int modificationTime) {
|
| - ParseDartTask_this._modificationTime = modificationTime;
|
| - TimeCounter_TimeCounterHandle timeCounterScan = PerformanceStatistics.scan.start();
|
| - try {
|
| - Scanner scanner = new Scanner(ParseDartTask_this.source, new CharSequenceReader(contents), errorListener);
|
| - scanner.preserveComments = ParseDartTask_this.context.analysisOptions.preserveComments;
|
| - token[0] = scanner.tokenize();
|
| - ParseDartTask_this._lineInfo = new LineInfo(scanner.lineStarts);
|
| - } finally {
|
| - timeCounterScan.stop();
|
| - }
|
| - }
|
| -}
|
| -
|
| /**
|
| * Instances of the class `ParseHtmlTask` parse a specific source as an HTML file.
|
| */
|
| @@ -10170,22 +10827,11 @@ class ParseHtmlTask extends AnalysisTask {
|
| 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
|
| @@ -10241,20 +10887,20 @@ class ParseHtmlTask extends AnalysisTask {
|
| }
|
|
|
| void internalPerform() {
|
| - ht.HtmlScanner scanner = new ht.HtmlScanner(source);
|
| try {
|
| - source.getContents(scanner);
|
| + TimestampedData<String> contents = context.getContents(source);
|
| + _modificationTime = contents.modificationTime;
|
| + ht.AbstractScanner scanner = new ht.StringScanner(source, contents.data);
|
| + scanner.passThroughElements = <String> [_TAG_SCRIPT];
|
| + ht.Token token = scanner.tokenize();
|
| + _lineInfo = new LineInfo(scanner.lineStarts);
|
| + RecordingErrorListener errorListener = new RecordingErrorListener();
|
| + _unit = new ht.HtmlParser(source, errorListener).parse(token, _lineInfo);
|
| + _errors = errorListener.getErrors2(source);
|
| + _referencedLibraries = librarySources;
|
| } on JavaException catch (exception) {
|
| throw new AnalysisException.con3(exception);
|
| }
|
| - ht.HtmlScanResult scannerResult = scanner.result;
|
| - _modificationTime = scannerResult.modificationTime;
|
| - _lineInfo = new LineInfo(scannerResult.lineStarts);
|
| - RecordingErrorListener errorListener = new RecordingErrorListener();
|
| - ht.HtmlParseResult result = new ht.HtmlParser(source, errorListener).parse(scannerResult);
|
| - _unit = result.htmlUnit;
|
| - _errors = errorListener.getErrors2(source);
|
| - _referencedLibraries = librarySources;
|
| }
|
|
|
| /**
|
| @@ -10291,7 +10937,7 @@ class RecursiveXmlVisitor_ParseHtmlTask_getLibrarySources extends ht.RecursiveXm
|
| Uri uri = new Uri(path: scriptAttribute.text);
|
| String fileName = uri.path;
|
| Source librarySource = ParseHtmlTask_this.context.sourceFactory.resolveUri(ParseHtmlTask_this.source, fileName);
|
| - if (librarySource != null && librarySource.exists()) {
|
| + if (ParseHtmlTask_this.context.exists(librarySource)) {
|
| libraries.add(librarySource);
|
| }
|
| } on URISyntaxException catch (e) {
|
| @@ -10314,7 +10960,7 @@ class ResolveAngularComponentTemplateTask extends AnalysisTask {
|
| /**
|
| * The Angular application to resolve in context of.
|
| */
|
| - AngularApplicationInfo _application;
|
| + AngularApplication _application;
|
|
|
| /**
|
| * The source to be resolved.
|
| @@ -10344,7 +10990,7 @@ class ResolveAngularComponentTemplateTask extends AnalysisTask {
|
| * @param component the component that uses this HTML template, not `null`
|
| * @param application the Angular application to resolve in context of
|
| */
|
| - ResolveAngularComponentTemplateTask(InternalAnalysisContext context, this.source, AngularComponentElement component, AngularApplicationInfo application) : super(context) {
|
| + ResolveAngularComponentTemplateTask(InternalAnalysisContext context, this.source, AngularComponentElement component, AngularApplication application) : super(context) {
|
| this._component = component;
|
| this._application = application;
|
| }
|
| @@ -10381,12 +11027,13 @@ class ResolveAngularComponentTemplateTask extends AnalysisTask {
|
| RecordingErrorListener errorListener = new RecordingErrorListener();
|
| LineInfo lineInfo = context.getLineInfo(source);
|
| // do resolve
|
| - AngularHtmlUnitResolver resolver = new AngularHtmlUnitResolver(context, errorListener, source, lineInfo, unit);
|
| - resolver.resolveComponentTemplate(_application, _component);
|
| + if (_application != null) {
|
| + AngularHtmlUnitResolver resolver = new AngularHtmlUnitResolver(context, errorListener, source, lineInfo, unit);
|
| + resolver.resolveComponentTemplate(_application, _component);
|
| + _resolvedUnit = unit;
|
| + }
|
| // remember errors
|
| _resolutionErrors = errorListener.getErrors2(source);
|
| - // remember resolved unit
|
| - _resolvedUnit = unit;
|
| }
|
| }
|
|
|
| @@ -10401,9 +11048,9 @@ class ResolveAngularEntryHtmlTask extends AnalysisTask {
|
| final Source source;
|
|
|
| /**
|
| - * The Angular application to resolve in context of.
|
| + * The listener to record errors.
|
| */
|
| - AngularApplicationInfo _application;
|
| + RecordingErrorListener _errorListener = new RecordingErrorListener();
|
|
|
| /**
|
| * The time at which the contents of the source were last modified.
|
| @@ -10421,26 +11068,39 @@ class ResolveAngularEntryHtmlTask extends AnalysisTask {
|
| HtmlElement _element = null;
|
|
|
| /**
|
| - * The resolution errors that were discovered while resolving the source.
|
| + * The Angular application to resolve in context of.
|
| */
|
| - List<AnalysisError> _resolutionErrors = AnalysisError.NO_ERRORS;
|
| + AngularApplication _application;
|
|
|
| /**
|
| * 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 resolved
|
| - * @param application the Angular application to resolve in context of
|
| */
|
| - ResolveAngularEntryHtmlTask(InternalAnalysisContext context, this.source, AngularApplicationInfo application) : super(context) {
|
| - this._application = application;
|
| - }
|
| + ResolveAngularEntryHtmlTask(InternalAnalysisContext context, this.source) : super(context);
|
|
|
| accept(AnalysisTaskVisitor visitor) => visitor.visitResolveAngularEntryHtmlTask(this);
|
|
|
| + /**
|
| + * Returns the [AngularApplication] for the Web application with this Angular entry point,
|
| + * maybe `null` if not an Angular entry point.
|
| + */
|
| + AngularApplication get application => _application;
|
| +
|
| HtmlElement get element => _element;
|
|
|
| /**
|
| + * The resolution errors that were discovered while resolving the source.
|
| + */
|
| + List<AnalysisError> get entryErrors => _errorListener.getErrors2(source);
|
| +
|
| + /**
|
| + * Returns [AnalysisError]s recorded for the given [Source].
|
| + */
|
| + List<AnalysisError> getErrors(Source source) => _errorListener.getErrors2(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.
|
| *
|
| @@ -10448,8 +11108,6 @@ class ResolveAngularEntryHtmlTask extends AnalysisTask {
|
| */
|
| int get modificationTime => _modificationTime;
|
|
|
| - List<AnalysisError> get resolutionErrors => _resolutionErrors;
|
| -
|
| /**
|
| * Return the [HtmlUnit] that was resolved by this task.
|
| *
|
| @@ -10472,12 +11130,13 @@ class ResolveAngularEntryHtmlTask extends AnalysisTask {
|
| }
|
| _modificationTime = resolvableHtmlUnit.modificationTime;
|
| // prepare for resolution
|
| - RecordingErrorListener errorListener = new RecordingErrorListener();
|
| LineInfo lineInfo = context.getLineInfo(source);
|
| + // try to resolve as an Angular entry point
|
| + _application = new AngularHtmlUnitResolver(context, _errorListener, source, lineInfo, unit).calculateAngularApplication();
|
| // do resolve
|
| - new AngularHtmlUnitResolver(context, errorListener, source, lineInfo, unit).resolveEntryPoint(_application);
|
| - // remember errors
|
| - _resolutionErrors = errorListener.getErrors2(source);
|
| + if (_application != null) {
|
| + new AngularHtmlUnitResolver(context, _errorListener, source, lineInfo, unit).resolveEntryPoint(_application);
|
| + }
|
| // remember resolved unit
|
| _resolvedUnit = unit;
|
| }
|
| @@ -10563,14 +11222,11 @@ class ResolveDartDependenciesTask extends AnalysisTask {
|
| }
|
|
|
| void internalPerform() {
|
| - ResolvableCompilationUnit unit = context.computeResolvableCompilationUnit(source);
|
| + TimestampedData<CompilationUnit> unit = context.internalParseCompilationUnit(source);
|
| _modificationTime = unit.modificationTime;
|
| - //
|
| - // Then parse the token stream.
|
| - //
|
| TimeCounter_TimeCounterHandle timeCounterParse = PerformanceStatistics.parse.start();
|
| try {
|
| - for (Directive directive in unit.compilationUnit.directives) {
|
| + for (Directive directive in unit.data.directives) {
|
| if (directive is ExportDirective) {
|
| Source exportSource = resolveSource(source, directive);
|
| if (exportSource != null) {
|
| @@ -10854,16 +11510,6 @@ class ResolveHtmlTask extends AnalysisTask {
|
| List<AnalysisError> _resolutionErrors = AnalysisError.NO_ERRORS;
|
|
|
| /**
|
| - * The flag that says is this unit is an Angular application.
|
| - */
|
| - bool _isAngularApplication2 = false;
|
| -
|
| - /**
|
| - * The Angular application information, maybe `null`
|
| - */
|
| - AngularApplicationInfo _angularApplication;
|
| -
|
| - /**
|
| * Initialize a newly created task to perform analysis within the given context.
|
| *
|
| * @param context the context in which the task is to be performed
|
| @@ -10873,12 +11519,6 @@ class ResolveHtmlTask extends AnalysisTask {
|
|
|
| accept(AnalysisTaskVisitor visitor) => visitor.visitResolveHtmlTask(this);
|
|
|
| - /**
|
| - * Returns the [AngularApplicationInfo] for the Web application with this Angular entry
|
| - * point, maybe `null` if not an Angular entry point.
|
| - */
|
| - AngularApplicationInfo get angularApplication => _angularApplication;
|
| -
|
| HtmlElement get element => _element;
|
|
|
| /**
|
| @@ -10898,11 +11538,6 @@ class ResolveHtmlTask extends AnalysisTask {
|
| */
|
| ht.HtmlUnit get resolvedUnit => _resolvedUnit;
|
|
|
| - /**
|
| - * Returns `true` if analyzed unit is an Angular application.
|
| - */
|
| - bool get isAngularApplication => _isAngularApplication2;
|
| -
|
| String get taskDescription {
|
| if (source == null) {
|
| return "resolve as html null source";
|
| @@ -10921,12 +11556,6 @@ class ResolveHtmlTask extends AnalysisTask {
|
| HtmlUnitBuilder builder = new HtmlUnitBuilder(context);
|
| _element = builder.buildHtmlElement2(source, _modificationTime, unit);
|
| RecordingErrorListener errorListener = builder.errorListener;
|
| - LineInfo lineInfo = context.getLineInfo(source);
|
| - // try to resolve as an Angular entry point
|
| - if (context.analysisOptions.analyzeAngular) {
|
| - _isAngularApplication2 = AngularHtmlUnitResolver.hasAngularAnnotation(unit);
|
| - _angularApplication = new AngularHtmlUnitResolver(context, errorListener, source, lineInfo, unit).calculateAngularApplication();
|
| - }
|
| // record all resolution errors
|
| _resolutionErrors = errorListener.getErrors2(source);
|
| // remember resolved unit
|
| @@ -10935,6 +11564,110 @@ class ResolveHtmlTask extends AnalysisTask {
|
| }
|
|
|
| /**
|
| + * Instances of the class `ScanDartTask` scan a specific source as a Dart file.
|
| + */
|
| +class ScanDartTask extends AnalysisTask {
|
| + /**
|
| + * The source to be scanned.
|
| + */
|
| + final Source source;
|
| +
|
| + /**
|
| + * The contents of the source.
|
| + */
|
| + String _content;
|
| +
|
| + /**
|
| + * The time at which the contents of the source were last modified.
|
| + */
|
| + int _modificationTime = 0;
|
| +
|
| + /**
|
| + * The token stream that was produced by scanning the source.
|
| + */
|
| + Token _tokenStream;
|
| +
|
| + /**
|
| + * The line information that was produced.
|
| + */
|
| + LineInfo _lineInfo;
|
| +
|
| + /**
|
| + * The errors that were produced by scanning the source.
|
| + */
|
| + List<AnalysisError> _errors = AnalysisError.NO_ERRORS;
|
| +
|
| + /**
|
| + * 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
|
| + * @param contentData the time-stamped contents of the source
|
| + */
|
| + ScanDartTask(InternalAnalysisContext context, this.source, TimestampedData<String> contentData) : super(context) {
|
| + this._content = contentData.data;
|
| + this._modificationTime = contentData.modificationTime;
|
| + }
|
| +
|
| + accept(AnalysisTaskVisitor visitor) => visitor.visitScanDartTask(this);
|
| +
|
| + /**
|
| + * Return the errors that were produced by scanning 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 the source
|
| + */
|
| + List<AnalysisError> get errors => _errors;
|
| +
|
| + /**
|
| + * 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 token stream that was produced by scanning the source, or `null` if the task
|
| + * has not yet been performed or if an exception occurred.
|
| + *
|
| + * @return the token stream that was produced by scanning the source
|
| + */
|
| + Token get tokenStream => _tokenStream;
|
| +
|
| + String get taskDescription {
|
| + if (source == null) {
|
| + return "scan as dart null source";
|
| + }
|
| + return "scan as dart ${source.fullName}";
|
| + }
|
| +
|
| + void internalPerform() {
|
| + RecordingErrorListener errorListener = new RecordingErrorListener();
|
| + TimeCounter_TimeCounterHandle timeCounterScan = PerformanceStatistics.scan.start();
|
| + try {
|
| + Scanner scanner = new Scanner(source, new CharSequenceReader(_content), errorListener);
|
| + scanner.preserveComments = context.analysisOptions.preserveComments;
|
| + _tokenStream = scanner.tokenize();
|
| + _lineInfo = new LineInfo(scanner.lineStarts);
|
| + _errors = errorListener.getErrors2(source);
|
| + } on JavaException catch (exception) {
|
| + throw new AnalysisException.con3(exception);
|
| + } finally {
|
| + timeCounterScan.stop();
|
| + }
|
| + }
|
| +}
|
| +
|
| +/**
|
| * The interface `Logger` defines the behavior of objects that can be used to receive
|
| * information about errors within the analysis engine. Implementations usually write this
|
| * information to a file, but can also record the information for later use (such as during testing)
|
|
|