| 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 be82258751f4cb6a9350eacd22bbdc5beb3d4c2f..746ecd58be97c8583eb90c7456bdcce3ad9cc898 100644
|
| --- a/pkg/analyzer/lib/src/generated/engine.dart
|
| +++ b/pkg/analyzer/lib/src/generated/engine.dart
|
| @@ -239,7 +239,7 @@ abstract class AnalysisContext {
|
| /**
|
| * Return the element model corresponding to the HTML file defined by the given source. If the
|
| * element model does not yet exist it will be created. The process of creating an element model
|
| - * for an HTML file can long-running, depending on the size of the file and the number of
|
| + * for an HTML file can be long-running, depending on the size of the file and the number of
|
| * libraries that are defined in it (via script tags) that also need to have a model built for
|
| * them.
|
| *
|
| @@ -334,6 +334,16 @@ abstract class AnalysisContext {
|
| AnalysisOptions get analysisOptions;
|
|
|
| /**
|
| + * Return the Angular application that contains the HTML file defined by the given source, or
|
| + * `null` if the source does not represent an HTML file, the Angular application containing
|
| + * the file has not yet been resolved, or the analysis of the HTML file failed for some reason.
|
| + *
|
| + * @param htmlSource the source defining the HTML file
|
| + * @return the Angular application that contains the HTML file defined by the given source
|
| + */
|
| + AngularApplication getAngularApplicationWithHtml(Source htmlSource);
|
| +
|
| + /**
|
| * 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.
|
| @@ -466,6 +476,15 @@ abstract class AnalysisContext {
|
| List<Source> getLibrariesDependingOn(Source librarySource);
|
|
|
| /**
|
| + * Return the sources for the defining compilation units of any libraries that are referenced from
|
| + * the given HTML file.
|
| + *
|
| + * @param htmlSource the source for the HTML file
|
| + * @return the sources for the libraries that are referenced by the given HTML file
|
| + */
|
| + List<Source> getLibrariesReferencedFromHtml(Source htmlSource);
|
| +
|
| + /**
|
| * Return the element model corresponding to 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.
|
| @@ -640,6 +659,8 @@ abstract class AnalysisContext {
|
| /**
|
| * Parse and resolve a single source within the given context to produce a fully resolved AST.
|
| *
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| + *
|
| * @param unitSource the source to be parsed and resolved
|
| * @param library the library containing the source to be resolved
|
| * @return the result of resolving the AST structure representing the content of the source in the
|
| @@ -654,6 +675,8 @@ abstract class AnalysisContext {
|
| * Return the resolved AST structure, or `null` if the source could not be either parsed or
|
| * resolved.
|
| *
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| + *
|
| * @param unitSource the source to be parsed and resolved
|
| * @param librarySource the source of the defining compilation unit of the library containing the
|
| * source to be resolved
|
| @@ -667,6 +690,8 @@ abstract class AnalysisContext {
|
| /**
|
| * Parse and resolve a single source within the given context to produce a fully resolved AST.
|
| *
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| + *
|
| * @param htmlSource the source to be parsed and resolved
|
| * @return the result of resolving the AST structure representing the content of the source
|
| * @throws AnalysisException if the analysis could not be performed
|
| @@ -1278,6 +1303,11 @@ class AnalysisCache {
|
| * flushed from the cache. The source that will be returned will be the source that has been
|
| * unreferenced for the longest period of time but that is not a priority for analysis.
|
| *
|
| + * It is possible for there to be no AST that can be flushed, in which case `null` will be
|
| + * returned. This happens, for example, if the context is reserving the AST's needed to resolve a
|
| + * cycle of libraries and the number of AST's being reserved is larger than the current cache
|
| + * size.
|
| + *
|
| * @return the source that was removed
|
| */
|
| Source _removeAstToFlush() {
|
| @@ -1292,7 +1322,6 @@ class AnalysisCache {
|
| }
|
| }
|
| if (sourceToRemove < 0) {
|
| - AnalysisEngine.instance.logger.logError2("Internal error: Could not flush data from the cache", new JavaException());
|
| return null;
|
| }
|
| return _recentlyUsed.removeAt(sourceToRemove);
|
| @@ -2969,6 +2998,12 @@ class HtmlEntryImpl extends SourceEntryImpl implements HtmlEntry {
|
| _resolvedUnitState = CacheState.FLUSHED;
|
| _resolvedUnit = null;
|
| }
|
| + if (identical(_angularEntryState, CacheState.VALID)) {
|
| + _angularEntryState = CacheState.FLUSHED;
|
| + }
|
| + if (identical(_angularErrorsState, CacheState.VALID)) {
|
| + _angularErrorsState = CacheState.FLUSHED;
|
| + }
|
| }
|
|
|
| @override
|
| @@ -3704,11 +3739,23 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| static int _PRIORITY_ORDER_SIZE_DELTA = 4;
|
|
|
| /**
|
| + * A flag indicating whether trace output should be produced as analysis tasks are performed. Used
|
| + * for debugging.
|
| + */
|
| + static bool _TRACE_PERFORM_TASK = false;
|
| +
|
| + /**
|
| * The set of analysis options controlling the behavior of this context.
|
| */
|
| AnalysisOptionsImpl _options = new AnalysisOptionsImpl();
|
|
|
| /**
|
| + * A flag indicating whether errors related to sources in the SDK should be generated and
|
| + * reported.
|
| + */
|
| + bool _generateSdkErrors = true;
|
| +
|
| + /**
|
| * A flag indicating whether this context is disposed.
|
| */
|
| bool _disposed = false;
|
| @@ -3724,6 +3771,11 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| SourceFactory _sourceFactory;
|
|
|
| /**
|
| + * A source representing the core library.
|
| + */
|
| + Source _coreLibrarySource;
|
| +
|
| + /**
|
| * A table mapping the sources known to the context to the information known about the source.
|
| */
|
| AnalysisCache _cache;
|
| @@ -3734,6 +3786,12 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| List<Source> _priorityOrder = Source.EMPTY_ARRAY;
|
|
|
| /**
|
| + * An array containing sources whose AST structure is needed in order to resolve the next library
|
| + * to be resolved.
|
| + */
|
| + Set<Source> _neededForResolution = null;
|
| +
|
| + /**
|
| * A table mapping sources to the change notices that are waiting to be returned related to that
|
| * source.
|
| */
|
| @@ -3824,26 +3882,32 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| // that might have been referencing the not-yet-existing source that was just added. Longer
|
| // term we need to keep track of which libraries are referencing non-existing sources and
|
| // only re-analyze those libraries.
|
| - _logInformation("Added Dart sources, invalidating all resolution information");
|
| + // logInformation("Added Dart sources, invalidating all resolution information");
|
| + List<Source> sourcesToInvalidate = new List<Source>();
|
| for (MapEntry<Source, SourceEntry> mapEntry in _cache.entrySet()) {
|
| Source source = mapEntry.getKey();
|
| SourceEntry sourceEntry = mapEntry.getValue();
|
| if (!source.isInSystemLibrary && sourceEntry is DartEntry) {
|
| - DartEntry dartEntry = sourceEntry;
|
| - DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| - _removeFromParts(source, dartEntry);
|
| - dartCopy.invalidateAllResolutionInformation();
|
| - mapEntry.setValue(dartCopy);
|
| - SourcePriority priority = SourcePriority.UNKNOWN;
|
| - SourceKind kind = dartCopy.kind;
|
| - if (identical(kind, SourceKind.LIBRARY)) {
|
| - priority = SourcePriority.LIBRARY;
|
| - } else if (identical(kind, SourceKind.PART)) {
|
| - priority = SourcePriority.NORMAL_PART;
|
| - }
|
| - _workManager.add(source, priority);
|
| + sourcesToInvalidate.add(source);
|
| }
|
| }
|
| + int count = sourcesToInvalidate.length;
|
| + for (int i = 0; i < count; i++) {
|
| + Source source = sourcesToInvalidate[i];
|
| + DartEntry dartEntry = _getReadableDartEntry(source);
|
| + _removeFromParts(source, dartEntry);
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.invalidateAllResolutionInformation();
|
| + _cache.put(source, dartCopy);
|
| + SourcePriority priority = SourcePriority.UNKNOWN;
|
| + SourceKind kind = dartCopy.kind;
|
| + if (identical(kind, SourceKind.LIBRARY)) {
|
| + priority = SourcePriority.LIBRARY;
|
| + } else if (identical(kind, SourceKind.PART)) {
|
| + priority = SourcePriority.NORMAL_PART;
|
| + }
|
| + _workManager.add(source, priority);
|
| + }
|
| }
|
| }
|
|
|
| @@ -4028,6 +4092,20 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| AnalysisOptions get analysisOptions => _options;
|
|
|
| @override
|
| + AngularApplication getAngularApplicationWithHtml(Source htmlSource) {
|
| + SourceEntry sourceEntry = _getReadableSourceEntryOrNull(htmlSource);
|
| + if (sourceEntry is HtmlEntry) {
|
| + HtmlEntry htmlEntry = sourceEntry;
|
| + AngularApplication application = htmlEntry.getValue(HtmlEntry.ANGULAR_APPLICATION);
|
| + if (application != null) {
|
| + return application;
|
| + }
|
| + return htmlEntry.getValue(HtmlEntry.ANGULAR_ENTRY);
|
| + }
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| CompilationUnitElement getCompilationUnitElement(Source unitSource, Source librarySource) {
|
| LibraryElement libraryElement = getLibraryElement(librarySource);
|
| if (libraryElement != null) {
|
| @@ -4201,6 +4279,16 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
|
|
| @override
|
| + List<Source> getLibrariesReferencedFromHtml(Source htmlSource) {
|
| + SourceEntry sourceEntry = _getReadableSourceEntryOrNull(htmlSource);
|
| + if (sourceEntry is HtmlEntry) {
|
| + HtmlEntry htmlEntry = sourceEntry;
|
| + return htmlEntry.getValue(HtmlEntry.REFERENCED_LIBRARIES);
|
| + }
|
| + return Source.EMPTY_ARRAY;
|
| + }
|
| +
|
| + @override
|
| LibraryElement getLibraryElement(Source source) {
|
| SourceEntry sourceEntry = _getReadableSourceEntryOrNull(source);
|
| if (sourceEntry is DartEntry) {
|
| @@ -4331,6 +4419,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
|
|
| @override
|
| AnalysisContentStatistics get statistics {
|
| + bool hintsEnabled = _options.hint;
|
| AnalysisContentStatisticsImpl statistics = new AnalysisContentStatisticsImpl();
|
| for (MapEntry<Source, SourceEntry> mapEntry in _cache.entrySet()) {
|
| statistics.addSource(mapEntry.getKey());
|
| @@ -4355,10 +4444,14 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| // get library-specific values
|
| List<Source> librarySources = getLibrariesContaining(source);
|
| for (Source librarySource in librarySources) {
|
| - statistics.putCacheItemInLibrary(dartEntry, librarySource, DartEntry.HINTS);
|
| statistics.putCacheItemInLibrary(dartEntry, librarySource, DartEntry.RESOLUTION_ERRORS);
|
| statistics.putCacheItemInLibrary(dartEntry, librarySource, DartEntry.RESOLVED_UNIT);
|
| - statistics.putCacheItemInLibrary(dartEntry, librarySource, DartEntry.VERIFICATION_ERRORS);
|
| + if (_generateSdkErrors || !source.isInSystemLibrary) {
|
| + statistics.putCacheItemInLibrary(dartEntry, librarySource, DartEntry.VERIFICATION_ERRORS);
|
| + if (hintsEnabled) {
|
| + statistics.putCacheItemInLibrary(dartEntry, librarySource, DartEntry.HINTS);
|
| + }
|
| + }
|
| }
|
| } else if (entry is HtmlEntry) {
|
| HtmlEntry htmlEntry = entry;
|
| @@ -4379,17 +4472,6 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
|
|
| @override
|
| - TimestampedData<CompilationUnit> internalResolveCompilationUnit(Source unitSource, LibraryElement libraryElement) {
|
| - DartEntry dartEntry = _getReadableDartEntry(unitSource);
|
| - if (dartEntry == null) {
|
| - throw new AnalysisException.con1("internalResolveCompilationUnit invoked for non-Dart file: ${unitSource.fullName}");
|
| - }
|
| - Source librarySource = libraryElement.source;
|
| - dartEntry = _cacheDartResolutionData(unitSource, librarySource, dartEntry, DartEntry.RESOLVED_UNIT);
|
| - return new TimestampedData<CompilationUnit>(dartEntry.modificationTime, dartEntry.getValueInLibrary(DartEntry.RESOLVED_UNIT, librarySource));
|
| - }
|
| -
|
| - @override
|
| bool isClientLibrary(Source librarySource) {
|
| SourceEntry sourceEntry = _getReadableSourceEntry(librarySource);
|
| if (sourceEntry is DartEntry) {
|
| @@ -4440,6 +4522,9 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
|
|
| @override
|
| AnalysisResult performAnalysisTask() {
|
| + if (_TRACE_PERFORM_TASK) {
|
| + print("----------------------------------------");
|
| + }
|
| int getStart = JavaSystem.currentTimeMillis();
|
| AnalysisTask task = nextAnalysisTask;
|
| int getEnd = JavaSystem.currentTimeMillis();
|
| @@ -4450,10 +4535,16 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| return new AnalysisResult(_getChangeNotices(true), getEnd - getStart, null, -1);
|
| }
|
| String taskDescriptor = task.toString();
|
| - if (_recentTasks.add(taskDescriptor)) {
|
| - _logInformation("Performing task: ${taskDescriptor}");
|
| - } else {
|
| - _logInformation("*** Performing repeated task: ${taskDescriptor}");
|
| + // if (recentTasks.add(taskDescriptor)) {
|
| + // logInformation("Performing task: " + taskDescriptor);
|
| + // } else {
|
| + // if (TRACE_PERFORM_TASK) {
|
| + // System.out.print("* ");
|
| + // }
|
| + // logInformation("*** Performing repeated task: " + taskDescriptor);
|
| + // }
|
| + if (_TRACE_PERFORM_TASK) {
|
| + print(taskDescriptor);
|
| }
|
| int performStart = JavaSystem.currentTimeMillis();
|
| try {
|
| @@ -4506,7 +4597,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
|
|
| @override
|
| void set analysisOptions(AnalysisOptions options) {
|
| - bool needsRecompute = this._options.analyzeFunctionBodies != options.analyzeFunctionBodies || this._options.dart2jsHint != options.dart2jsHint || (this._options.hint && !options.hint) || this._options.preserveComments != options.preserveComments;
|
| + bool needsRecompute = this._options.analyzeFunctionBodies != options.analyzeFunctionBodies || this._options.generateSdkErrors != options.generateSdkErrors || this._options.dart2jsHint != options.dart2jsHint || (this._options.hint && !options.hint) || this._options.preserveComments != options.preserveComments;
|
| int cacheSize = options.cacheSize;
|
| if (this._options.cacheSize != cacheSize) {
|
| this._options.cacheSize = cacheSize;
|
| @@ -4524,10 +4615,12 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
| }
|
| this._options.analyzeFunctionBodies = options.analyzeFunctionBodies;
|
| + this._options.generateSdkErrors = options.generateSdkErrors;
|
| this._options.dart2jsHint = options.dart2jsHint;
|
| this._options.hint = options.hint;
|
| this._options.incremental = options.incremental;
|
| this._options.preserveComments = options.preserveComments;
|
| + _generateSdkErrors = options.generateSdkErrors;
|
| if (needsRecompute) {
|
| _invalidateAllResolutionInformation();
|
| }
|
| @@ -4614,17 +4707,145 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
| factory.context = this;
|
| _sourceFactory = factory;
|
| + _coreLibrarySource = _sourceFactory.forUri(DartSdk.DART_CORE);
|
| _invalidateAllResolutionInformation();
|
| }
|
|
|
| /**
|
| - * 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.
|
| + * Record the results produced by performing a [ResolveDartLibraryCycleTask]. 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 recordResolveDartLibraryCycleTaskResults(ResolveDartLibraryCycleTask task) {
|
| + LibraryResolver2 resolver = task.libraryResolver;
|
| + AnalysisException thrownException = task.exception;
|
| + DartEntry unitEntry = null;
|
| + Source unitSource = task.unitSource;
|
| + if (resolver != null) {
|
| + //
|
| + // The resolver should only be null if an exception was thrown before (or while) it was
|
| + // being created.
|
| + //
|
| + List<ResolvableLibrary> resolvedLibraries = resolver.resolvedLibraries;
|
| + if (resolvedLibraries == null) {
|
| + //
|
| + // The resolved libraries should only be null if an exception was thrown during resolution.
|
| + //
|
| + unitEntry = _getReadableDartEntry(unitSource);
|
| + if (unitEntry == null) {
|
| + throw new AnalysisException.con1("A Dart file became a non-Dart file: ${unitSource.fullName}");
|
| + }
|
| + DartEntryImpl dartCopy = unitEntry.writableCopy;
|
| + dartCopy.recordResolutionError();
|
| + dartCopy.exception = thrownException;
|
| + _cache.put(unitSource, dartCopy);
|
| + _cache.remove(unitSource);
|
| + if (thrownException != null) {
|
| + throw thrownException;
|
| + }
|
| + return dartCopy;
|
| + }
|
| + if (_allModificationTimesMatch(resolvedLibraries)) {
|
| + Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML);
|
| + RecordingErrorListener errorListener = resolver.errorListener;
|
| + for (ResolvableLibrary library in resolvedLibraries) {
|
| + Source librarySource = library.librarySource;
|
| + for (Source source in library.compilationUnitSources) {
|
| + CompilationUnit unit = library.getAST(source);
|
| + List<AnalysisError> errors = errorListener.getErrorsForSource(source);
|
| + LineInfo lineInfo = getLineInfo(source);
|
| + DartEntry dartEntry = _cache.get(source) as DartEntry;
|
| + int sourceTime = getModificationStamp(source);
|
| + 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) {
|
| + dartCopy.setValue(SourceEntry.LINE_INFO, lineInfo);
|
| + dartCopy.setState(DartEntry.PARSED_UNIT, CacheState.FLUSHED);
|
| + dartCopy.setValueInLibrary(DartEntry.RESOLVED_UNIT, librarySource, unit);
|
| + dartCopy.setValueInLibrary(DartEntry.RESOLUTION_ERRORS, librarySource, errors);
|
| + if (source == librarySource) {
|
| + _recordElementData(dartEntry, dartCopy, library.libraryElement, librarySource, htmlSource);
|
| + }
|
| + _cache.storedAst(source);
|
| + } else {
|
| + dartCopy.recordResolutionError();
|
| + _cache.remove(source);
|
| + }
|
| + dartCopy.exception = thrownException;
|
| + _cache.put(source, dartCopy);
|
| + if (source != librarySource) {
|
| + _workManager.add(source, SourcePriority.PRIORITY_PART);
|
| + }
|
| + if (source == unitSource) {
|
| + unitEntry = dartCopy;
|
| + }
|
| + if (_generateSdkErrors || !source.isInSystemLibrary) {
|
| + ChangeNoticeImpl notice = _getNotice(source);
|
| + notice.compilationUnit = unit;
|
| + notice.setErrors(dartCopy.allErrors, lineInfo);
|
| + }
|
| + }
|
| + }
|
| + } else {
|
| + PrintStringWriter writer = new PrintStringWriter();
|
| + writer.println("Library resolution results discarded for");
|
| + for (ResolvableLibrary library in resolvedLibraries) {
|
| + for (Source source in library.compilationUnitSources) {
|
| + DartEntry dartEntry = _getReadableDartEntry(source);
|
| + if (dartEntry != null) {
|
| + int resultTime = library.getModificationTime(source);
|
| + writer.println(" ${_debuggingString(source)}; sourceTime = ${getModificationStamp(source)}, resultTime = ${resultTime}, cacheTime = ${dartEntry.modificationTime}");
|
| + 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.recordResolutionNotInProcess();
|
| + } 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.recordResolutionError();
|
| + _cache.remove(source);
|
| + }
|
| + dartCopy.exception = thrownException;
|
| + _cache.put(source, dartCopy);
|
| + if (source == unitSource) {
|
| + unitEntry = dartCopy;
|
| + }
|
| + } else {
|
| + writer.println(" ${_debuggingString(source)}; sourceTime = ${getModificationStamp(source)}, no entry");
|
| + }
|
| + }
|
| + }
|
| + _logInformation(writer.toString());
|
| + }
|
| + }
|
| + if (thrownException != null) {
|
| + throw thrownException;
|
| + }
|
| + if (unitEntry == null) {
|
| + unitEntry = _getReadableDartEntry(unitSource);
|
| + if (unitEntry == null) {
|
| + throw new AnalysisException.con1("A Dart file became a non-Dart file: ${unitSource.fullName}");
|
| + }
|
| + }
|
| + return unitEntry;
|
| + }
|
| +
|
| DartEntry recordResolveDartLibraryTaskResults(ResolveDartLibraryTask task) {
|
| LibraryResolver resolver = task.libraryResolver;
|
| AnalysisException thrownException = task.exception;
|
| @@ -4654,7 +4875,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
| return dartCopy;
|
| }
|
| - if (_allModificationTimesMatch(resolvedLibraries)) {
|
| + if (_allModificationTimesMatch2(resolvedLibraries)) {
|
| Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML);
|
| RecordingErrorListener errorListener = resolver.errorListener;
|
| for (Library library in resolvedLibraries) {
|
| @@ -4695,9 +4916,11 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| if (source == unitSource) {
|
| unitEntry = dartCopy;
|
| }
|
| - ChangeNoticeImpl notice = _getNotice(source);
|
| - notice.compilationUnit = unit;
|
| - notice.setErrors(dartCopy.allErrors, lineInfo);
|
| + if (_generateSdkErrors || !source.isInSystemLibrary) {
|
| + ChangeNoticeImpl notice = _getNotice(source);
|
| + notice.compilationUnit = unit;
|
| + notice.setErrors(dartCopy.allErrors, lineInfo);
|
| + }
|
| }
|
| }
|
| } else {
|
| @@ -4786,7 +5009,38 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * @throws AnalysisException if any of the modification times could not be determined (this should
|
| * not happen)
|
| */
|
| - bool _allModificationTimesMatch(Set<Library> resolvedLibraries) {
|
| + bool _allModificationTimesMatch(List<ResolvableLibrary> resolvedLibraries) {
|
| + bool allTimesMatch = true;
|
| + for (ResolvableLibrary library in resolvedLibraries) {
|
| + for (Source source in library.compilationUnitSources) {
|
| + DartEntry dartEntry = _getReadableDartEntry(source);
|
| + if (dartEntry == null) {
|
| + // 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: ${source.fullName}");
|
| + }
|
| + int sourceTime = getModificationStamp(source);
|
| + int resultTime = library.getModificationTime(source);
|
| + if (sourceTime != resultTime) {
|
| + // The source has changed without the context being notified. Simulate notification.
|
| + _sourceChanged(source);
|
| + allTimesMatch = false;
|
| + }
|
| + }
|
| + }
|
| + return allTimesMatch;
|
| + }
|
| +
|
| + /**
|
| + * Return `true` if the modification times of the sources used by the given library resolver
|
| + * to resolve one or more libraries are consistent with the modification times in the cache.
|
| + *
|
| + * @param resolver the library resolver used to resolve one or more libraries
|
| + * @return `true` if we should record the results of the resolution
|
| + * @throws AnalysisException if any of the modification times could not be determined (this should
|
| + * not happen)
|
| + */
|
| + bool _allModificationTimesMatch2(Set<Library> resolvedLibraries) {
|
| bool allTimesMatch = true;
|
| for (Library library in resolvedLibraries) {
|
| for (Source source in library.compilationUnitSources) {
|
| @@ -4814,6 +5068,8 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * [CacheState#ERROR]. This method assumes that the data can be produced by generating hints
|
| * for the library if the data is not already cached.
|
| *
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| + *
|
| * @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
|
| @@ -4831,7 +5087,25 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| // If not, compute the information. Unless the modification date of the source continues to
|
| // change, this loop will eventually terminate.
|
| //
|
| - dartEntry = new GenerateDartHintsTask(this, getLibraryElement(librarySource)).perform(_resultRecorder) as DartEntry;
|
| + DartEntry libraryEntry = _getReadableDartEntry(librarySource);
|
| + libraryEntry = _cacheDartResolutionData(librarySource, librarySource, libraryEntry, DartEntry.ELEMENT);
|
| + LibraryElement libraryElement = libraryEntry.getValue(DartEntry.ELEMENT);
|
| + CompilationUnitElement definingUnit = libraryElement.definingCompilationUnit;
|
| + List<CompilationUnitElement> parts = libraryElement.parts;
|
| + List<TimestampedData<CompilationUnit>> units = new List<TimestampedData>(parts.length + 1);
|
| + units[0] = _getResolvedUnit(definingUnit, librarySource);
|
| + if (units[0] == null) {
|
| + Source source = definingUnit.source;
|
| + units[0] = new TimestampedData<CompilationUnit>(getModificationStamp(source), resolveCompilationUnit(source, libraryElement));
|
| + }
|
| + for (int i = 0; i < parts.length; i++) {
|
| + units[i + 1] = _getResolvedUnit(parts[i], librarySource);
|
| + if (units[i + 1] == null) {
|
| + Source source = parts[i].source;
|
| + units[i + 1] = new TimestampedData<CompilationUnit>(getModificationStamp(source), resolveCompilationUnit(source, libraryElement));
|
| + }
|
| + }
|
| + dartEntry = new GenerateDartHintsTask(this, units, getLibraryElement(librarySource)).perform(_resultRecorder) as DartEntry;
|
| state = dartEntry.getStateInLibrary(descriptor, librarySource);
|
| }
|
| return dartEntry;
|
| @@ -4842,7 +5116,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * by the given descriptor is either [CacheState#VALID] or [CacheState#ERROR]. This
|
| * method assumes that the data can be produced by parsing the source if it is not already cached.
|
| *
|
| - * <b>Note:</b> This method cannot be used in an async environment
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| *
|
| * @param source the source representing the Dart file
|
| * @param dartEntry the cache entry associated with the Dart file
|
| @@ -4879,6 +5153,8 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * [CacheState#ERROR]. This method assumes that the data can be produced by resolving the
|
| * source in the context of the library if it is not already cached.
|
| *
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| + *
|
| * @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
|
| @@ -4910,7 +5186,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * method assumes that the data can be produced by scanning the source if it is not already
|
| * cached.
|
| *
|
| - * <b>Note:</b> This method cannot be used in an async environment
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| *
|
| * @param source the source representing the Dart file
|
| * @param dartEntry the cache entry associated with the Dart file
|
| @@ -4968,7 +5244,8 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| // If not, compute the information. Unless the modification date of the source continues to
|
| // change, this loop will eventually terminate.
|
| //
|
| - dartEntry = new GenerateDartErrorsTask(this, unitSource, getLibraryElement(librarySource)).perform(_resultRecorder) as DartEntry;
|
| + LibraryElement library = computeLibraryElement(librarySource);
|
| + dartEntry = new GenerateDartErrorsTask(this, unitSource, dartEntry.modificationTime, resolveCompilationUnit(unitSource, library), library).perform(_resultRecorder) as DartEntry;
|
| state = dartEntry.getStateInLibrary(descriptor, librarySource);
|
| }
|
| return dartEntry;
|
| @@ -4980,7 +5257,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * [CacheState#ERROR]. This method assumes that the data can be produced by parsing the
|
| * source if it is not already cached.
|
| *
|
| - * <b>Note:</b> This method cannot be used in an async environment
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| *
|
| * @param source the source representing the HTML file
|
| * @param htmlEntry the cache entry associated with the HTML file
|
| @@ -5026,7 +5303,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * [CacheState#ERROR]. This method assumes that the data can be produced by resolving the
|
| * source if it is not already cached.
|
| *
|
| - * <b>Note:</b> This method cannot be used in an async environment
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| *
|
| * @param source the source representing the HTML file
|
| * @param dartEntry the cache entry associated with the HTML file
|
| @@ -5093,32 +5370,91 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
|
|
| /**
|
| - * Create a [GetContentTask] for the given source, marking the content as being in-process.
|
| + * Create a [GenerateDartErrorsTask] for the given source, marking the verification errors
|
| + * as being in-process.
|
| *
|
| - * @param source the source whose content is to be accessed
|
| - * @param sourceEntry the entry for the source
|
| + * @param source the source whose content is to be verified
|
| + * @param dartEntry the entry for the source
|
| + * @param librarySource the source for the library containing the source
|
| + * @param libraryEntry the entry for the library
|
| * @return task data representing the created task
|
| */
|
| - AnalysisContextImpl_TaskData _createGetContentTask(Source source, SourceEntry sourceEntry) {
|
| - SourceEntryImpl sourceCopy = sourceEntry.writableCopy;
|
| - sourceCopy.setState(SourceEntry.CONTENT, CacheState.IN_PROCESS);
|
| - _cache.put(source, sourceCopy);
|
| - return new AnalysisContextImpl_TaskData(new GetContentTask(this, source), false);
|
| + AnalysisContextImpl_TaskData _createGenerateDartErrorsTask(Source source, DartEntry dartEntry, Source librarySource, SourceEntry libraryEntry) {
|
| + if (dartEntry.getStateInLibrary(DartEntry.RESOLVED_UNIT, librarySource) != CacheState.VALID || libraryEntry.getState(DartEntry.ELEMENT) != CacheState.VALID) {
|
| + }
|
| + CompilationUnit unit = dartEntry.getValueInLibrary(DartEntry.RESOLVED_UNIT, librarySource);
|
| + LibraryElement libraryElement = libraryEntry.getValue(DartEntry.ELEMENT);
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.setStateInLibrary(DartEntry.VERIFICATION_ERRORS, librarySource, CacheState.IN_PROCESS);
|
| + _cache.put(source, dartCopy);
|
| + return new AnalysisContextImpl_TaskData(new GenerateDartErrorsTask(this, source, dartCopy.modificationTime, unit, libraryElement), false);
|
| }
|
|
|
| /**
|
| - * Create a [ParseDartTask] for the given source, marking the parse errors as being
|
| + * Create a [GenerateDartHintsTask] for the given source, marking the hints as being
|
| * in-process.
|
| *
|
| - * @param source the source whose content is to be parsed
|
| + * @param source the source whose content is to be verified
|
| * @param dartEntry the entry for the source
|
| + * @param librarySource the source for the library containing the source
|
| + * @param libraryEntry the entry for the library
|
| * @return task data representing the created task
|
| */
|
| - AnalysisContextImpl_TaskData _createParseDartTask(Source source, DartEntry dartEntry) {
|
| - if (dartEntry.getState(DartEntry.TOKEN_STREAM) != CacheState.VALID || dartEntry.getState(SourceEntry.LINE_INFO) != CacheState.VALID) {
|
| - return _createScanDartTask(source, dartEntry);
|
| + AnalysisContextImpl_TaskData _createGenerateDartHintsTask(Source source, DartEntry dartEntry, Source librarySource, DartEntry libraryEntry) {
|
| + if (libraryEntry.getState(DartEntry.ELEMENT) != CacheState.VALID) {
|
| + return _createResolveDartLibraryTask(librarySource, libraryEntry);
|
| }
|
| - Token tokenStream = dartEntry.getValue(DartEntry.TOKEN_STREAM);
|
| + LibraryElement libraryElement = libraryEntry.getValue(DartEntry.ELEMENT);
|
| + CompilationUnitElement definingUnit = libraryElement.definingCompilationUnit;
|
| + List<CompilationUnitElement> parts = libraryElement.parts;
|
| + List<TimestampedData<CompilationUnit>> units = new List<TimestampedData>(parts.length + 1);
|
| + units[0] = _getResolvedUnit(definingUnit, librarySource);
|
| + if (units[0] == null) {
|
| + // TODO(brianwilkerson) We should return a ResolveDartUnitTask (unless there are multiple ASTs
|
| + // that need to be resolved.
|
| + return _createResolveDartLibraryTask(librarySource, libraryEntry);
|
| + }
|
| + for (int i = 0; i < parts.length; i++) {
|
| + units[i + 1] = _getResolvedUnit(parts[i], librarySource);
|
| + if (units[i + 1] == null) {
|
| + // TODO(brianwilkerson) We should return a ResolveDartUnitTask (unless there are multiple
|
| + // ASTs that need to be resolved.
|
| + return _createResolveDartLibraryTask(librarySource, libraryEntry);
|
| + }
|
| + }
|
| + DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| + dartCopy.setStateInLibrary(DartEntry.HINTS, librarySource, CacheState.IN_PROCESS);
|
| + _cache.put(source, dartCopy);
|
| + return new AnalysisContextImpl_TaskData(new GenerateDartHintsTask(this, units, libraryElement), false);
|
| + }
|
| +
|
| + /**
|
| + * Create a [GetContentTask] for the given source, marking the content as being in-process.
|
| + *
|
| + * @param source the source whose content is to be accessed
|
| + * @param sourceEntry the entry for the source
|
| + * @return task data representing the created task
|
| + */
|
| + AnalysisContextImpl_TaskData _createGetContentTask(Source source, SourceEntry sourceEntry) {
|
| + SourceEntryImpl sourceCopy = sourceEntry.writableCopy;
|
| + sourceCopy.setState(SourceEntry.CONTENT, CacheState.IN_PROCESS);
|
| + _cache.put(source, sourceCopy);
|
| + return new AnalysisContextImpl_TaskData(new GetContentTask(this, source), false);
|
| + }
|
| +
|
| + /**
|
| + * Create a [ParseDartTask] for the given source, marking the parse errors as being
|
| + * in-process.
|
| + *
|
| + * @param source the source whose content is to be parsed
|
| + * @param dartEntry the entry for the source
|
| + * @return task data representing the created task
|
| + */
|
| + AnalysisContextImpl_TaskData _createParseDartTask(Source source, DartEntry dartEntry) {
|
| + if (dartEntry.getState(DartEntry.TOKEN_STREAM) != CacheState.VALID || dartEntry.getState(SourceEntry.LINE_INFO) != CacheState.VALID) {
|
| + return _createScanDartTask(source, dartEntry);
|
| + }
|
| + Token tokenStream = dartEntry.getValue(DartEntry.TOKEN_STREAM);
|
| DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| dartCopy.setState(DartEntry.TOKEN_STREAM, CacheState.FLUSHED);
|
| dartCopy.setState(DartEntry.PARSE_ERRORS, CacheState.IN_PROCESS);
|
| @@ -5185,6 +5521,29 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
|
|
| /**
|
| + * Create a [ResolveDartLibraryTask] for the given source, marking the element model as
|
| + * being in-process.
|
| + *
|
| + * @param source the source whose content is to be resolved
|
| + * @param dartEntry the entry for the source
|
| + * @return task data representing the created task
|
| + */
|
| + AnalysisContextImpl_TaskData _createResolveDartLibraryTask(Source source, DartEntry dartEntry) {
|
| + try {
|
| + AnalysisContextImpl_CycleBuilder builder = new AnalysisContextImpl_CycleBuilder(this);
|
| + builder.computeCycleContaining(source);
|
| + AnalysisContextImpl_TaskData taskData = builder.taskData;
|
| + if (taskData != null) {
|
| + return taskData;
|
| + }
|
| + return new AnalysisContextImpl_TaskData(new ResolveDartLibraryCycleTask(this, source, source, builder.librariesInCycle), false);
|
| + } on AnalysisException catch (exception) {
|
| + AnalysisEngine.instance.logger.logError2("Internal error trying to compute the next analysis task", exception);
|
| + }
|
| + return new AnalysisContextImpl_TaskData(null, false);
|
| + }
|
| +
|
| + /**
|
| * Create a [ResolveHtmlTask] for the given source, marking the resolved unit as being
|
| * in-process.
|
| *
|
| @@ -5278,6 +5637,8 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * the given descriptor that is associated with that source. This method assumes that the data can
|
| * be produced by generating hints for the library if it is not already cached.
|
| *
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| + *
|
| * @param unitSource the source representing the Dart file
|
| * @param librarySource the source representing the library containing the Dart file
|
| * @param dartEntry the entry representing the Dart file
|
| @@ -5299,7 +5660,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * associated with that source. This method assumes that the data can be produced by parsing the
|
| * source if it is not already cached.
|
| *
|
| - * <b>Note:</b> This method cannot be used in an async environment
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| *
|
| * @param source the source representing the Dart file
|
| * @param dartEntry the cache entry associated with the Dart file
|
| @@ -5321,7 +5682,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * associated with that source, or the given default value if the source is not a Dart file. This
|
| * method assumes that the data can be produced by parsing the source if it is not already cached.
|
| *
|
| - * <b>Note:</b> This method cannot be used in an async environment
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| *
|
| * @param source the source representing the Dart file
|
| * @param descriptor the descriptor representing the data to be returned
|
| @@ -5347,6 +5708,8 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * the given descriptor that is associated with that source. This method assumes that the data can
|
| * be produced by resolving the source in the context of the library if it is not already cached.
|
| *
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| + *
|
| * @param unitSource the source representing the Dart file
|
| * @param librarySource the source representing the library containing the Dart file
|
| * @param dartEntry the entry representing the Dart file
|
| @@ -5371,6 +5734,8 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * source is not a Dart file. This method assumes that the data can be produced by resolving the
|
| * source in the context of the library if it is not already cached.
|
| *
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| + *
|
| * @param unitSource the source representing the Dart file
|
| * @param librarySource the source representing the library containing the Dart file
|
| * @param descriptor the descriptor representing the data to be returned
|
| @@ -5397,7 +5762,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * associated with that source. This method assumes that the data can be produced by scanning the
|
| * source if it is not already cached.
|
| *
|
| - * <b>Note:</b> This method cannot be used in an async environment
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| *
|
| * @param source the source representing the Dart file
|
| * @param dartEntry the cache entry associated with the Dart file
|
| @@ -5416,7 +5781,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * method assumes that the data can be produced by scanning the source if it is not already
|
| * cached.
|
| *
|
| - * <b>Note:</b> This method cannot be used in an async environment
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| *
|
| * @param source the source representing the Dart file
|
| * @param descriptor the descriptor representing the data to be returned
|
| @@ -5462,7 +5827,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * associated with that source, or the given default value if the source is not an HTML file. This
|
| * method assumes that the data can be produced by parsing the source if it is not already cached.
|
| *
|
| - * <b>Note:</b> This method cannot be used in an async environment
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| *
|
| * @param source the source representing the Dart file
|
| * @param descriptor the descriptor representing the data to be returned
|
| @@ -5489,7 +5854,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * method assumes that the data can be produced by resolving the source if it is not already
|
| * cached.
|
| *
|
| - * <b>Note:</b> This method cannot be used in an async environment
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| *
|
| * @param source the source representing the HTML file
|
| * @param descriptor the descriptor representing the data to be returned
|
| @@ -5516,7 +5881,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| * associated with that source. This method assumes that the data can be produced by resolving the
|
| * source if it is not already cached.
|
| *
|
| - * <b>Note:</b> This method cannot be used in an async environment
|
| + * <b>Note:</b> This method cannot be used in an async environment.
|
| *
|
| * @param source the source representing the HTML file
|
| * @param htmlEntry the entry representing the HTML file
|
| @@ -5541,7 +5906,6 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| */
|
| AnalysisTask get nextAnalysisTask {
|
| bool hintsEnabled = _options.hint;
|
| - bool sdkErrorsEnabled = _options.generateSdkErrors;
|
| bool hasBlockedTask = false;
|
| //
|
| // Look for incremental analysis
|
| @@ -5554,8 +5918,10 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| //
|
| // Look for a priority source that needs to be analyzed.
|
| //
|
| - for (Source source in _priorityOrder) {
|
| - AnalysisContextImpl_TaskData taskData = _getNextAnalysisTaskForSource(source, _cache.get(source), true, hintsEnabled, sdkErrorsEnabled);
|
| + int priorityCount = _priorityOrder.length;
|
| + for (int i = 0; i < priorityCount; i++) {
|
| + Source source = _priorityOrder[i];
|
| + AnalysisContextImpl_TaskData taskData = _getNextAnalysisTaskForSource(source, _cache.get(source), true, hintsEnabled);
|
| AnalysisTask task = taskData.task;
|
| if (task != null) {
|
| return task;
|
| @@ -5563,6 +5929,32 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| hasBlockedTask = true;
|
| }
|
| }
|
| + if (_neededForResolution != null) {
|
| + List<Source> sourcesToRemove = new List<Source>();
|
| + for (Source source in _neededForResolution) {
|
| + SourceEntry sourceEntry = _cache.get(source);
|
| + if (sourceEntry is DartEntry) {
|
| + DartEntry dartEntry = sourceEntry;
|
| + if (!dartEntry.hasResolvableCompilationUnit) {
|
| + if (identical(dartEntry.getState(DartEntry.PARSED_UNIT), CacheState.ERROR)) {
|
| + sourcesToRemove.add(source);
|
| + } else {
|
| + AnalysisContextImpl_TaskData taskData = _createParseDartTask(source, dartEntry);
|
| + AnalysisTask task = taskData.task;
|
| + if (task != null) {
|
| + return task;
|
| + } else if (taskData.isBlocked) {
|
| + hasBlockedTask = true;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| + int count = sourcesToRemove.length;
|
| + for (int i = 0; i < count; i++) {
|
| + _neededForResolution.remove(sourcesToRemove[i]);
|
| + }
|
| + }
|
| //
|
| // Look for a non-priority source that needs to be analyzed.
|
| //
|
| @@ -5570,9 +5962,13 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| WorkManager_WorkIterator sources = _workManager.iterator();
|
| while (sources.hasNext) {
|
| Source source = sources.next();
|
| - AnalysisContextImpl_TaskData taskData = _getNextAnalysisTaskForSource(source, _cache.get(source), false, hintsEnabled, sdkErrorsEnabled);
|
| + AnalysisContextImpl_TaskData taskData = _getNextAnalysisTaskForSource(source, _cache.get(source), false, hintsEnabled);
|
| AnalysisTask task = taskData.task;
|
| if (task != null) {
|
| + int count = sourcesToRemove.length;
|
| + for (int i = 0; i < count; i++) {
|
| + _workManager.remove(sourcesToRemove[i]);
|
| + }
|
| return task;
|
| } else if (taskData.isBlocked) {
|
| hasBlockedTask = true;
|
| @@ -5614,11 +6010,9 @@ 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
|
| */
|
| - AnalysisContextImpl_TaskData _getNextAnalysisTaskForSource(Source source, SourceEntry sourceEntry, bool isPriority, bool hintsEnabled, bool sdkErrorsEnabled) {
|
| + AnalysisContextImpl_TaskData _getNextAnalysisTaskForSource(Source source, SourceEntry sourceEntry, bool isPriority, bool hintsEnabled) {
|
| if (sourceEntry == null) {
|
| return new AnalysisContextImpl_TaskData(null, false);
|
| }
|
| @@ -5649,12 +6043,22 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| return _createParseDartTask(source, dartEntry);
|
| }
|
| }
|
| + SourceKind kind = dartEntry.getValue(DartEntry.SOURCE_KIND);
|
| + if (identical(kind, SourceKind.UNKNOWN)) {
|
| + return _createParseDartTask(source, dartEntry);
|
| + } else if (identical(kind, SourceKind.LIBRARY)) {
|
| + CacheState elementState = dartEntry.getState(DartEntry.ELEMENT);
|
| + if (identical(elementState, CacheState.INVALID)) {
|
| + return _createResolveDartLibraryTask(source, dartEntry);
|
| + }
|
| + }
|
| List<Source> librariesContaining = dartEntry.getValue(DartEntry.CONTAINING_LIBRARIES);
|
| for (Source librarySource in librariesContaining) {
|
| SourceEntry libraryEntry = _cache.get(librarySource);
|
| if (libraryEntry is DartEntry) {
|
| CacheState elementState = libraryEntry.getState(DartEntry.ELEMENT);
|
| if (identical(elementState, CacheState.INVALID) || (isPriority && identical(elementState, CacheState.FLUSHED))) {
|
| + //return createResolveDartLibraryTask(librarySource, (DartEntry) libraryEntry);
|
| DartEntryImpl libraryCopy = libraryEntry.writableCopy;
|
| libraryCopy.setState(DartEntry.ELEMENT, CacheState.IN_PROCESS);
|
| _cache.put(librarySource, libraryCopy);
|
| @@ -5669,33 +6073,23 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| //
|
| //LibraryElement libraryElement = libraryEntry.getValue(DartEntry.ELEMENT);
|
| //if (libraryElement != null) {
|
| + // return new ResolveDartUnitTask(this, source, libraryElement);
|
| + //}
|
| + // Possibly replace with: return createResolveDartLibraryTask(librarySource, (DartEntry) libraryEntry);
|
| DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| dartCopy.setStateInLibrary(DartEntry.RESOLVED_UNIT, librarySource, CacheState.IN_PROCESS);
|
| _cache.put(source, dartCopy);
|
| - //return new ResolveDartUnitTask(this, source, libraryElement);
|
| return new AnalysisContextImpl_TaskData(new ResolveDartLibraryTask(this, source, librarySource), false);
|
| }
|
| - if (sdkErrorsEnabled || !source.isInSystemLibrary) {
|
| + if (_generateSdkErrors || !source.isInSystemLibrary) {
|
| CacheState verificationErrorsState = dartEntry.getStateInLibrary(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.setStateInLibrary(DartEntry.VERIFICATION_ERRORS, librarySource, CacheState.IN_PROCESS);
|
| - _cache.put(source, dartCopy);
|
| - return new AnalysisContextImpl_TaskData(new GenerateDartErrorsTask(this, source, libraryElement), false);
|
| - }
|
| + return _createGenerateDartErrorsTask(source, dartEntry, librarySource, libraryEntry);
|
| }
|
| if (hintsEnabled) {
|
| CacheState hintsState = dartEntry.getStateInLibrary(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.setStateInLibrary(DartEntry.HINTS, librarySource, CacheState.IN_PROCESS);
|
| - _cache.put(source, dartCopy);
|
| - return new AnalysisContextImpl_TaskData(new GenerateDartHintsTask(this, libraryElement), false);
|
| - }
|
| + return _createGenerateDartHintsTask(source, dartEntry, librarySource, libraryEntry);
|
| }
|
| }
|
| }
|
| @@ -5723,12 +6117,12 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| if (_options.analyzeAngular) {
|
| // Try to resolve the HTML as an Angular entry point.
|
| CacheState angularEntryState = htmlEntry.getState(HtmlEntry.ANGULAR_ENTRY);
|
| - if (identical(angularEntryState, CacheState.INVALID)) {
|
| + if (identical(angularEntryState, CacheState.INVALID) || (isPriority && identical(angularEntryState, CacheState.FLUSHED))) {
|
| return _createResolveAngularEntryHtmlTask(source, htmlEntry);
|
| }
|
| // Try to resolve the HTML as an Angular application part.
|
| CacheState angularErrorsState = htmlEntry.getState(HtmlEntry.ANGULAR_ERRORS);
|
| - if (identical(angularErrorsState, CacheState.INVALID)) {
|
| + if (identical(angularErrorsState, CacheState.INVALID) || (isPriority && identical(angularErrorsState, CacheState.FLUSHED))) {
|
| return _createResolveAngularComponentTemplateTask(source, htmlEntry);
|
| }
|
| }
|
| @@ -5811,6 +6205,25 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| SourceEntry _getReadableSourceEntryOrNull(Source source) => _cache.get(source);
|
|
|
| /**
|
| + * Return a resolved compilation unit corresponding to the given element in the given library, or
|
| + * `null` if the information is not cached.
|
| + *
|
| + * @param element the element representing the compilation unit
|
| + * @param librarySource the source representing the library containing the unit
|
| + * @return the specified resolved compilation unit
|
| + */
|
| + TimestampedData<CompilationUnit> _getResolvedUnit(CompilationUnitElement element, Source librarySource) {
|
| + SourceEntry sourceEntry = _cache.get(element.source);
|
| + if (sourceEntry is DartEntry) {
|
| + DartEntry dartEntry = sourceEntry;
|
| + if (identical(dartEntry.getStateInLibrary(DartEntry.RESOLVED_UNIT, librarySource), CacheState.VALID)) {
|
| + return new TimestampedData<CompilationUnit>(dartEntry.modificationTime, dartEntry.getValueInLibrary(DartEntry.RESOLVED_UNIT, librarySource));
|
| + }
|
| + }
|
| + return null;
|
| + }
|
| +
|
| + /**
|
| * Return an array containing all of the sources known to this context that have the given kind.
|
| *
|
| * @param kind the kind of sources to be returned
|
| @@ -5912,7 +6325,7 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| // Angular
|
| if (_options.analyzeAngular) {
|
| CacheState angularErrorsState = htmlEntry.getState(HtmlEntry.ANGULAR_ERRORS);
|
| - if (identical(angularErrorsState, CacheState.INVALID)) {
|
| + if (identical(angularErrorsState, CacheState.INVALID) || (isPriority && identical(angularErrorsState, CacheState.FLUSHED))) {
|
| AngularApplication entryInfo = htmlEntry.getValue(HtmlEntry.ANGULAR_ENTRY);
|
| if (entryInfo != null) {
|
| sources.add(source);
|
| @@ -5999,8 +6412,10 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| 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));
|
| + if (_generateSdkErrors || !elementSource.isInSystemLibrary) {
|
| + ChangeNoticeImpl notice = _getNotice(elementSource);
|
| + notice.setErrors(dartCopy.allErrors, dartEntry.getValue(SourceEntry.LINE_INFO));
|
| + }
|
| }
|
| }
|
|
|
| @@ -6024,27 +6439,25 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| if (libraryEntry != null) {
|
| List<Source> includedParts = libraryEntry.getValue(DartEntry.INCLUDED_PARTS);
|
| DartEntryImpl libraryCopy = libraryEntry.writableCopy;
|
| - int oldTime = libraryCopy.modificationTime;
|
| + // long oldTime = libraryCopy.getModificationTime();
|
| libraryCopy.invalidateAllResolutionInformation();
|
| _cache.put(librarySource, libraryCopy);
|
| _workManager.add(librarySource, SourcePriority.LIBRARY);
|
| - if (writer != null) {
|
| - writer.println(" Invalidated library source: ${_debuggingString(librarySource)} (previously modified at ${oldTime})");
|
| - }
|
| + // if (writer != null) {
|
| + // writer.println(" Invalidated library source: " + debuggingString(librarySource)
|
| + // + " (previously modified at " + oldTime + ")");
|
| + // }
|
| for (Source partSource in includedParts) {
|
| SourceEntry partEntry = _cache.get(partSource);
|
| if (partEntry is DartEntry) {
|
| DartEntryImpl partCopy = partEntry.writableCopy;
|
| - oldTime = partCopy.modificationTime;
|
| + // oldTime = partCopy.getModificationTime();
|
| if (partEntry != libraryCopy) {
|
| partCopy.removeContainingLibrary(librarySource);
|
| _workManager.add(librarySource, SourcePriority.NORMAL_PART);
|
| }
|
| partCopy.invalidateAllResolutionInformation();
|
| _cache.put(partSource, partCopy);
|
| - if (writer != null) {
|
| - writer.println(" Invalidated part source: ${_debuggingString(partSource)} (previously modified at ${oldTime})");
|
| - }
|
| }
|
| }
|
| }
|
| @@ -6152,8 +6565,10 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| 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));
|
| + if (_generateSdkErrors || !elementSource.isInSystemLibrary) {
|
| + ChangeNoticeImpl notice = _getNotice(elementSource);
|
| + notice.setErrors(dartCopy.allErrors, computeLineInfo(elementSource));
|
| + }
|
| }
|
| }
|
| // remember Angular entry point
|
| @@ -6174,25 +6589,6 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| dartCopy.setValue(DartEntry.ELEMENT, library);
|
| dartCopy.setValue(DartEntry.IS_LAUNCHABLE, library.entryPoint != null);
|
| dartCopy.setValue(DartEntry.IS_CLIENT, _isClient(library, htmlSource, new Set<LibraryElement>()));
|
| - // TODO(brianwilkerson) Understand why we're doing this both here and in
|
| - // ResolveDartDependenciesTask and whether we should also be capturing the imported and exported
|
| - // sources here.
|
| - _removeFromParts(librarySource, dartEntry);
|
| - List<CompilationUnitElement> parts = library.parts;
|
| - int count = parts.length;
|
| - List<Source> unitSources = new List<Source>(count + 1);
|
| - unitSources[0] = library.definingCompilationUnit.source;
|
| - for (int i = 0; i < count; i++) {
|
| - Source unitSource = parts[i].source;
|
| - unitSources[i + 1] = unitSource;
|
| - DartEntry unitEntry = _getReadableDartEntry(unitSource);
|
| - if (unitSource != null) {
|
| - DartEntryImpl unitCopy = unitEntry.writableCopy;
|
| - unitCopy.addContainingLibrary(librarySource);
|
| - _cache.put(unitSource, unitCopy);
|
| - }
|
| - }
|
| - dartCopy.setValue(DartEntry.INCLUDED_PARTS, unitSources);
|
| }
|
|
|
| /**
|
| @@ -6231,8 +6627,10 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| if (thrownException == null) {
|
| dartCopy.setValueInLibrary(DartEntry.VERIFICATION_ERRORS, librarySource, task.errors);
|
| - ChangeNoticeImpl notice = _getNotice(source);
|
| - notice.setErrors(dartCopy.allErrors, dartCopy.getValue(SourceEntry.LINE_INFO));
|
| + if (_generateSdkErrors || !source.isInSystemLibrary) {
|
| + ChangeNoticeImpl notice = _getNotice(source);
|
| + notice.setErrors(dartCopy.allErrors, dartCopy.getValue(SourceEntry.LINE_INFO));
|
| + }
|
| } else {
|
| dartCopy.setStateInLibrary(DartEntry.VERIFICATION_ERRORS, librarySource, CacheState.ERROR);
|
| }
|
| @@ -6331,8 +6729,10 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| DartEntryImpl dartCopy = dartEntry.writableCopy;
|
| if (thrownException == null) {
|
| dartCopy.setValueInLibrary(DartEntry.HINTS, librarySource, results.data);
|
| - ChangeNoticeImpl notice = _getNotice(unitSource);
|
| - notice.setErrors(dartCopy.allErrors, dartCopy.getValue(SourceEntry.LINE_INFO));
|
| + if (_generateSdkErrors || !unitSource.isInSystemLibrary) {
|
| + ChangeNoticeImpl notice = _getNotice(unitSource);
|
| + notice.setErrors(dartCopy.allErrors, dartCopy.getValue(SourceEntry.LINE_INFO));
|
| + }
|
| } else {
|
| dartCopy.setStateInLibrary(DartEntry.HINTS, librarySource, CacheState.ERROR);
|
| }
|
| @@ -6419,8 +6819,10 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| DartEntry _recordIncrementalAnalysisTaskResults(IncrementalAnalysisTask task) {
|
| CompilationUnit unit = task.compilationUnit;
|
| if (unit != null) {
|
| - ChangeNoticeImpl notice = _getNotice(task.source);
|
| - notice.compilationUnit = unit;
|
| + if (_generateSdkErrors || !task.source.isInSystemLibrary) {
|
| + ChangeNoticeImpl notice = _getNotice(task.source);
|
| + notice.compilationUnit = unit;
|
| + }
|
| _incrementalAnalysisCache = IncrementalAnalysisCache.cacheResult(task.cache, unit);
|
| }
|
| return null;
|
| @@ -6486,8 +6888,10 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| dartCopy.setValue(DartEntry.IMPORTED_LIBRARIES, task.importedSources);
|
| dartCopy.setValue(DartEntry.INCLUDED_PARTS, newParts);
|
| _cache.storedAst(source);
|
| - ChangeNoticeImpl notice = _getNotice(source);
|
| - notice.setErrors(dartCopy.allErrors, dartCopy.getValue(SourceEntry.LINE_INFO));
|
| + if (_generateSdkErrors || !source.isInSystemLibrary) {
|
| + ChangeNoticeImpl notice = _getNotice(source);
|
| + notice.setErrors(dartCopy.allErrors, task.lineInfo);
|
| + }
|
| // 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);
|
| @@ -6572,8 +6976,10 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| htmlCopy.setValue(HtmlEntry.PARSE_ERRORS, task.errors);
|
| htmlCopy.setValue(HtmlEntry.REFERENCED_LIBRARIES, task.referencedLibraries);
|
| _cache.storedAst(source);
|
| - ChangeNoticeImpl notice = _getNotice(source);
|
| - notice.setErrors(htmlCopy.allErrors, lineInfo);
|
| + if (_generateSdkErrors || !source.isInSystemLibrary) {
|
| + ChangeNoticeImpl notice = _getNotice(source);
|
| + notice.setErrors(htmlCopy.allErrors, lineInfo);
|
| + }
|
| } else {
|
| htmlCopy.recordParseError();
|
| _cache.removedAst(source);
|
| @@ -6657,9 +7063,11 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| 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));
|
| + if (_generateSdkErrors || !source.isInSystemLibrary) {
|
| + ChangeNoticeImpl notice = _getNotice(source);
|
| + notice.htmlUnit = task.resolvedUnit;
|
| + notice.setErrors(htmlCopy.allErrors, htmlCopy.getValue(SourceEntry.LINE_INFO));
|
| + }
|
| } else {
|
| htmlCopy.recordResolutionError();
|
| }
|
| @@ -6739,9 +7147,11 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| 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));
|
| + if (_generateSdkErrors || !source.isInSystemLibrary) {
|
| + ChangeNoticeImpl notice = _getNotice(source);
|
| + notice.htmlUnit = task.resolvedUnit;
|
| + notice.setErrors(htmlCopy.allErrors, htmlCopy.getValue(SourceEntry.LINE_INFO));
|
| + }
|
| } else {
|
| htmlCopy.recordResolutionError();
|
| }
|
| @@ -6902,9 +7312,11 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| htmlCopy.setValue(HtmlEntry.ELEMENT, task.element);
|
| htmlCopy.setValue(HtmlEntry.RESOLUTION_ERRORS, task.resolutionErrors);
|
| _cache.storedAst(source);
|
| - ChangeNoticeImpl notice = _getNotice(source);
|
| - notice.htmlUnit = task.resolvedUnit;
|
| - notice.setErrors(htmlCopy.allErrors, htmlCopy.getValue(SourceEntry.LINE_INFO));
|
| + if (_generateSdkErrors || !source.isInSystemLibrary) {
|
| + ChangeNoticeImpl notice = _getNotice(source);
|
| + notice.htmlUnit = task.resolvedUnit;
|
| + notice.setErrors(htmlCopy.allErrors, htmlCopy.getValue(SourceEntry.LINE_INFO));
|
| + }
|
| } else {
|
| htmlCopy.recordResolutionError();
|
| _cache.removedAst(source);
|
| @@ -6987,8 +7399,10 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| 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);
|
| + if (_generateSdkErrors || !source.isInSystemLibrary) {
|
| + ChangeNoticeImpl notice = _getNotice(source);
|
| + notice.setErrors(dartEntry.allErrors, lineInfo);
|
| + }
|
| } else {
|
| _removeFromParts(source, dartEntry);
|
| dartCopy.recordScanError();
|
| @@ -7086,14 +7500,12 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| SourceEntry sourceEntry = _cache.get(source);
|
| if (sourceEntry == null) {
|
| sourceEntry = _createSourceEntry(source);
|
| - _logInformation("Added new source: ${_debuggingString(source)}");
|
| } else {
|
| SourceEntryImpl sourceCopy = sourceEntry.writableCopy;
|
| - int oldTime = sourceCopy.modificationTime;
|
| + // long oldTime = sourceCopy.getModificationTime();
|
| 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})");
|
| }
|
| if (sourceEntry is HtmlEntry) {
|
| _workManager.add(source, SourcePriority.HTML);
|
| @@ -7113,23 +7525,22 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| 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) {
|
| - _logInformation("Modified source, but there is no entry: ${_debuggingString(source)}");
|
| - } else {
|
| - _logInformation("Modified source, but modification time matches: ${_debuggingString(source)}");
|
| - }
|
| + // if (sourceEntry == null) {
|
| + // logInformation("Modified source, but there is no entry: " + debuggingString(source));
|
| + // } else {
|
| + // logInformation("Modified source, but modification time matches: " + debuggingString(source));
|
| + // }
|
| return;
|
| }
|
| if (sourceEntry is HtmlEntry) {
|
| HtmlEntryImpl htmlCopy = sourceEntry.writableCopy;
|
| - int oldTime = htmlCopy.modificationTime;
|
| + // long oldTime = htmlCopy.getModificationTime();
|
| htmlCopy.modificationTime = getModificationStamp(source);
|
| _invalidateAngularResolution(htmlCopy);
|
| htmlCopy.invalidateAllInformation();
|
| _cache.put(source, htmlCopy);
|
| _cache.removedAst(source);
|
| _workManager.add(source, SourcePriority.HTML);
|
| - _logInformation("Modified HTML source: ${_debuggingString(source)} (previously modified at ${oldTime})");
|
| } else if (sourceEntry is DartEntry) {
|
| List<Source> containingLibraries = getLibrariesContaining(source);
|
| Set<Source> librariesToInvalidate = new Set<Source>();
|
| @@ -7140,8 +7551,6 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
| }
|
| PrintStringWriter writer = new PrintStringWriter();
|
| - int oldTime = sourceEntry.modificationTime;
|
| - writer.println("Modified Dart source: ${_debuggingString(source)} (previously modified at ${oldTime})");
|
| for (Source library in librariesToInvalidate) {
|
| // for (Source library : containingLibraries) {
|
| _invalidateLibraryResolution(library, writer);
|
| @@ -7153,7 +7562,6 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| _cache.put(source, dartCopy);
|
| _cache.removedAst(source);
|
| _workManager.add(source, SourcePriority.UNKNOWN);
|
| - _logInformation(writer.toString());
|
| }
|
| }
|
|
|
| @@ -7164,7 +7572,6 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| */
|
| void _sourceRemoved(Source source) {
|
| PrintStringWriter writer = new PrintStringWriter();
|
| - writer.println("Removed source: ${_debuggingString(source)}");
|
| SourceEntry sourceEntry = _cache.get(source);
|
| if (sourceEntry is HtmlEntry) {
|
| HtmlEntryImpl htmlCopy = sourceEntry.writableCopy;
|
| @@ -7184,7 +7591,6 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| _cache.remove(source);
|
| _workManager.remove(source);
|
| _removeFromPriorityOrder(source);
|
| - _logInformation(writer.toString());
|
| }
|
|
|
| /**
|
| @@ -7215,21 +7621,23 @@ class AnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
| }
|
| int consistencyCheckEnd = JavaSystem.nanoTime();
|
| - PrintStringWriter writer = new PrintStringWriter();
|
| - writer.print("Consistency check took ");
|
| - writer.print((consistencyCheckEnd - consistencyCheckStart) / 1000000.0);
|
| - writer.println(" ms and found");
|
| - writer.print(" ");
|
| - writer.print(inconsistentCount);
|
| - writer.println(" inconsistent entries");
|
| - writer.print(" ");
|
| - writer.print(missingSources.length);
|
| - writer.println(" missing sources");
|
| - for (Source source in missingSources) {
|
| - writer.print(" ");
|
| - writer.println(source.fullName);
|
| - }
|
| - _logInformation(writer.toString());
|
| + if (inconsistentCount > 0 || missingSources.length > 0) {
|
| + PrintStringWriter writer = new PrintStringWriter();
|
| + writer.print("Consistency check took ");
|
| + writer.print((consistencyCheckEnd - consistencyCheckStart) / 1000000.0);
|
| + writer.println(" ms and found");
|
| + writer.print(" ");
|
| + writer.print(inconsistentCount);
|
| + writer.println(" inconsistent entries");
|
| + writer.print(" ");
|
| + writer.print(missingSources.length);
|
| + writer.println(" missing sources");
|
| + for (Source source in missingSources) {
|
| + writer.print(" ");
|
| + writer.println(source.fullName);
|
| + }
|
| + _logInformation(writer.toString());
|
| + }
|
| return inconsistentCount > 0;
|
| }
|
| }
|
| @@ -7268,6 +7676,9 @@ class AnalysisContextImpl_AnalysisTaskResultRecorder implements AnalysisTaskVisi
|
| HtmlEntry visitResolveAngularEntryHtmlTask(ResolveAngularEntryHtmlTask task) => AnalysisContextImpl_this._recordResolveAngularEntryHtmlTaskResults(task);
|
|
|
| @override
|
| + DartEntry visitResolveDartLibraryCycleTask(ResolveDartLibraryCycleTask task) => AnalysisContextImpl_this.recordResolveDartLibraryCycleTaskResults(task);
|
| +
|
| + @override
|
| DartEntry visitResolveDartLibraryTask(ResolveDartLibraryTask task) => AnalysisContextImpl_this.recordResolveDartLibraryTaskResults(task);
|
|
|
| @override
|
| @@ -7287,11 +7698,15 @@ class AnalysisContextImpl_ContextRetentionPolicy implements CacheRetentionPolicy
|
|
|
| @override
|
| RetentionPriority getAstPriority(Source source, SourceEntry sourceEntry) {
|
| - for (Source prioritySource in AnalysisContextImpl_this._priorityOrder) {
|
| - if (source == prioritySource) {
|
| + int priorityCount = AnalysisContextImpl_this._priorityOrder.length;
|
| + for (int i = 0; i < priorityCount; i++) {
|
| + if (source == AnalysisContextImpl_this._priorityOrder[i]) {
|
| return RetentionPriority.HIGH;
|
| }
|
| }
|
| + if (AnalysisContextImpl_this._neededForResolution != null && AnalysisContextImpl_this._neededForResolution.contains(source)) {
|
| + return RetentionPriority.HIGH;
|
| + }
|
| if (sourceEntry is DartEntry) {
|
| DartEntry dartEntry = sourceEntry;
|
| if (_astIsNeeded(dartEntry)) {
|
| @@ -7305,6 +7720,515 @@ class AnalysisContextImpl_ContextRetentionPolicy implements CacheRetentionPolicy
|
| }
|
|
|
| /**
|
| + * Instances of the class `LibraryPair` hold a library and a list of the (source, entry)
|
| + * pairs for compilation units in the library.
|
| + */
|
| +class CycleBuilder_LibraryPair {
|
| + /**
|
| + * The library containing the compilation units.
|
| + */
|
| + ResolvableLibrary library;
|
| +
|
| + /**
|
| + * The (source, entry) pairs representing the compilation units in the library.
|
| + */
|
| + List<CycleBuilder_SourceEntryPair> entryPairs;
|
| +
|
| + /**
|
| + * Initialize a newly created pair.
|
| + *
|
| + * @param library the library containing the compilation units
|
| + * @param entryPairs the (source, entry) pairs representing the compilation units in the
|
| + * library
|
| + */
|
| + CycleBuilder_LibraryPair(ResolvableLibrary library, List<CycleBuilder_SourceEntryPair> entryPairs) {
|
| + this.library = library;
|
| + this.entryPairs = entryPairs;
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Instances of the class `SourceEntryPair` hold a source and the cache entry associated
|
| + * with that source. They are used to reduce the number of times an entry must be looked up in
|
| + * the [cache].
|
| + */
|
| +class CycleBuilder_SourceEntryPair {
|
| + /**
|
| + * The source associated with the entry.
|
| + */
|
| + Source source;
|
| +
|
| + /**
|
| + * The entry associated with the source.
|
| + */
|
| + DartEntry entry;
|
| +
|
| + /**
|
| + * Initialize a newly created pair.
|
| + *
|
| + * @param source the source associated with the entry
|
| + * @param entry the entry associated with the source
|
| + */
|
| + CycleBuilder_SourceEntryPair(Source source, DartEntry entry) {
|
| + this.source = source;
|
| + this.entry = entry;
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Instances of the class `CycleBuilder` are used to construct a list of the libraries that
|
| + * must be resolved together in order to resolve any one of the libraries.
|
| + */
|
| +class AnalysisContextImpl_CycleBuilder {
|
| + final AnalysisContextImpl AnalysisContextImpl_this;
|
| +
|
| + /**
|
| + * A table mapping the sources of the defining compilation units of libraries to the
|
| + * representation of the library that has the information needed to resolve the library.
|
| + */
|
| + Map<Source, ResolvableLibrary> _libraryMap = new Map<Source, ResolvableLibrary>();
|
| +
|
| + /**
|
| + * The dependency graph used to compute the libraries in the cycle.
|
| + */
|
| + DirectedGraph<ResolvableLibrary> _dependencyGraph;
|
| +
|
| + /**
|
| + * A list containing the libraries that are ready to be resolved.
|
| + */
|
| + List<ResolvableLibrary> _librariesInCycle;
|
| +
|
| + /**
|
| + * The analysis task that needs to be performed before the cycle of libraries can be resolved,
|
| + * or `null` if the libraries are ready to be resolved.
|
| + */
|
| + AnalysisContextImpl_TaskData _taskData;
|
| +
|
| + /**
|
| + * Initialize a newly created cycle builder.
|
| + */
|
| + AnalysisContextImpl_CycleBuilder(this.AnalysisContextImpl_this) : super();
|
| +
|
| + /**
|
| + * Compute a list of the libraries that need to be resolved together in order to resolve the
|
| + * given library.
|
| + *
|
| + * @param librarySource the source of the library to be resolved
|
| + * @throws AnalysisException if the core library cannot be found
|
| + */
|
| + void computeCycleContaining(Source librarySource) {
|
| + //
|
| + // Create the object representing the library being resolved.
|
| + //
|
| + ResolvableLibrary targetLibrary = _createLibrary(librarySource);
|
| + //
|
| + // Compute the set of libraries that need to be resolved together.
|
| + //
|
| + _dependencyGraph = new DirectedGraph<ResolvableLibrary>();
|
| + _computeLibraryDependencies(targetLibrary);
|
| + if (_taskData != null) {
|
| + return;
|
| + }
|
| + _librariesInCycle = _dependencyGraph.findCycleContaining(targetLibrary);
|
| + //
|
| + // Ensure that all of the data needed to resolve them has been computed.
|
| + //
|
| + _ensureImportsAndExports();
|
| + if (_taskData != null) {
|
| + // At least one imported library needs to be resolved before the target library.
|
| + AnalysisTask task = _taskData.task;
|
| + if (task is ResolveDartLibraryTask) {
|
| + AnalysisContextImpl_this._workManager.addFirst(task.librarySource, SourcePriority.LIBRARY);
|
| + }
|
| + return;
|
| + }
|
| + _computePartsInCycle(librarySource);
|
| + if (_taskData != null) {
|
| + // At least one part needs to be parsed.
|
| + return;
|
| + }
|
| + // All of the AST's necessary to perform a resolution of the library cycle have been
|
| + // gathered, so it is no longer necessary to retain them in the cache.
|
| + AnalysisContextImpl_this._neededForResolution = null;
|
| + }
|
| +
|
| + /**
|
| + * Return a list containing the libraries that are ready to be resolved (assuming that
|
| + * [getTaskData] returns `null`).
|
| + *
|
| + * @return the libraries that are ready to be resolved
|
| + */
|
| + List<ResolvableLibrary> get librariesInCycle => _librariesInCycle;
|
| +
|
| + /**
|
| + * Return a representation of an analysis task that needs to be performed before the cycle of
|
| + * libraries can be resolved, or `null` if the libraries are ready to be resolved.
|
| + *
|
| + * @return the analysis task that needs to be performed before the cycle of libraries can be
|
| + * resolved
|
| + */
|
| + AnalysisContextImpl_TaskData get taskData => _taskData;
|
| +
|
| + /**
|
| + * Recursively traverse the libraries reachable from the given library, creating instances of
|
| + * the class [Library] to represent them, and record the references in the library
|
| + * objects.
|
| + *
|
| + * @param library the library to be processed to find libraries that have not yet been traversed
|
| + * @throws AnalysisException if some portion of the library graph could not be traversed
|
| + */
|
| + void _computeLibraryDependencies(ResolvableLibrary library) {
|
| + Source librarySource = library.librarySource;
|
| + DartEntry dartEntry = AnalysisContextImpl_this._getReadableDartEntry(librarySource);
|
| + List<Source> importedSources = _getSources(librarySource, dartEntry, DartEntry.IMPORTED_LIBRARIES);
|
| + if (_taskData != null) {
|
| + return;
|
| + }
|
| + List<Source> exportedSources = _getSources(librarySource, dartEntry, DartEntry.EXPORTED_LIBRARIES);
|
| + if (_taskData != null) {
|
| + return;
|
| + }
|
| + _computeLibraryDependenciesFromDirectives(library, importedSources, exportedSources);
|
| + }
|
| +
|
| + /**
|
| + * Recursively traverse the libraries reachable from the given library, creating instances of
|
| + * the class [Library] to represent them, and record the references in the library
|
| + * objects.
|
| + *
|
| + * @param library the library to be processed to find libraries that have not yet been traversed
|
| + * @param importedSources an array containing the sources that are imported into the given
|
| + * library
|
| + * @param exportedSources an array containing the sources that are exported from the given
|
| + * library
|
| + */
|
| + void _computeLibraryDependenciesFromDirectives(ResolvableLibrary library, List<Source> importedSources, List<Source> exportedSources) {
|
| + int importCount = importedSources.length;
|
| + if (importCount > 0) {
|
| + List<ResolvableLibrary> importedLibraries = new List<ResolvableLibrary>();
|
| + bool explicitlyImportsCore = false;
|
| + for (int i = 0; i < importCount; i++) {
|
| + Source importedSource = importedSources[i];
|
| + if (importedSource == AnalysisContextImpl_this._coreLibrarySource) {
|
| + explicitlyImportsCore = true;
|
| + }
|
| + ResolvableLibrary importedLibrary = _libraryMap[importedSource];
|
| + if (importedLibrary == null) {
|
| + importedLibrary = _createLibraryOrNull(importedSource);
|
| + if (importedLibrary != null) {
|
| + _computeLibraryDependencies(importedLibrary);
|
| + if (_taskData != null) {
|
| + return;
|
| + }
|
| + }
|
| + }
|
| + if (importedLibrary != null) {
|
| + importedLibraries.add(importedLibrary);
|
| + _dependencyGraph.addEdge(library, importedLibrary);
|
| + }
|
| + }
|
| + library.explicitlyImportsCore = explicitlyImportsCore;
|
| + if (!explicitlyImportsCore && AnalysisContextImpl_this._coreLibrarySource != library.librarySource) {
|
| + ResolvableLibrary importedLibrary = _libraryMap[AnalysisContextImpl_this._coreLibrarySource];
|
| + if (importedLibrary == null) {
|
| + importedLibrary = _createLibraryOrNull(AnalysisContextImpl_this._coreLibrarySource);
|
| + if (importedLibrary != null) {
|
| + _computeLibraryDependencies(importedLibrary);
|
| + if (_taskData != null) {
|
| + return;
|
| + }
|
| + }
|
| + }
|
| + if (importedLibrary != null) {
|
| + importedLibraries.add(importedLibrary);
|
| + _dependencyGraph.addEdge(library, importedLibrary);
|
| + }
|
| + }
|
| + library.importedLibraries = new List.from(importedLibraries);
|
| + } else {
|
| + library.explicitlyImportsCore = false;
|
| + ResolvableLibrary importedLibrary = _libraryMap[AnalysisContextImpl_this._coreLibrarySource];
|
| + if (importedLibrary == null) {
|
| + importedLibrary = _createLibraryOrNull(AnalysisContextImpl_this._coreLibrarySource);
|
| + if (importedLibrary != null) {
|
| + _computeLibraryDependencies(importedLibrary);
|
| + if (_taskData != null) {
|
| + return;
|
| + }
|
| + }
|
| + }
|
| + if (importedLibrary != null) {
|
| + _dependencyGraph.addEdge(library, importedLibrary);
|
| + library.importedLibraries = <ResolvableLibrary> [importedLibrary];
|
| + }
|
| + }
|
| + int exportCount = exportedSources.length;
|
| + if (exportCount > 0) {
|
| + List<ResolvableLibrary> exportedLibraries = new List<ResolvableLibrary>();
|
| + for (int i = 0; i < exportCount; i++) {
|
| + Source exportedSource = exportedSources[i];
|
| + ResolvableLibrary exportedLibrary = _libraryMap[exportedSource];
|
| + if (exportedLibrary == null) {
|
| + exportedLibrary = _createLibraryOrNull(exportedSource);
|
| + if (exportedLibrary != null) {
|
| + _computeLibraryDependencies(exportedLibrary);
|
| + if (_taskData != null) {
|
| + return;
|
| + }
|
| + }
|
| + }
|
| + if (exportedLibrary != null) {
|
| + exportedLibraries.add(exportedLibrary);
|
| + _dependencyGraph.addEdge(library, exportedLibrary);
|
| + }
|
| + }
|
| + library.exportedLibraries = new List.from(exportedLibraries);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Gather the resolvable AST structures for each of the compilation units in each of the
|
| + * libraries in the cycle. This is done in two phases: first we ensure that we have cached an
|
| + * AST structure for each compilation unit, then we gather them. We split the work this way
|
| + * because getting the AST structures can change the state of the cache in such a way that we
|
| + * would have more work to do if any compilation unit didn't have a resolvable AST structure.
|
| + */
|
| + void _computePartsInCycle(Source librarySource) {
|
| + int count = _librariesInCycle.length;
|
| + List<CycleBuilder_LibraryPair> libraryData = new List<CycleBuilder_LibraryPair>();
|
| + for (int i = 0; i < count; i++) {
|
| + ResolvableLibrary library = _librariesInCycle[i];
|
| + libraryData.add(new CycleBuilder_LibraryPair(library, _ensurePartsInLibrary(library)));
|
| + }
|
| + AnalysisContextImpl_this._neededForResolution = _gatherSources(libraryData);
|
| + if (AnalysisContextImpl._TRACE_PERFORM_TASK) {
|
| + print(" preserve resolution data for ${AnalysisContextImpl_this._neededForResolution.length} sources while resolving ${librarySource.fullName}");
|
| + }
|
| + if (_taskData != null) {
|
| + return;
|
| + }
|
| + for (int i = 0; i < count; i++) {
|
| + _computePartsInLibrary(libraryData[i]);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Gather the resolvable compilation units for each of the compilation units in the specified
|
| + * library.
|
| + *
|
| + * @param libraryPair a holder containing both the library and a list of (source, entry) pairs
|
| + * for all of the compilation units in the library
|
| + */
|
| + void _computePartsInLibrary(CycleBuilder_LibraryPair libraryPair) {
|
| + ResolvableLibrary library = libraryPair.library;
|
| + List<CycleBuilder_SourceEntryPair> entryPairs = libraryPair.entryPairs;
|
| + int count = entryPairs.length;
|
| + List<ResolvableCompilationUnit> units = new List<ResolvableCompilationUnit>(count);
|
| + for (int i = 0; i < count; i++) {
|
| + CycleBuilder_SourceEntryPair entryPair = entryPairs[i];
|
| + Source source = entryPair.source;
|
| + DartEntryImpl dartCopy = entryPair.entry.writableCopy;
|
| + units[i] = new ResolvableCompilationUnit.con2(dartCopy.modificationTime, dartCopy.resolvableCompilationUnit, source);
|
| + AnalysisContextImpl_this._cache.put(source, dartCopy);
|
| + }
|
| + library.resolvableCompilationUnits = units;
|
| + }
|
| +
|
| + /**
|
| + * Create an object to represent the information about the library defined by the compilation
|
| + * unit with the given source.
|
| + *
|
| + * @param librarySource the source of the library's defining compilation unit
|
| + * @return the library object that was created
|
| + */
|
| + ResolvableLibrary _createLibrary(Source librarySource) {
|
| + ResolvableLibrary library = new ResolvableLibrary(librarySource);
|
| + SourceEntry sourceEntry = AnalysisContextImpl_this._cache.get(librarySource);
|
| + if (sourceEntry is DartEntry) {
|
| + LibraryElementImpl libraryElement = sourceEntry.getValue(DartEntry.ELEMENT) as LibraryElementImpl;
|
| + if (libraryElement != null) {
|
| + library.libraryElement = libraryElement;
|
| + }
|
| + }
|
| + _libraryMap[librarySource] = library;
|
| + return library;
|
| + }
|
| +
|
| + /**
|
| + * Create an object to represent the information about the library defined by the compilation
|
| + * unit with the given source.
|
| + *
|
| + * @param librarySource the source of the library's defining compilation unit
|
| + * @return the library object that was created
|
| + */
|
| + ResolvableLibrary _createLibraryOrNull(Source librarySource) {
|
| + if (!AnalysisContextImpl_this.exists(librarySource)) {
|
| + return null;
|
| + }
|
| + ResolvableLibrary library = new ResolvableLibrary(librarySource);
|
| + SourceEntry sourceEntry = AnalysisContextImpl_this._cache.get(librarySource);
|
| + if (sourceEntry is DartEntry) {
|
| + LibraryElementImpl libraryElement = sourceEntry.getValue(DartEntry.ELEMENT) as LibraryElementImpl;
|
| + if (libraryElement != null) {
|
| + library.libraryElement = libraryElement;
|
| + }
|
| + }
|
| + _libraryMap[librarySource] = library;
|
| + return library;
|
| + }
|
| +
|
| + /**
|
| + * Ensure that all of the libraries that are exported by the given library (but are not
|
| + * themselves in the cycle) have element models built for them.
|
| + *
|
| + * @param library the library being tested
|
| + */
|
| + void _ensureExports(ResolvableLibrary library, Set<Source> visitedLibraries) {
|
| + List<ResolvableLibrary> dependencies = library.exports;
|
| + int dependencyCount = dependencies.length;
|
| + for (int i = 0; i < dependencyCount; i++) {
|
| + ResolvableLibrary dependency = dependencies[i];
|
| + if (!_librariesInCycle.contains(dependency) && visitedLibraries.add(dependency.librarySource)) {
|
| + if (dependency.libraryElement == null) {
|
| + Source dependencySource = dependency.librarySource;
|
| + AnalysisContextImpl_this._workManager.addFirst(dependencySource, SourcePriority.LIBRARY);
|
| + if (_taskData == null) {
|
| + _taskData = AnalysisContextImpl_this._createResolveDartLibraryTask(dependencySource, AnalysisContextImpl_this._getReadableDartEntry(dependencySource));
|
| + return;
|
| + }
|
| + } else {
|
| + _ensureExports(dependency, visitedLibraries);
|
| + if (_taskData != null) {
|
| + return;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Ensure that all of the libraries that are exported by the given library (but are not
|
| + * themselves in the cycle) have element models built for them.
|
| + *
|
| + * @param library the library being tested
|
| + * @throws MissingDataException if there is at least one library being depended on that does not
|
| + * have an element model built for it
|
| + */
|
| + void _ensureImports(ResolvableLibrary library) {
|
| + List<ResolvableLibrary> dependencies = library.imports;
|
| + int dependencyCount = dependencies.length;
|
| + for (int i = 0; i < dependencyCount; i++) {
|
| + ResolvableLibrary dependency = dependencies[i];
|
| + if (!_librariesInCycle.contains(dependency) && dependency.libraryElement == null) {
|
| + Source dependencySource = dependency.librarySource;
|
| + AnalysisContextImpl_this._workManager.addFirst(dependencySource, SourcePriority.LIBRARY);
|
| + if (_taskData == null) {
|
| + _taskData = AnalysisContextImpl_this._createResolveDartLibraryTask(dependencySource, AnalysisContextImpl_this._getReadableDartEntry(dependencySource));
|
| + return;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Ensure that all of the libraries that are either imported or exported by libraries in the
|
| + * cycle (but are not themselves in the cycle) have element models built for them.
|
| + */
|
| + void _ensureImportsAndExports() {
|
| + Set<Source> visitedLibraries = new Set<Source>();
|
| + int libraryCount = _librariesInCycle.length;
|
| + for (int i = 0; i < libraryCount; i++) {
|
| + ResolvableLibrary library = _librariesInCycle[i];
|
| + _ensureImports(library);
|
| + if (_taskData != null) {
|
| + return;
|
| + }
|
| + _ensureExports(library, visitedLibraries);
|
| + if (_taskData != null) {
|
| + return;
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Ensure that there is a resolvable compilation unit available for all of the compilation units
|
| + * in the given library.
|
| + *
|
| + * @param library the library for which resolvable compilation units must be available
|
| + * @return a list of (source, entry) pairs for all of the compilation units in the library
|
| + */
|
| + List<CycleBuilder_SourceEntryPair> _ensurePartsInLibrary(ResolvableLibrary library) {
|
| + List<CycleBuilder_SourceEntryPair> pairs = new List<CycleBuilder_SourceEntryPair>();
|
| + Source librarySource = library.librarySource;
|
| + DartEntry libraryEntry = AnalysisContextImpl_this._getReadableDartEntry(librarySource);
|
| + _ensureResolvableCompilationUnit(librarySource, libraryEntry);
|
| + pairs.add(new CycleBuilder_SourceEntryPair(librarySource, libraryEntry));
|
| + List<Source> partSources = _getSources(librarySource, libraryEntry, DartEntry.INCLUDED_PARTS);
|
| + int count = partSources.length;
|
| + for (int i = 0; i < count; i++) {
|
| + Source partSource = partSources[i];
|
| + DartEntry partEntry = AnalysisContextImpl_this._getReadableDartEntry(partSource);
|
| + if (partEntry != null && partEntry.getState(DartEntry.PARSED_UNIT) != CacheState.ERROR) {
|
| + _ensureResolvableCompilationUnit(partSource, partEntry);
|
| + pairs.add(new CycleBuilder_SourceEntryPair(partSource, partEntry));
|
| + }
|
| + }
|
| + return pairs;
|
| + }
|
| +
|
| + /**
|
| + * Ensure that there is a resolvable compilation unit available for the given source.
|
| + *
|
| + * @param source the source for which a resolvable compilation unit must be available
|
| + * @param dartEntry the entry associated with the source
|
| + */
|
| + void _ensureResolvableCompilationUnit(Source source, DartEntry dartEntry) {
|
| + if (!dartEntry.hasResolvableCompilationUnit) {
|
| + if (_taskData == null) {
|
| + _taskData = AnalysisContextImpl_this._createParseDartTask(source, dartEntry);
|
| + }
|
| + }
|
| + }
|
| +
|
| + Set<Source> _gatherSources(List<CycleBuilder_LibraryPair> libraryData) {
|
| + int libraryCount = libraryData.length;
|
| + Set<Source> sources = new Set<Source>();
|
| + for (int i = 0; i < libraryCount; i++) {
|
| + List<CycleBuilder_SourceEntryPair> entryPairs = libraryData[i].entryPairs;
|
| + int entryCount = entryPairs.length;
|
| + for (int j = 0; j < entryCount; j++) {
|
| + sources.add(entryPairs[j].source);
|
| + }
|
| + }
|
| + return sources;
|
| + }
|
| +
|
| + /**
|
| + * Return the sources described by the given descriptor.
|
| + *
|
| + * @param source the source with which the sources are associated
|
| + * @param dartEntry the entry corresponding to the source
|
| + * @param descriptor the descriptor indicating which sources are to be returned
|
| + * @return the sources described by the given descriptor
|
| + */
|
| + List<Source> _getSources(Source source, DartEntry dartEntry, DataDescriptor<List<Source>> descriptor) {
|
| + if (dartEntry == null) {
|
| + return Source.EMPTY_ARRAY;
|
| + }
|
| + CacheState exportState = dartEntry.getState(descriptor);
|
| + if (identical(exportState, CacheState.ERROR)) {
|
| + return Source.EMPTY_ARRAY;
|
| + } else if (exportState != CacheState.VALID) {
|
| + if (_taskData == null) {
|
| + _taskData = AnalysisContextImpl_this._createParseDartTask(source, dartEntry);
|
| + }
|
| + return Source.EMPTY_ARRAY;
|
| + }
|
| + return dartEntry.getValue(descriptor);
|
| + }
|
| +}
|
| +
|
| +/**
|
| * Instances of the class `TaskData` represent information about the next task to be
|
| * performed. Each data has an implicit associated source: the source that might need to be
|
| * analyzed. There are essentially three states that can be represented:
|
| @@ -7347,6 +8271,14 @@ class AnalysisContextImpl_TaskData {
|
| * loaded
|
| */
|
| bool get isBlocked => _blocked;
|
| +
|
| + @override
|
| + String toString() {
|
| + if (task == null) {
|
| + return "blocked: ${_blocked}";
|
| + }
|
| + return task.toString();
|
| + }
|
| }
|
|
|
| /**
|
| @@ -8235,6 +9167,18 @@ class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
| }
|
|
|
| + @override
|
| + AngularApplication getAngularApplicationWithHtml(Source htmlSource) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getAngularApplication");
|
| + _checkThread(instrumentation);
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.getAngularApplicationWithHtml(htmlSource);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| +
|
| /**
|
| * @return the underlying [AnalysisContext].
|
| */
|
| @@ -8404,6 +9348,18 @@ class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
|
| }
|
|
|
| @override
|
| + List<Source> getLibrariesReferencedFromHtml(Source htmlSource) {
|
| + InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLibrariesReferencedFromHtml");
|
| + _checkThread(instrumentation);
|
| + try {
|
| + instrumentation.metric3("contextId", _contextId);
|
| + return _basis.getLibrariesReferencedFromHtml(htmlSource);
|
| + } finally {
|
| + instrumentation.log();
|
| + }
|
| + }
|
| +
|
| + @override
|
| LibraryElement getLibraryElement(Source source) {
|
| InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getLibraryElement");
|
| _checkThread(instrumentation);
|
| @@ -8509,7 +9465,6 @@ class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
|
| @override
|
| SourceFactory get sourceFactory {
|
| InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getSourceFactory");
|
| - _checkThread(instrumentation);
|
| try {
|
| instrumentation.metric3("contextId", _contextId);
|
| return _basis.sourceFactory;
|
| @@ -8525,9 +9480,6 @@ class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
|
| TypeProvider get typeProvider => _basis.typeProvider;
|
|
|
| @override
|
| - TimestampedData<CompilationUnit> internalResolveCompilationUnit(Source unitSource, LibraryElement libraryElement) => _basis.internalResolveCompilationUnit(unitSource, libraryElement);
|
| -
|
| - @override
|
| bool isClientLibrary(Source librarySource) {
|
| InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-isClientLibrary");
|
| _checkThread(instrumentation);
|
| @@ -8818,19 +9770,6 @@ abstract class InternalAnalysisContext implements AnalysisContext {
|
| TypeProvider get typeProvider;
|
|
|
| /**
|
| - * Return a time-stamped fully-resolved compilation unit for the given source in the given
|
| - * library.
|
| - *
|
| - * @param unitSource the source of the compilation unit for which a resolved AST structure is to
|
| - * be returned
|
| - * @param libraryElement the element representing the library in which the compilation unit is to
|
| - * be resolved
|
| - * @return a time-stamped fully-resolved compilation unit for the source
|
| - * @throws AnalysisException if the resolved compilation unit could not be computed
|
| - */
|
| - TimestampedData<CompilationUnit> internalResolveCompilationUnit(Source unitSource, LibraryElement libraryElement);
|
| -
|
| - /**
|
| * Given a table mapping the source for the libraries represented by the corresponding elements to
|
| * the elements representing the libraries, record those mappings.
|
| *
|
| @@ -9281,6 +10220,33 @@ class WorkManager {
|
| _workQueues[i].remove(source);
|
| }
|
| }
|
| +
|
| + @override
|
| + String toString() {
|
| + JavaStringBuilder builder = new JavaStringBuilder();
|
| + List<SourcePriority> priorities = SourcePriority.values;
|
| + bool needsSeparator = false;
|
| + int queueCount = _workQueues.length;
|
| + for (int i = 0; i < queueCount; i++) {
|
| + List<Source> queue = _workQueues[i];
|
| + if (!queue.isEmpty) {
|
| + if (needsSeparator) {
|
| + builder.append("; ");
|
| + }
|
| + builder.append(priorities[i]);
|
| + builder.append(": ");
|
| + int queueSize = queue.length;
|
| + for (int j = 0; j < queueSize; j++) {
|
| + if (j > 0) {
|
| + builder.append(", ");
|
| + }
|
| + builder.append(queue[j].fullName);
|
| + }
|
| + needsSeparator = true;
|
| + }
|
| + }
|
| + return builder.toString();
|
| + }
|
| }
|
|
|
| /**
|
| @@ -10439,24 +11405,29 @@ class NgDirectiveElementProcessor extends NgDirectiveProcessor {
|
| if (name == ".") {
|
| name = selectorAttributeName;
|
| }
|
| - // resolve attribute expression
|
| + // prepare attribute
|
| ht.XmlAttributeNode attribute = node.getAttribute(name);
|
| - if (attribute != null) {
|
| - // 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();
|
| - try {
|
| - _onNgEventDirective(resolver);
|
| - AngularExpression expression = parseAngularExpression(resolver, attribute);
|
| - resolver._resolveExpression(expression);
|
| - setAngularExpression(attribute, expression);
|
| - } finally {
|
| - resolver._popNameScope();
|
| - }
|
| + if (attribute == null) {
|
| + continue;
|
| + }
|
| + // if not resolved as the selector, resolve as a property
|
| + if (name != selectorAttributeName) {
|
| + attribute.element = property;
|
| + }
|
| + // skip if attribute has no value
|
| + if (!NgDirectiveProcessor.hasValue(attribute)) {
|
| + continue;
|
| + }
|
| + // resolve if binding
|
| + if (property.propertyKind != AngularPropertyKind.ATTR) {
|
| + resolver._pushNameScope();
|
| + try {
|
| + _onNgEventDirective(resolver);
|
| + AngularExpression expression = parseAngularExpression(resolver, attribute);
|
| + resolver._resolveExpression(expression);
|
| + setAngularExpression(attribute, expression);
|
| + } finally {
|
| + resolver._popNameScope();
|
| }
|
| }
|
| }
|
| @@ -10480,6 +11451,11 @@ class NgDirectiveElementProcessor extends NgDirectiveProcessor {
|
| * [NgDirectiveProcessor] describes any <code>NgDirective</code> annotation instance.
|
| */
|
| abstract class NgDirectiveProcessor extends NgProcessor {
|
| + static bool hasValue(ht.XmlAttributeNode attribute) {
|
| + ht.Token valueToken = attribute.valueToken;
|
| + return valueToken != null && !valueToken.isSynthetic;
|
| + }
|
| +
|
| static AngularRawXmlExpression newAngularRawXmlExpression(AngularExpression e) => new AngularRawXmlExpression(e);
|
|
|
| static ht.RawXmlExpression newRawXmlExpression(Expression e) => new ht.RawXmlExpression(e);
|
| @@ -10764,6 +11740,15 @@ abstract class AnalysisTaskVisitor<E> {
|
| E visitResolveAngularEntryHtmlTask(ResolveAngularEntryHtmlTask task);
|
|
|
| /**
|
| + * Visit a [ResolveDartLibraryCycleTask].
|
| + *
|
| + * @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 visitResolveDartLibraryCycleTask(ResolveDartLibraryCycleTask task);
|
| +
|
| + /**
|
| * Visit a [ResolveDartLibraryTask].
|
| *
|
| * @param task the task to be visited
|
| @@ -10811,14 +11796,19 @@ class GenerateDartErrorsTask extends AnalysisTask {
|
| Source source;
|
|
|
| /**
|
| - * The element model for the library containing the source.
|
| + * The time at which the contents of the source were last modified.
|
| */
|
| - LibraryElement libraryElement;
|
| + int modificationTime = 0;
|
|
|
| /**
|
| - * The time at which the contents of the source were last modified.
|
| + * The compilation unit used to resolve the dependencies.
|
| */
|
| - int _modificationTime = -1;
|
| + CompilationUnit _unit;
|
| +
|
| + /**
|
| + * The element model for the library containing the source.
|
| + */
|
| + LibraryElement libraryElement;
|
|
|
| /**
|
| * The errors that were generated for the source.
|
| @@ -10830,10 +11820,14 @@ class GenerateDartErrorsTask extends AnalysisTask {
|
| *
|
| * @param context the context in which the task is to be performed
|
| * @param source the source for which errors and warnings are to be produced
|
| + * @param modificationTime the time at which the contents of the source were last modified
|
| + * @param unit the compilation unit used to resolve the dependencies
|
| * @param libraryElement the element model for the library containing the source
|
| */
|
| - GenerateDartErrorsTask(InternalAnalysisContext context, Source source, LibraryElement libraryElement) : super(context) {
|
| + GenerateDartErrorsTask(InternalAnalysisContext context, Source source, int modificationTime, CompilationUnit unit, LibraryElement libraryElement) : super(context) {
|
| this.source = source;
|
| + this.modificationTime = modificationTime;
|
| + this._unit = unit;
|
| this.libraryElement = libraryElement;
|
| }
|
|
|
| @@ -10847,25 +11841,13 @@ class GenerateDartErrorsTask extends AnalysisTask {
|
| */
|
| List<AnalysisError> get errors => _errors;
|
|
|
| - /**
|
| - * Return the time at which the contents of the source that was verified 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 verified were last modified
|
| - */
|
| - int get modificationTime => _modificationTime;
|
| -
|
| @override
|
| String get taskDescription => "generate errors and warnings for ${source.fullName}";
|
|
|
| @override
|
| void internalPerform() {
|
| - InternalAnalysisContext context = this.context;
|
| - TimestampedData<CompilationUnit> data = context.internalResolveCompilationUnit(source, libraryElement);
|
| TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.errors.start();
|
| try {
|
| - _modificationTime = data.modificationTime;
|
| - CompilationUnit unit = data.data;
|
| RecordingErrorListener errorListener = new RecordingErrorListener();
|
| ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
|
| TypeProvider typeProvider = context.typeProvider;
|
| @@ -10874,12 +11856,12 @@ class GenerateDartErrorsTask extends AnalysisTask {
|
| // the ErrorVerifier because some error codes need the computed constant values.
|
| //
|
| ConstantVerifier constantVerifier = new ConstantVerifier(errorReporter, typeProvider);
|
| - unit.accept(constantVerifier);
|
| + _unit.accept(constantVerifier);
|
| //
|
| // Use the ErrorVerifier to compute the rest of the errors.
|
| //
|
| ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter, libraryElement, typeProvider, new InheritanceManager(libraryElement));
|
| - unit.accept(errorVerifier);
|
| + _unit.accept(errorVerifier);
|
| _errors = errorListener.getErrorsForSource(source);
|
| } finally {
|
| timeCounter.stop();
|
| @@ -10892,6 +11874,12 @@ class GenerateDartErrorsTask extends AnalysisTask {
|
| */
|
| class GenerateDartHintsTask extends AnalysisTask {
|
| /**
|
| + * The compilation units that comprise the library, with the defining compilation unit appearing
|
| + * first in the array.
|
| + */
|
| + List<TimestampedData<CompilationUnit>> _units;
|
| +
|
| + /**
|
| * The element model for the library being analyzed.
|
| */
|
| LibraryElement libraryElement;
|
| @@ -10906,9 +11894,12 @@ class GenerateDartHintsTask extends AnalysisTask {
|
| * 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 units the compilation units that comprise the library, with the defining compilation
|
| + * unit appearing first in the array
|
| * @param libraryElement the element model for the library being analyzed
|
| */
|
| - GenerateDartHintsTask(InternalAnalysisContext context, LibraryElement libraryElement) : super(context) {
|
| + GenerateDartHintsTask(InternalAnalysisContext context, List<TimestampedData<CompilationUnit>> units, LibraryElement libraryElement) : super(context) {
|
| + this._units = units;
|
| this.libraryElement = libraryElement;
|
| }
|
|
|
| @@ -10936,57 +11927,31 @@ class GenerateDartHintsTask extends AnalysisTask {
|
|
|
| @override
|
| void internalPerform() {
|
| - RecordingErrorListener errorListener = new RecordingErrorListener();
|
| - List<CompilationUnitElement> parts = libraryElement.parts;
|
| - int partCount = parts.length;
|
| - List<CompilationUnit> compilationUnits = new List<CompilationUnit>(partCount + 1);
|
| - Map<Source, TimestampedData<CompilationUnit>> timestampMap = new Map<Source, TimestampedData<CompilationUnit>>();
|
| //
|
| - // Get all of the (fully resolved) compilation units that will be analyzed.
|
| + // Gather the compilation units.
|
| //
|
| - Source unitSource = libraryElement.definingCompilationUnit.source;
|
| - TimestampedData<CompilationUnit> resolvedUnit = _getCompilationUnit(unitSource);
|
| - timestampMap[unitSource] = resolvedUnit;
|
| - CompilationUnit unit = resolvedUnit.data;
|
| - if (unit == null) {
|
| - throw new AnalysisException.con1("Internal error: GenerateDartHintsTask failed to access resolved compilation unit for ${unitSource.fullName}");
|
| - }
|
| - compilationUnits[0] = unit;
|
| - for (int i = 0; i < partCount; i++) {
|
| - unitSource = parts[i].source;
|
| - resolvedUnit = _getCompilationUnit(unitSource);
|
| - timestampMap[unitSource] = resolvedUnit;
|
| - unit = resolvedUnit.data;
|
| - if (unit == null) {
|
| - throw new AnalysisException.con1("Internal error: GenerateDartHintsTask failed to access resolved compilation unit for ${unitSource.fullName}");
|
| - }
|
| - compilationUnits[i + 1] = unit;
|
| + int unitCount = _units.length;
|
| + List<CompilationUnit> compilationUnits = new List<CompilationUnit>(unitCount);
|
| + for (int i = 0; i < unitCount; i++) {
|
| + compilationUnits[i] = _units[i].data;
|
| }
|
| //
|
| // Analyze all of the units.
|
| //
|
| + RecordingErrorListener errorListener = new RecordingErrorListener();
|
| HintGenerator hintGenerator = new HintGenerator(compilationUnits, context, errorListener);
|
| hintGenerator.generateForLibrary();
|
| //
|
| // Store the results.
|
| //
|
| _hintMap = new Map<Source, TimestampedData<List<AnalysisError>>>();
|
| - for (MapEntry<Source, TimestampedData<CompilationUnit>> entry in getMapEntrySet(timestampMap)) {
|
| - Source source = entry.getKey();
|
| - TimestampedData<CompilationUnit> unitData = entry.getValue();
|
| + for (int i = 0; i < unitCount; i++) {
|
| + int modificationTime = _units[i].modificationTime;
|
| + Source source = _units[i].data.element.source;
|
| List<AnalysisError> errors = errorListener.getErrorsForSource(source);
|
| - _hintMap[source] = new TimestampedData<List<AnalysisError>>(unitData.modificationTime, errors);
|
| + _hintMap[source] = new TimestampedData<List<AnalysisError>>(modificationTime, errors);
|
| }
|
| }
|
| -
|
| - /**
|
| - * Return the resolved compilation unit associated with the given source.
|
| - *
|
| - * @param unitSource the source for the compilation unit whose resolved AST is to be returned
|
| - * @return the resolved compilation unit associated with the given source
|
| - * @throws AnalysisException if the resolved compilation unit could not be computed
|
| - */
|
| - TimestampedData<CompilationUnit> _getCompilationUnit(Source unitSource) => context.internalResolveCompilationUnit(unitSource, libraryElement);
|
| }
|
|
|
| /**
|
| @@ -11189,7 +12154,7 @@ class ParseDartTask extends AnalysisTask {
|
| /**
|
| * The line information associated with the source.
|
| */
|
| - LineInfo _lineInfo;
|
| + LineInfo lineInfo;
|
|
|
| /**
|
| * The compilation unit that was produced by parsing the source.
|
| @@ -11244,7 +12209,7 @@ class ParseDartTask extends AnalysisTask {
|
| this.source = source;
|
| this.modificationTime = modificationTime;
|
| this._tokenStream = tokenStream;
|
| - this._lineInfo = lineInfo;
|
| + this.lineInfo = lineInfo;
|
| }
|
|
|
| @override
|
| @@ -11325,7 +12290,7 @@ class ParseDartTask extends AnalysisTask {
|
| Parser parser = new Parser(source, errorListener);
|
| parser.parseFunctionBodies = context.analysisOptions.analyzeFunctionBodies;
|
| _unit = parser.parseCompilationUnit(_tokenStream);
|
| - _unit.lineInfo = _lineInfo;
|
| + _unit.lineInfo = lineInfo;
|
| _errors = errorListener.getErrorsForSource(source);
|
| for (Directive directive in _unit.directives) {
|
| if (directive is ExportDirective) {
|
| @@ -11342,7 +12307,7 @@ class ParseDartTask extends AnalysisTask {
|
| _containsLibraryDirective = true;
|
| } else if (directive is PartDirective) {
|
| Source partSource = _resolveSource(source, directive, errorListener);
|
| - if (partSource != null) {
|
| + if (partSource != null && partSource != source) {
|
| _includedSources.add(partSource);
|
| }
|
| } else if (directive is PartOfDirective) {
|
| @@ -11781,6 +12746,71 @@ class ResolveAngularEntryHtmlTask extends AnalysisTask {
|
| /**
|
| * Instances of the class `ResolveDartLibraryTask` resolve a specific Dart library.
|
| */
|
| +class ResolveDartLibraryCycleTask extends AnalysisTask {
|
| + /**
|
| + * The source representing the file whose compilation unit is to be returned. TODO(brianwilkerson)
|
| + * This should probably be removed, but is being left in for now to ease the transition.
|
| + */
|
| + Source unitSource;
|
| +
|
| + /**
|
| + * The source representing the library to be resolved.
|
| + */
|
| + Source librarySource;
|
| +
|
| + /**
|
| + * The libraries that are part of the cycle containing the library to be resolved.
|
| + */
|
| + List<ResolvableLibrary> _librariesInCycle;
|
| +
|
| + /**
|
| + * The library resolver holding information about the libraries that were resolved.
|
| + */
|
| + LibraryResolver2 _resolver;
|
| +
|
| + /**
|
| + * 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 unitSource the source representing the file whose compilation unit is to be returned
|
| + * @param librarySource the source representing the library to be resolved
|
| + * @param librariesInCycle the libraries that are part of the cycle containing the library to be
|
| + * resolved
|
| + */
|
| + ResolveDartLibraryCycleTask(InternalAnalysisContext context, Source unitSource, Source librarySource, List<ResolvableLibrary> librariesInCycle) : super(context) {
|
| + this.unitSource = unitSource;
|
| + this.librarySource = librarySource;
|
| + this._librariesInCycle = librariesInCycle;
|
| + }
|
| +
|
| + @override
|
| + accept(AnalysisTaskVisitor visitor) => visitor.visitResolveDartLibraryCycleTask(this);
|
| +
|
| + /**
|
| + * Return the library resolver holding information about the libraries that were resolved.
|
| + *
|
| + * @return the library resolver holding information about the libraries that were resolved
|
| + */
|
| + LibraryResolver2 get libraryResolver => _resolver;
|
| +
|
| + @override
|
| + String get taskDescription {
|
| + if (librarySource == null) {
|
| + return "resolve library null source";
|
| + }
|
| + return "resolve library ${librarySource.fullName}";
|
| + }
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + _resolver = new LibraryResolver2(context);
|
| + _resolver.resolveLibrary(librarySource, _librariesInCycle);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Instances of the class `ResolveDartLibraryTask` resolve a specific Dart library.
|
| + */
|
| class ResolveDartLibraryTask extends AnalysisTask {
|
| /**
|
| * The source representing the file whose compilation unit is to be returned.
|
|
|