Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Unified Diff: analyzer/lib/src/context/context.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « analyzer/lib/src/context/cache.dart ('k') | analyzer/lib/src/error.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: analyzer/lib/src/context/context.dart
diff --git a/analyzer/lib/src/context/context.dart b/analyzer/lib/src/context/context.dart
deleted file mode 100644
index 9c0c9808356e71d72075280b178eba1551f8733c..0000000000000000000000000000000000000000
--- a/analyzer/lib/src/context/context.dart
+++ /dev/null
@@ -1,2031 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library analyzer.src.context.context;
-
-import 'dart:async';
-import 'dart:collection';
-
-import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/src/cancelable_future.dart';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/constant.dart';
-import 'package:analyzer/src/generated/element.dart';
-import 'package:analyzer/src/generated/engine.dart'
- hide
- AnalysisCache,
- CachePartition,
- SdkCachePartition,
- UniversalCachePartition,
- WorkManager;
-import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/html.dart' as ht show HtmlUnit;
-import 'package:analyzer/src/generated/incremental_resolver.dart';
-import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
-import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/utilities_collection.dart';
-import 'package:analyzer/src/task/dart.dart';
-import 'package:analyzer/src/task/dart_work_manager.dart';
-import 'package:analyzer/src/task/driver.dart';
-import 'package:analyzer/src/task/html.dart';
-import 'package:analyzer/src/task/html_work_manager.dart';
-import 'package:analyzer/src/task/incremental_element_builder.dart';
-import 'package:analyzer/src/task/manager.dart';
-import 'package:analyzer/task/dart.dart';
-import 'package:analyzer/task/general.dart';
-import 'package:analyzer/task/html.dart';
-import 'package:analyzer/task/model.dart';
-import 'package:html/dom.dart' show Document;
-
-/**
- * Type of callback functions used by PendingFuture. Functions of this type
- * should perform a computation based on the data in [entry] and return it. If
- * the computation can't be performed yet because more analysis is needed,
- * `null` should be returned.
- *
- * The function may also throw an exception, in which case the corresponding
- * future will be completed with failure.
- *
- * Because this function is called while the state of analysis is being updated,
- * it should be free of side effects so that it doesn't cause reentrant changes
- * to the analysis state.
- */
-typedef T PendingFutureComputer<T>(CacheEntry entry);
-
-/**
- * An [AnalysisContext] in which analysis can be performed.
- */
-class AnalysisContextImpl implements InternalAnalysisContext {
- /**
- * The next context identifier.
- */
- static int _NEXT_ID = 0;
-
- /**
- * The unique identifier of this context.
- */
- final int _id = _NEXT_ID++;
-
- /**
- * A client-provided name used to identify this context, or `null` if the
- * client has not provided a name.
- */
- String name;
-
- /**
- * The set of analysis options controlling the behavior of this context.
- */
- AnalysisOptionsImpl _options = new AnalysisOptionsImpl();
-
- /**
- * A flag indicating whether this context is disposed.
- */
- bool _disposed = false;
-
- /**
- * A cache of content used to override the default content of a source.
- */
- ContentCache _contentCache = new ContentCache();
-
- /**
- * The source factory used to create the sources that can be analyzed in this
- * context.
- */
- SourceFactory _sourceFactory;
-
- /**
- * The set of declared variables used when computing constant values.
- */
- DeclaredVariables _declaredVariables = new DeclaredVariables();
-
- /**
- * The partition that contains analysis results that are not shared with other
- * contexts.
- */
- CachePartition _privatePartition;
-
- /**
- * The cache in which information about the results associated with targets
- * are stored.
- */
- AnalysisCache _cache;
-
- /**
- * The task manager used to manage the tasks used to analyze code.
- */
- TaskManager _taskManager;
-
- /**
- * The [DartWorkManager] instance that performs Dart specific scheduling.
- */
- DartWorkManager dartWorkManager;
-
- /**
- * The work manager that performs HTML specific scheduling.
- */
- HtmlWorkManager htmlWorkManager;
-
- /**
- * The analysis driver used to perform analysis.
- */
- AnalysisDriver driver;
-
- /**
- * A list containing sources for which data should not be flushed.
- */
- List<Source> _priorityOrder = <Source>[];
-
- /**
- * A map from all sources for which there are futures pending to a list of
- * the corresponding PendingFuture objects. These sources will be analyzed
- * in the same way as priority sources, except with higher priority.
- */
- HashMap<AnalysisTarget, List<PendingFuture>> _pendingFutureTargets =
- new HashMap<AnalysisTarget, List<PendingFuture>>();
-
- /**
- * A table mapping sources to the change notices that are waiting to be
- * returned related to that source.
- */
- HashMap<Source, ChangeNoticeImpl> _pendingNotices =
- new HashMap<Source, ChangeNoticeImpl>();
-
- /**
- * The [TypeProvider] for this context, `null` if not yet created.
- */
- TypeProvider _typeProvider;
-
- /**
- * The controller for sending [SourcesChangedEvent]s.
- */
- StreamController<SourcesChangedEvent> _onSourcesChangedController;
-
- /**
- * The listeners that are to be notified when various analysis results are
- * produced in this context.
- */
- List<AnalysisListener> _listeners = new List<AnalysisListener>();
-
- /**
- * The most recently incrementally resolved source, or `null` when it was
- * already validated, or the most recent change was not incrementally resolved.
- */
- Source incrementalResolutionValidation_lastUnitSource;
-
- /**
- * The most recently incrementally resolved library source, or `null` when it
- * was already validated, or the most recent change was not incrementally
- * resolved.
- */
- Source incrementalResolutionValidation_lastLibrarySource;
-
- /**
- * The result of incremental resolution result of
- * [incrementalResolutionValidation_lastSource].
- */
- CompilationUnit incrementalResolutionValidation_lastUnit;
-
- /**
- * A factory to override how the [ResolverVisitor] is created.
- */
- ResolverVisitorFactory resolverVisitorFactory;
-
- /**
- * A factory to override how the [TypeResolverVisitor] is created.
- */
- TypeResolverVisitorFactory typeResolverVisitorFactory;
-
- /**
- * A factory to override how [LibraryResolver] is created.
- */
- LibraryResolverFactory libraryResolverFactory;
-
- /**
- * Initialize a newly created analysis context.
- */
- AnalysisContextImpl() {
- _privatePartition = new UniversalCachePartition(this);
- _cache = createCacheFromSourceFactory(null);
- _taskManager = AnalysisEngine.instance.taskManager;
- // TODO(scheglov) Get WorkManager(Factory)(s) from plugins.
- dartWorkManager = new DartWorkManager(this);
- htmlWorkManager = new HtmlWorkManager(this);
- driver = new AnalysisDriver(
- _taskManager, <WorkManager>[dartWorkManager, htmlWorkManager], this);
- _onSourcesChangedController =
- new StreamController<SourcesChangedEvent>.broadcast();
- }
-
- @override
- AnalysisCache get analysisCache => _cache;
-
- @override
- AnalysisOptions get analysisOptions => _options;
-
- @override
- void set analysisOptions(AnalysisOptions options) {
- bool needsRecompute = this._options.analyzeFunctionBodiesPredicate !=
- options.analyzeFunctionBodiesPredicate ||
- this._options.generateImplicitErrors !=
- options.generateImplicitErrors ||
- this._options.generateSdkErrors != options.generateSdkErrors ||
- this._options.dart2jsHint != options.dart2jsHint ||
- (this._options.hint && !options.hint) ||
- (this._options.lint && !options.lint) ||
- this._options.preserveComments != options.preserveComments ||
- this._options.enableStrictCallChecks != options.enableStrictCallChecks;
- int cacheSize = options.cacheSize;
- if (this._options.cacheSize != cacheSize) {
- this._options.cacheSize = cacheSize;
- }
- this._options.analyzeFunctionBodiesPredicate =
- options.analyzeFunctionBodiesPredicate;
- this._options.generateImplicitErrors = options.generateImplicitErrors;
- this._options.generateSdkErrors = options.generateSdkErrors;
- this._options.dart2jsHint = options.dart2jsHint;
- this._options.enableStrictCallChecks = options.enableStrictCallChecks;
- this._options.hint = options.hint;
- this._options.incremental = options.incremental;
- this._options.incrementalApi = options.incrementalApi;
- this._options.incrementalValidation = options.incrementalValidation;
- this._options.lint = options.lint;
- this._options.preserveComments = options.preserveComments;
- if (needsRecompute) {
- dartWorkManager.onAnalysisOptionsChanged();
- htmlWorkManager.onAnalysisOptionsChanged();
- }
- }
-
- @override
- void set analysisPriorityOrder(List<Source> sources) {
- if (sources == null || sources.isEmpty) {
- _priorityOrder = Source.EMPTY_LIST;
- } else {
- while (sources.remove(null)) {
- // Nothing else to do.
- }
- if (sources.isEmpty) {
- _priorityOrder = Source.EMPTY_LIST;
- } else {
- _priorityOrder = sources;
- }
- }
- dartWorkManager.applyPriorityTargets(_priorityOrder);
- htmlWorkManager.applyPriorityTargets(_priorityOrder);
- }
-
- @override
- set contentCache(ContentCache value) {
- _contentCache = value;
- }
-
- @override
- DeclaredVariables get declaredVariables => _declaredVariables;
-
- @override
- List<AnalysisTarget> get explicitTargets {
- List<AnalysisTarget> targets = <AnalysisTarget>[];
- MapIterator<AnalysisTarget, CacheEntry> iterator = _cache.iterator();
- while (iterator.moveNext()) {
- if (iterator.value.explicitlyAdded) {
- targets.add(iterator.key);
- }
- }
- return targets;
- }
-
- @override
- List<Source> get htmlSources => _getSources(SourceKind.HTML);
-
- @override
- bool get isDisposed => _disposed;
-
- @override
- List<Source> get launchableClientLibrarySources {
- List<Source> sources = <Source>[];
- for (Source source in _cache.sources) {
- CacheEntry entry = _cache.get(source);
- if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY &&
- !source.isInSystemLibrary &&
- isClientLibrary(source)) {
- sources.add(source);
- }
- }
- return sources;
- }
-
- @override
- List<Source> get launchableServerLibrarySources {
- List<Source> sources = <Source>[];
- for (Source source in _cache.sources) {
- CacheEntry entry = _cache.get(source);
- if (source is Source &&
- entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY &&
- !source.isInSystemLibrary &&
- isServerLibrary(source)) {
- sources.add(source);
- }
- }
- return sources;
- }
-
- @override
- List<Source> get librarySources => _getSources(SourceKind.LIBRARY);
-
- @override
- Stream<SourcesChangedEvent> get onSourcesChanged =>
- _onSourcesChangedController.stream;
-
- /**
- * Make _pendingFutureSources available to unit tests.
- */
- HashMap<AnalysisTarget, List<PendingFuture>> get pendingFutureSources_forTesting =>
- _pendingFutureTargets;
-
- @override
- List<Source> get prioritySources => _priorityOrder;
-
- @override
- List<AnalysisTarget> get priorityTargets => prioritySources;
-
- @override
- CachePartition get privateAnalysisCachePartition => _privatePartition;
-
- @override
- SourceFactory get sourceFactory => _sourceFactory;
-
- @override
- void set sourceFactory(SourceFactory factory) {
- if (identical(_sourceFactory, factory)) {
- return;
- } else if (factory.context != null) {
- throw new IllegalStateException(
- "Source factories cannot be shared between contexts");
- }
- if (_sourceFactory != null) {
- _sourceFactory.context = null;
- }
- factory.context = this;
- _sourceFactory = factory;
- _cache = createCacheFromSourceFactory(factory);
- dartWorkManager.onSourceFactoryChanged();
- htmlWorkManager.onSourceFactoryChanged();
- }
-
- @override
- List<Source> get sources {
- return _cache.sources.toList();
- }
-
- /**
- * Return a list of the sources that would be processed by
- * [performAnalysisTask]. This method duplicates, and must therefore be kept
- * in sync with, [getNextAnalysisTask]. This method is intended to be used for
- * testing purposes only.
- */
- List<Source> get sourcesNeedingProcessing {
- HashSet<Source> sources = new HashSet<Source>();
- bool hintsEnabled = _options.hint;
- bool lintsEnabled = _options.lint;
-
- MapIterator<AnalysisTarget, CacheEntry> iterator =
- _privatePartition.iterator();
- while (iterator.moveNext()) {
- AnalysisTarget target = iterator.key;
- if (target is Source) {
- _getSourcesNeedingProcessing(
- target, iterator.value, false, hintsEnabled, lintsEnabled, sources);
- }
- }
- return new List<Source>.from(sources);
- }
-
- @override
- AnalysisContextStatistics get statistics {
- AnalysisContextStatisticsImpl statistics =
- new AnalysisContextStatisticsImpl();
- // TODO(brianwilkerson) Implement this.
-// visitCacheItems(statistics._internalPutCacheItem);
-// statistics.partitionData = _cache.partitionData;
- return statistics;
- }
-
- List<Source> get test_priorityOrder => _priorityOrder;
-
- @override
- TypeProvider get typeProvider {
- // Make sure a task didn't accidentally try to call back into the context
- // to retrieve the type provider.
- assert(!driver.isTaskRunning);
-
- if (_typeProvider != null) {
- return _typeProvider;
- }
- Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
- if (coreSource == null) {
- throw new AnalysisException("Could not create a source for dart:core");
- }
- LibraryElement coreElement = computeLibraryElement(coreSource);
- if (coreElement == null) {
- throw new AnalysisException("Could not create an element for dart:core");
- }
- Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
- if (asyncSource == null) {
- throw new AnalysisException("Could not create a source for dart:async");
- }
- LibraryElement asyncElement = computeLibraryElement(asyncSource);
- if (asyncElement == null) {
- throw new AnalysisException("Could not create an element for dart:async");
- }
- _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
- return _typeProvider;
- }
-
- /**
- * Sets the [TypeProvider] for this context.
- */
- void set typeProvider(TypeProvider typeProvider) {
- _typeProvider = typeProvider;
- }
-
- @override
- void addListener(AnalysisListener listener) {
- if (!_listeners.contains(listener)) {
- _listeners.add(listener);
- }
- }
-
- @override
- void applyAnalysisDelta(AnalysisDelta delta) {
- ChangeSet changeSet = new ChangeSet();
- delta.analysisLevels.forEach((Source source, AnalysisLevel level) {
- if (level == AnalysisLevel.NONE) {
- changeSet.removedSource(source);
- } else {
- changeSet.addedSource(source);
- }
- });
- applyChanges(changeSet);
- }
-
- @override
- void applyChanges(ChangeSet changeSet) {
- if (changeSet.isEmpty) {
- return;
- }
- //
- // First, compute the list of sources that have been removed.
- //
- List<Source> removedSources =
- new List<Source>.from(changeSet.removedSources);
- for (SourceContainer container in changeSet.removedContainers) {
- _addSourcesInContainer(removedSources, container);
- }
- //
- // Then determine which cached results are no longer valid.
- //
- for (Source source in changeSet.addedSources) {
- _sourceAvailable(source);
- }
- for (Source source in changeSet.changedSources) {
- if (_contentCache.getContents(source) != null) {
- // This source is overridden in the content cache, so the change will
- // have no effect. Just ignore it to avoid wasting time doing
- // re-analysis.
- continue;
- }
- _sourceChanged(source);
- }
- changeSet.changedContents.forEach((Source key, String value) {
- _contentsChanged(key, value, false);
- });
- changeSet.changedRanges
- .forEach((Source source, ChangeSet_ContentChange change) {
- _contentRangeChanged(source, change.contents, change.offset,
- change.oldLength, change.newLength);
- });
- for (Source source in changeSet.deletedSources) {
- _sourceDeleted(source);
- }
- for (Source source in removedSources) {
- _sourceRemoved(source);
- }
- dartWorkManager.applyChange(
- changeSet.addedSources, changeSet.changedSources, removedSources);
- htmlWorkManager.applyChange(
- changeSet.addedSources, changeSet.changedSources, removedSources);
- _onSourcesChangedController.add(new SourcesChangedEvent(changeSet));
- }
-
- @override
- String computeDocumentationComment(Element element) {
- if (element == null) {
- return null;
- }
- Source source = element.source;
- if (source == null) {
- return null;
- }
- CompilationUnit unit = parseCompilationUnit(source);
- if (unit == null) {
- return null;
- }
- NodeLocator locator = new NodeLocator(element.nameOffset);
- AstNode nameNode = locator.searchWithin(unit);
- while (nameNode != null) {
- if (nameNode is AnnotatedNode) {
- Comment comment = nameNode.documentationComment;
- if (comment == null) {
- return null;
- }
- StringBuffer buffer = new StringBuffer();
- List<Token> tokens = comment.tokens;
- for (int i = 0; i < tokens.length; i++) {
- if (i > 0) {
- buffer.write("\n");
- }
- buffer.write(tokens[i].lexeme);
- }
- return buffer.toString();
- }
- nameNode = nameNode.parent;
- }
- return null;
- }
-
- @override
- List<AnalysisError> computeErrors(Source source) {
- String name = source.shortName;
- if (AnalysisEngine.isDartFileName(name)) {
- return computeResult(source, DART_ERRORS);
- } else if (AnalysisEngine.isHtmlFileName(name)) {
- return computeResult(source, HTML_ERRORS);
- }
- return AnalysisError.NO_ERRORS;
- }
-
- @override
- List<Source> computeExportedLibraries(Source source) =>
- computeResult(source, EXPORTED_LIBRARIES);
-
- @override
- @deprecated
- HtmlElement computeHtmlElement(Source source) {
- // TODO(brianwilkerson) Remove this method after switching to the new task
- // model.
- throw new UnimplementedError('Not supported in the new task model');
- }
-
- @override
- List<Source> computeImportedLibraries(Source source) =>
- computeResult(source, EXPLICITLY_IMPORTED_LIBRARIES);
-
- @override
- SourceKind computeKindOf(Source source) {
- String name = source.shortName;
- if (AnalysisEngine.isDartFileName(name)) {
- return computeResult(source, SOURCE_KIND);
- } else if (AnalysisEngine.isHtmlFileName(name)) {
- return SourceKind.HTML;
- }
- return SourceKind.UNKNOWN;
- }
-
- @override
- LibraryElement computeLibraryElement(Source source) {
- //_computeResult(source, HtmlEntry.ELEMENT);
- return computeResult(source, LIBRARY_ELEMENT);
- }
-
- @override
- LineInfo computeLineInfo(Source source) => computeResult(source, LINE_INFO);
-
- @override
- @deprecated
- CompilationUnit computeResolvableCompilationUnit(Source source) {
- return null;
- }
-
- @override
- CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync(
- Source unitSource, Source librarySource) {
- if (!AnalysisEngine.isDartFileName(unitSource.shortName) ||
- !AnalysisEngine.isDartFileName(librarySource.shortName)) {
- return new CancelableFuture.error(new AnalysisNotScheduledError());
- }
- var unitTarget = new LibrarySpecificUnit(librarySource, unitSource);
- return new _AnalysisFutureHelper<CompilationUnit>(this).computeAsync(
- unitTarget, (CacheEntry entry) {
- CacheState state = entry.getState(RESOLVED_UNIT);
- if (state == CacheState.ERROR) {
- throw entry.exception;
- } else if (state == CacheState.INVALID) {
- return null;
- }
- return entry.getValue(RESOLVED_UNIT);
- }, () {
- dartWorkManager.addPriorityResult(unitTarget, RESOLVED_UNIT);
- });
- }
-
- Object /*V*/ computeResult(
- AnalysisTarget target, ResultDescriptor /*<V>*/ descriptor) {
- CacheEntry entry = getCacheEntry(target);
- CacheState state = entry.getState(descriptor);
- if (state == CacheState.FLUSHED || state == CacheState.INVALID) {
- driver.computeResult(target, descriptor);
- }
- state = entry.getState(descriptor);
- if (state == CacheState.ERROR) {
- throw new AnalysisException(
- 'Cannot compute $descriptor for $target', entry.exception);
- }
- return entry.getValue(descriptor);
- }
-
- /**
- * Create an analysis cache based on the given source [factory].
- */
- AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
- if (factory == null) {
- return new AnalysisCache(<CachePartition>[_privatePartition]);
- }
- DartSdk sdk = factory.dartSdk;
- if (sdk == null) {
- return new AnalysisCache(<CachePartition>[_privatePartition]);
- }
- return new AnalysisCache(<CachePartition>[
- AnalysisEngine.instance.partitionManager_new.forSdk(sdk),
- _privatePartition
- ]);
- }
-
- @override
- void dispose() {
- _disposed = true;
- for (List<PendingFuture> pendingFutures in _pendingFutureTargets.values) {
- for (PendingFuture pendingFuture in pendingFutures) {
- pendingFuture.forciblyComplete();
- }
- }
- _pendingFutureTargets.clear();
- _privatePartition.dispose();
- }
-
- @override
- List<CompilationUnit> ensureResolvedDartUnits(Source unitSource) {
- // Check every library.
- List<CompilationUnit> units = <CompilationUnit>[];
- List<Source> containingLibraries = getLibrariesContaining(unitSource);
- for (Source librarySource in containingLibraries) {
- LibrarySpecificUnit target =
- new LibrarySpecificUnit(librarySource, unitSource);
- CompilationUnit unit = _cache.getValue(target, RESOLVED_UNIT);
- if (unit == null) {
- units = null;
- break;
- }
- units.add(unit);
- }
- // If we have results, then we're done.
- if (units != null) {
- return units;
- }
- // Schedule recomputing RESOLVED_UNIT results.
- for (Source librarySource in containingLibraries) {
- LibrarySpecificUnit target =
- new LibrarySpecificUnit(librarySource, unitSource);
- if (_cache.getState(target, RESOLVED_UNIT) == CacheState.FLUSHED) {
- dartWorkManager.addPriorityResult(target, RESOLVED_UNIT);
- }
- }
- return null;
- }
-
- @override
- bool exists(Source source) {
- if (source == null) {
- return false;
- }
- if (_contentCache.getContents(source) != null) {
- return true;
- }
- return source.exists();
- }
-
- @override
- CacheEntry getCacheEntry(AnalysisTarget target) {
- CacheEntry entry = _cache.get(target);
- if (entry == null) {
- entry = new CacheEntry(target);
- if (target is Source) {
- entry.modificationTime = getModificationStamp(target);
- }
- _cache.put(entry);
- }
- return entry;
- }
-
- @override
- CompilationUnitElement getCompilationUnitElement(
- Source unitSource, Source librarySource) {
- AnalysisTarget target = new LibrarySpecificUnit(librarySource, unitSource);
- return _cache.getValue(target, COMPILATION_UNIT_ELEMENT);
- }
-
- @override
- TimestampedData<String> getContents(Source source) {
- String contents = _contentCache.getContents(source);
- if (contents != null) {
- return new TimestampedData<String>(
- _contentCache.getModificationStamp(source), contents);
- }
- return source.contents;
- }
-
- @override
- InternalAnalysisContext getContextFor(Source source) {
- InternalAnalysisContext context = _cache.getContextFor(source);
- return context == null ? this : context;
- }
-
- @override
- Element getElement(ElementLocation location) {
- // TODO(brianwilkerson) This should not be a "get" method.
- try {
- List<String> components = location.components;
- Source source = _computeSourceFromEncoding(components[0]);
- String sourceName = source.shortName;
- if (AnalysisEngine.isDartFileName(sourceName)) {
- ElementImpl element = computeLibraryElement(source) as ElementImpl;
- for (int i = 1; i < components.length; i++) {
- if (element == null) {
- return null;
- }
- element = element.getChild(components[i]);
- }
- return element;
- }
- } catch (exception) {
- // If the location cannot be decoded for some reason then the underlying
- // cause should have been logged already and we can fall though to return
- // null.
- }
- return null;
- }
-
- @override
- AnalysisErrorInfo getErrors(Source source) {
- String name = source.shortName;
- if (AnalysisEngine.isDartFileName(name) || source is DartScript) {
- return dartWorkManager.getErrors(source);
- } else if (AnalysisEngine.isHtmlFileName(name)) {
- return htmlWorkManager.getErrors(source);
- }
- return new AnalysisErrorInfoImpl(AnalysisError.NO_ERRORS, null);
- }
-
- @override
- @deprecated
- HtmlElement getHtmlElement(Source source) {
- // TODO(brianwilkerson) Remove this method after switching to the new task
- // model.
- throw new UnimplementedError('Not supported in the new task model');
- }
-
- @override
- List<Source> getHtmlFilesReferencing(Source source) {
- if (!AnalysisEngine.isDartFileName(source.shortName)) {
- return Source.EMPTY_LIST;
- }
- List<Source> htmlSources = <Source>[];
- List<Source> librarySources = getLibrariesContaining(source);
- for (Source source in _cache.sources) {
- if (AnalysisEngine.isHtmlFileName(source.shortName)) {
- List<Source> referencedLibraries =
- analysisCache.getValue(source, REFERENCED_LIBRARIES);
- if (_containsAny(referencedLibraries, librarySources)) {
- htmlSources.add(source);
- }
- }
- }
- if (htmlSources.isEmpty) {
- return Source.EMPTY_LIST;
- }
- return htmlSources;
- }
-
- @override
- SourceKind getKindOf(Source source) {
- String name = source.shortName;
- if (AnalysisEngine.isDartFileName(name)) {
- return _cache.getValue(source, SOURCE_KIND);
- } else if (AnalysisEngine.isHtmlFileName(name)) {
- return SourceKind.HTML;
- }
- return SourceKind.UNKNOWN;
- }
-
- @override
- List<Source> getLibrariesContaining(Source source) {
- SourceKind kind = getKindOf(source);
- if (kind == SourceKind.LIBRARY) {
- return <Source>[source];
- }
- return dartWorkManager.getLibrariesContainingPart(source);
- }
-
- @override
- List<Source> getLibrariesDependingOn(Source librarySource) {
- List<Source> dependentLibraries = <Source>[];
- for (Source source in _cache.sources) {
- CacheEntry entry = _cache.get(source);
- if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY) {
- if (_contains(entry.getValue(EXPORTED_LIBRARIES), librarySource)) {
- dependentLibraries.add(source);
- }
- if (_contains(entry.getValue(IMPORTED_LIBRARIES), librarySource)) {
- dependentLibraries.add(source);
- }
- }
- }
- if (dependentLibraries.isEmpty) {
- return Source.EMPTY_LIST;
- }
- return dependentLibraries;
- }
-
- @override
- List<Source> getLibrariesReferencedFromHtml(Source htmlSource) {
- CacheEntry entry = _cache.get(htmlSource);
- if (entry != null) {
- return entry.getValue(REFERENCED_LIBRARIES);
- }
- return Source.EMPTY_LIST;
- }
-
- @override
- LibraryElement getLibraryElement(Source source) =>
- _cache.getValue(source, LIBRARY_ELEMENT);
-
- @override
- LineInfo getLineInfo(Source source) => _cache.getValue(source, LINE_INFO);
-
- @override
- int getModificationStamp(Source source) {
- int stamp = _contentCache.getModificationStamp(source);
- if (stamp != null) {
- return stamp;
- }
- return source.modificationStamp;
- }
-
- @override
- ChangeNoticeImpl getNotice(Source source) {
- ChangeNoticeImpl notice = _pendingNotices[source];
- if (notice == null) {
- notice = new ChangeNoticeImpl(source);
- _pendingNotices[source] = notice;
- }
- return notice;
- }
-
- @override
- Namespace getPublicNamespace(LibraryElement library) {
- // TODO(brianwilkerson) Rename this to not start with 'get'.
- // Note that this is not part of the API of the interface.
- // TODO(brianwilkerson) The public namespace used to be cached, but no
- // longer is. Konstantin adds:
- // The only client of this method is NamespaceBuilder._createExportMapping(),
- // and it is not used with tasks - instead we compute export namespace once
- // using BuildExportNamespaceTask and reuse in scopes.
- NamespaceBuilder builder = new NamespaceBuilder();
- return builder.createPublicNamespaceForLibrary(library);
- }
-
- @override
- CompilationUnit getResolvedCompilationUnit(
- Source unitSource, LibraryElement library) {
- if (library == null ||
- !AnalysisEngine.isDartFileName(unitSource.shortName)) {
- return null;
- }
- return getResolvedCompilationUnit2(unitSource, library.source);
- }
-
- @override
- CompilationUnit getResolvedCompilationUnit2(
- Source unitSource, Source librarySource) {
- if (!AnalysisEngine.isDartFileName(unitSource.shortName) ||
- !AnalysisEngine.isDartFileName(librarySource.shortName)) {
- return null;
- }
- return _cache.getValue(
- new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT);
- }
-
- @override
- @deprecated
- ht.HtmlUnit getResolvedHtmlUnit(Source htmlSource) {
- // TODO(brianwilkerson) Remove this method after switching to the new task
- // model.
- throw new UnimplementedError('Not supported in the new task model');
- }
-
- @override
- List<Source> getSourcesWithFullName(String path) {
- return analysisCache.getSourcesWithFullName(path);
- }
-
- @override
- bool handleContentsChanged(
- Source source, String originalContents, String newContents, bool notify) {
- CacheEntry entry = _cache.get(source);
- if (entry == null) {
- return false;
- }
- bool changed = newContents != originalContents;
- if (newContents != null) {
- if (changed) {
- if (!analysisOptions.incremental ||
- !_tryPoorMansIncrementalResolution(source, newContents)) {
- _sourceChanged(source);
- }
- entry.modificationTime = _contentCache.getModificationStamp(source);
- entry.setValue(CONTENT, newContents, TargetedResult.EMPTY_LIST);
- } else {
- entry.modificationTime = _contentCache.getModificationStamp(source);
- }
- } else if (originalContents != null) {
- // We are removing the overlay for the file, check if the file's
- // contents is the same as it was in the overlay.
- try {
- TimestampedData<String> fileContents = getContents(source);
- newContents = fileContents.data;
- entry.modificationTime = fileContents.modificationTime;
- if (newContents == originalContents) {
- entry.setValue(CONTENT, newContents, TargetedResult.EMPTY_LIST);
- changed = false;
- }
- } catch (e) {}
- // If not the same content (e.g. the file is being closed without save),
- // then force analysis.
- if (changed) {
- if (!analysisOptions.incremental ||
- !_tryPoorMansIncrementalResolution(source, newContents)) {
- _sourceChanged(source);
- }
- }
- }
- if (notify && changed) {
- _onSourcesChangedController
- .add(new SourcesChangedEvent.changedContent(source, newContents));
- }
- return changed;
- }
-
- @override
- void invalidateLibraryHints(Source librarySource) {
- List<Source> sources = _cache.getValue(librarySource, UNITS);
- if (sources != null) {
- for (Source source in sources) {
- getCacheEntry(source).setState(HINTS, CacheState.INVALID);
- }
- }
- }
-
- @override
- bool isClientLibrary(Source librarySource) {
- CacheEntry entry = _cache.get(librarySource);
- return entry.getValue(IS_CLIENT) && entry.getValue(IS_LAUNCHABLE);
- }
-
- @override
- bool isServerLibrary(Source librarySource) {
- CacheEntry entry = _cache.get(librarySource);
- return !entry.getValue(IS_CLIENT) && entry.getValue(IS_LAUNCHABLE);
- }
-
- @override
- Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor) {
- return driver.onResultComputed(descriptor);
- }
-
- @override
- CompilationUnit parseCompilationUnit(Source source) {
- if (!AnalysisEngine.isDartFileName(source.shortName)) {
- return null;
- }
- try {
- getContents(source);
- } catch (exception, stackTrace) {
- throw new AnalysisException('Could not get contents of $source',
- new CaughtException(exception, stackTrace));
- }
- return computeResult(source, PARSED_UNIT);
- }
-
- @override
- Document parseHtmlDocument(Source source) {
- if (!AnalysisEngine.isHtmlFileName(source.shortName)) {
- return null;
- }
- return computeResult(source, HTML_DOCUMENT);
- }
-
- @override
- @deprecated // use parseHtmlDocument(source)
- ht.HtmlUnit parseHtmlUnit(Source source) {
- // TODO(brianwilkerson) Remove this method after switching to the new task
- // model.
- throw new UnimplementedError('Not supported in the new task model');
- }
-
- @override
- AnalysisResult performAnalysisTask() {
- return PerformanceStatistics.performAnaysis.makeCurrentWhile(() {
- _evaluatePendingFutures();
- bool done = !driver.performAnalysisTask();
- List<ChangeNotice> notices = _getChangeNotices(done);
- if (notices != null) {
- int noticeCount = notices.length;
- for (int i = 0; i < noticeCount; i++) {
- ChangeNotice notice = notices[i];
- _notifyErrors(notice.source, notice.errors, notice.lineInfo);
- }
- }
- return new AnalysisResult(notices, -1, '', -1);
- });
- }
-
- @override
- void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
- elementMap.forEach((Source librarySource, LibraryElement library) {
- //
- // Cache the element in the library's info.
- //
- CacheEntry entry = getCacheEntry(librarySource);
- setValue(ResultDescriptor result, value) {
- entry.setValue(result, value, TargetedResult.EMPTY_LIST);
- }
- setValue(BUILD_DIRECTIVES_ERRORS, AnalysisError.NO_ERRORS);
- setValue(BUILD_LIBRARY_ERRORS, AnalysisError.NO_ERRORS);
- // CLASS_ELEMENTS
- setValue(COMPILATION_UNIT_ELEMENT, library.definingCompilationUnit);
- // CONSTRUCTORS
- // CONSTRUCTORS_ERRORS
- entry.setState(CONTENT, CacheState.FLUSHED);
- setValue(EXPORTED_LIBRARIES, Source.EMPTY_LIST);
- // EXPORT_SOURCE_CLOSURE
- setValue(IMPORTED_LIBRARIES, Source.EMPTY_LIST);
- // IMPORT_SOURCE_CLOSURE
- setValue(INCLUDED_PARTS, Source.EMPTY_LIST);
- setValue(IS_CLIENT, true);
- setValue(IS_LAUNCHABLE, false);
- setValue(LIBRARY_ELEMENT, library);
- setValue(LIBRARY_ELEMENT1, library);
- setValue(LIBRARY_ELEMENT2, library);
- setValue(LIBRARY_ELEMENT3, library);
- setValue(LIBRARY_ELEMENT4, library);
- setValue(LIBRARY_ELEMENT5, library);
- setValue(LINE_INFO, new LineInfo(<int>[0]));
- setValue(PARSE_ERRORS, AnalysisError.NO_ERRORS);
- entry.setState(PARSED_UNIT, CacheState.FLUSHED);
- entry.setState(RESOLVE_TYPE_NAMES_ERRORS, CacheState.FLUSHED);
- setValue(SCAN_ERRORS, AnalysisError.NO_ERRORS);
- setValue(SOURCE_KIND, SourceKind.LIBRARY);
- entry.setState(TOKEN_STREAM, CacheState.FLUSHED);
- setValue(UNITS, <Source>[librarySource]);
-
- LibrarySpecificUnit unit =
- new LibrarySpecificUnit(librarySource, librarySource);
- entry = getCacheEntry(unit);
- setValue(HINTS, AnalysisError.NO_ERRORS);
- // dartEntry.setValue(LINTS, AnalysisError.NO_ERRORS);
- entry.setState(RESOLVE_REFERENCES_ERRORS, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT1, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT2, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT3, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT4, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT5, CacheState.FLUSHED);
- // USED_IMPORTED_ELEMENTS
- // USED_LOCAL_ELEMENTS
- setValue(VERIFY_ERRORS, AnalysisError.NO_ERRORS);
- });
-
- CacheEntry entry = getCacheEntry(AnalysisContextTarget.request);
- entry.setValue(TYPE_PROVIDER, typeProvider, TargetedResult.EMPTY_LIST);
- }
-
- @override
- void removeListener(AnalysisListener listener) {
- _listeners.remove(listener);
- }
-
- @override
- CompilationUnit resolveCompilationUnit(
- Source unitSource, LibraryElement library) {
- if (library == null) {
- return null;
- }
- return resolveCompilationUnit2(unitSource, library.source);
- }
-
- @override
- CompilationUnit resolveCompilationUnit2(
- Source unitSource, Source librarySource) {
- if (!AnalysisEngine.isDartFileName(unitSource.shortName) ||
- !AnalysisEngine.isDartFileName(librarySource.shortName)) {
- return null;
- }
- return computeResult(
- new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT);
- }
-
- @override
- @deprecated
- ht.HtmlUnit resolveHtmlUnit(Source htmlSource) {
- // TODO(brianwilkerson) Remove this method after switching to the new task
- // model.
- throw new UnimplementedError('Not supported in the new task model');
- }
-
- @override
- void setChangedContents(Source source, String contents, int offset,
- int oldLength, int newLength) {
- if (_contentRangeChanged(source, contents, offset, oldLength, newLength)) {
- _onSourcesChangedController.add(new SourcesChangedEvent.changedRange(
- source, contents, offset, oldLength, newLength));
- }
- }
-
- @override
- void setContents(Source source, String contents) {
- _contentsChanged(source, contents, true);
- }
-
- @override
- bool shouldErrorsBeAnalyzed(Source source, Object entry) {
- CacheEntry entry = analysisCache.get(source);
- if (source.isInSystemLibrary) {
- return _options.generateSdkErrors;
- } else if (!entry.explicitlyAdded) {
- return _options.generateImplicitErrors;
- } else {
- return true;
- }
- }
-
- @override
- void test_flushAstStructures(Source source) {
- CacheEntry entry = getCacheEntry(source);
- entry.setState(PARSED_UNIT, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT1, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT2, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT3, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT4, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT5, CacheState.FLUSHED);
- entry.setState(RESOLVED_UNIT, CacheState.FLUSHED);
- }
-
- @override
- bool validateCacheConsistency() {
- int consistencyCheckStart = JavaSystem.nanoTime();
- HashSet<Source> changedSources = new HashSet<Source>();
- HashSet<Source> missingSources = new HashSet<Source>();
- for (Source source in _cache.sources) {
- CacheEntry entry = _cache.get(source);
- int sourceTime = getModificationStamp(source);
- if (sourceTime != entry.modificationTime) {
- changedSources.add(source);
- }
- if (entry.exception != null) {
- if (!exists(source)) {
- missingSources.add(source);
- }
- }
- }
- for (Source source in changedSources) {
- _sourceChanged(source);
- }
- int removalCount = 0;
- for (Source source in missingSources) {
- if (getLibrariesContaining(source).isEmpty &&
- getLibrariesDependingOn(source).isEmpty) {
- _cache.remove(source);
- removalCount++;
- }
- }
- int consistencyCheckEnd = JavaSystem.nanoTime();
- if (changedSources.length > 0 || missingSources.length > 0) {
- StringBuffer buffer = new StringBuffer();
- buffer.write("Consistency check took ");
- buffer.write((consistencyCheckEnd - consistencyCheckStart) / 1000000.0);
- buffer.writeln(" ms and found");
- buffer.write(" ");
- buffer.write(changedSources.length);
- buffer.writeln(" inconsistent entries");
- buffer.write(" ");
- buffer.write(missingSources.length);
- buffer.write(" missing sources (");
- buffer.write(removalCount);
- buffer.writeln(" removed");
- for (Source source in missingSources) {
- buffer.write(" ");
- buffer.writeln(source.fullName);
- }
- _logInformation(buffer.toString());
- }
- return changedSources.length > 0;
- }
-
- @deprecated
- @override
- void visitCacheItems(void callback(Source source, SourceEntry dartEntry,
- DataDescriptor rowDesc, CacheState state)) {
- // TODO(brianwilkerson) Figure out where this is used and either remove it
- // or adjust the call sites to use CacheEntry's.
-// bool hintsEnabled = _options.hint;
-// bool lintsEnabled = _options.lint;
-// MapIterator<AnalysisTarget, cache.CacheEntry> iterator = _cache.iterator();
-// while (iterator.moveNext()) {
-// Source source = iterator.key;
-// cache.CacheEntry entry = iterator.value;
-// for (DataDescriptor descriptor in entry.descriptors) {
-// if (descriptor == DartEntry.SOURCE_KIND) {
-// // The source kind is always valid, so the state isn't interesting.
-// continue;
-// } else if (descriptor == DartEntry.CONTAINING_LIBRARIES) {
-// // The list of containing libraries is always valid, so the state
-// // isn't interesting.
-// continue;
-// } else if (descriptor == DartEntry.PUBLIC_NAMESPACE) {
-// // The public namespace isn't computed by performAnalysisTask()
-// // and therefore isn't interesting.
-// continue;
-// } else if (descriptor == HtmlEntry.HINTS) {
-// // We are not currently recording any hints related to HTML.
-// continue;
-// }
-// callback(
-// source, entry, descriptor, entry.getState(descriptor));
-// }
-// if (entry is DartEntry) {
-// // get library-specific values
-// List<Source> librarySources = getLibrariesContaining(source);
-// for (Source librarySource in librarySources) {
-// for (DataDescriptor descriptor in entry.libraryDescriptors) {
-// if (descriptor == DartEntry.BUILT_ELEMENT ||
-// descriptor == DartEntry.BUILT_UNIT) {
-// // These values are not currently being computed, so their state
-// // is not interesting.
-// continue;
-// } else if (!entry.explicitlyAdded &&
-// !_generateImplicitErrors &&
-// (descriptor == DartEntry.VERIFICATION_ERRORS ||
-// descriptor == DartEntry.HINTS ||
-// descriptor == DartEntry.LINTS)) {
-// continue;
-// } else if (source.isInSystemLibrary &&
-// !_generateSdkErrors &&
-// (descriptor == DartEntry.VERIFICATION_ERRORS ||
-// descriptor == DartEntry.HINTS ||
-// descriptor == DartEntry.LINTS)) {
-// continue;
-// } else if (!hintsEnabled && descriptor == DartEntry.HINTS) {
-// continue;
-// } else if (!lintsEnabled && descriptor == DartEntry.LINTS) {
-// continue;
-// }
-// callback(librarySource, entry, descriptor,
-// entry.getStateInLibrary(descriptor, librarySource));
-// }
-// }
-// }
-// }
- }
-
- @override
- void visitContentCache(ContentCacheVisitor visitor) {
- _contentCache.accept(visitor);
- }
-
- /**
- * Add all of the sources contained in the given source [container] to the
- * given list of [sources].
- */
- void _addSourcesInContainer(List<Source> sources, SourceContainer container) {
- for (Source source in _cache.sources) {
- if (container.contains(source)) {
- sources.add(source);
- }
- }
- }
-
- /**
- * Remove the given [pendingFuture] from [_pendingFutureTargets], since the
- * client has indicated its computation is not needed anymore.
- */
- void _cancelFuture(PendingFuture pendingFuture) {
- List<PendingFuture> pendingFutures =
- _pendingFutureTargets[pendingFuture.target];
- if (pendingFutures != null) {
- pendingFutures.remove(pendingFuture);
- if (pendingFutures.isEmpty) {
- _pendingFutureTargets.remove(pendingFuture.target);
- }
- }
- }
-
- /**
- * Given the encoded form of a source ([encoding]), use the source factory to
- * reconstitute the original source.
- */
- Source _computeSourceFromEncoding(String encoding) =>
- _sourceFactory.fromEncoding(encoding);
-
- /**
- * Return `true` if the given list of [sources] contains the given
- * [targetSource].
- */
- bool _contains(List<Source> sources, Source targetSource) {
- for (Source source in sources) {
- if (source == targetSource) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Return `true` if the given list of [sources] contains any of the given
- * [targetSources].
- */
- bool _containsAny(List<Source> sources, List<Source> targetSources) {
- for (Source targetSource in targetSources) {
- if (_contains(sources, targetSource)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Set the contents of the given [source] to the given [contents] and mark the
- * source as having changed. The additional [offset], [oldLength] and
- * [newLength] information is used by the context to determine what reanalysis
- * is necessary. The method [setChangedContents] triggers a source changed
- * event where as this method does not.
- */
- bool _contentRangeChanged(Source source, String contents, int offset,
- int oldLength, int newLength) {
- bool changed = false;
- String originalContents = _contentCache.setContents(source, contents);
- if (contents != null) {
- if (contents != originalContents) {
- _sourceChanged(source);
- changed = true;
- CacheEntry entry = _cache.get(source);
- if (entry != null) {
- entry.modificationTime = _contentCache.getModificationStamp(source);
- entry.setValue(CONTENT, contents, TargetedResult.EMPTY_LIST);
- }
- }
- } else if (originalContents != null) {
- _sourceChanged(source);
- changed = true;
- }
- return changed;
- }
-
- /**
- * Set the contents of the given [source] to the given [contents] and mark the
- * source as having changed. This has the effect of overriding the default
- * contents of the source. If the contents are `null` the override is removed
- * so that the default contents will be returned. If [notify] is true, a
- * source changed event is triggered.
- */
- void _contentsChanged(Source source, String contents, bool notify) {
- String originalContents = _contentCache.setContents(source, contents);
- handleContentsChanged(source, originalContents, contents, notify);
- }
-
- /**
- * Create a cache entry for the given [source]. The source was explicitly
- * added to this context if [explicitlyAdded] is `true`. Return the cache
- * entry that was created.
- */
- CacheEntry _createCacheEntry(Source source, bool explicitlyAdded) {
- CacheEntry entry = new CacheEntry(source);
- entry.modificationTime = getModificationStamp(source);
- entry.explicitlyAdded = explicitlyAdded;
- _cache.put(entry);
- return entry;
- }
-
- /**
- * Return a list containing all of the cache entries for targets associated
- * with the given [source].
- */
- List<CacheEntry> _entriesFor(Source source) {
- List<CacheEntry> entries = <CacheEntry>[];
- MapIterator<AnalysisTarget, CacheEntry> iterator = _cache.iterator();
- while (iterator.moveNext()) {
- if (iterator.key.source == source) {
- entries.add(iterator.value);
- }
- }
- return entries;
- }
-
- void _evaluatePendingFutures() {
- for (AnalysisTarget target in _pendingFutureTargets.keys) {
- CacheEntry cacheEntry = _cache.get(target);
- List<PendingFuture> pendingFutures = _pendingFutureTargets[target];
- for (int i = 0; i < pendingFutures.length;) {
- if (pendingFutures[i].evaluate(cacheEntry)) {
- pendingFutures.removeAt(i);
- } else {
- i++;
- }
- }
- }
- }
-
- /**
- * Return a list containing all of the change notices that are waiting to be
- * returned. If there are no notices, then return either `null` or an empty
- * list, depending on the value of [nullIfEmpty].
- */
- List<ChangeNotice> _getChangeNotices(bool nullIfEmpty) {
- if (_pendingNotices.isEmpty) {
- if (nullIfEmpty) {
- return null;
- }
- return ChangeNoticeImpl.EMPTY_LIST;
- }
- List<ChangeNotice> notices = new List.from(_pendingNotices.values);
- _pendingNotices.clear();
- return notices;
- }
-
- /**
- * Return a list containing all of the sources known to this context that have
- * the given [kind].
- */
- List<Source> _getSources(SourceKind kind) {
- List<Source> sources = <Source>[];
- if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) {
- for (Source source in _cache.sources) {
- CacheEntry entry = _cache.get(source);
- if (entry.getValue(SOURCE_KIND) == kind) {
- sources.add(source);
- }
- }
- } else if (kind == SourceKind.HTML) {
- for (Source source in _cache.sources) {
- if (AnalysisEngine.isHtmlFileName(source.shortName)) {
- sources.add(source);
- }
- }
- }
- if (sources.isEmpty) {
- return Source.EMPTY_LIST;
- }
- return sources;
- }
-
- /**
- * Look at the given [source] to see whether a task needs to be performed
- * related to it. If so, add the source to the set of sources that need to be
- * processed. This method is intended to be used for testing purposes only.
- */
- void _getSourcesNeedingProcessing(Source source, CacheEntry entry,
- bool isPriority, bool hintsEnabled, bool lintsEnabled,
- HashSet<Source> sources) {
- CacheState state = entry.getState(CONTENT);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- state = entry.getState(SOURCE_KIND);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- SourceKind kind = entry.getValue(SOURCE_KIND);
- if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) {
- state = entry.getState(SCAN_ERRORS);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- state = entry.getState(PARSE_ERRORS);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
-// if (isPriority) {
-// if (!entry.hasResolvableCompilationUnit) {
-// sources.add(source);
-// return;
-// }
-// }
- for (Source librarySource in getLibrariesContaining(source)) {
- CacheEntry libraryEntry = _cache.get(librarySource);
- state = libraryEntry.getState(LIBRARY_ELEMENT);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- CacheEntry unitEntry =
- _cache.get(new LibrarySpecificUnit(librarySource, source));
- state = unitEntry.getState(RESOLVED_UNIT);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- if (shouldErrorsBeAnalyzed(source, unitEntry)) {
- state = unitEntry.getState(VERIFY_ERRORS);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- if (hintsEnabled) {
- state = unitEntry.getState(HINTS);
- if (state == CacheState.INVALID ||
- (isPriority && state == CacheState.FLUSHED)) {
- sources.add(source);
- return;
- } else if (state == CacheState.ERROR) {
- return;
- }
- }
-// if (lintsEnabled) {
-// state = unitEntry.getState(LINTS);
-// if (state == CacheState.INVALID ||
-// (isPriority && state == CacheState.FLUSHED)) {
-// sources.add(source);
-// return;
-// } else if (state == CacheState.ERROR) {
-// return;
-// }
-// }
- }
- }
-// } else if (kind == SourceKind.HTML) {
-// CacheState parsedUnitState = entry.getState(HtmlEntry.PARSED_UNIT);
-// if (parsedUnitState == CacheState.INVALID ||
-// (isPriority && parsedUnitState == CacheState.FLUSHED)) {
-// sources.add(source);
-// return;
-// }
-// CacheState resolvedUnitState =
-// entry.getState(HtmlEntry.RESOLVED_UNIT);
-// if (resolvedUnitState == CacheState.INVALID ||
-// (isPriority && resolvedUnitState == CacheState.FLUSHED)) {
-// sources.add(source);
-// return;
-// }
- }
- }
-
- /**
- * Log the given debugging [message].
- */
- void _logInformation(String message) {
- AnalysisEngine.instance.logger.logInformation(message);
- }
-
- /**
- * Notify all of the analysis listeners that the errors associated with the
- * given [source] has been updated to the given [errors].
- */
- void _notifyErrors(
- Source source, List<AnalysisError> errors, LineInfo lineInfo) {
- int count = _listeners.length;
- for (int i = 0; i < count; i++) {
- _listeners[i].computedErrors(this, source, errors, lineInfo);
- }
- }
-
- /**
- * Remove the given [source] from the priority order if it is in the list.
- */
- void _removeFromPriorityOrder(Source source) {
- int count = _priorityOrder.length;
- List<Source> newOrder = <Source>[];
- for (int i = 0; i < count; i++) {
- if (_priorityOrder[i] != source) {
- newOrder.add(_priorityOrder[i]);
- }
- }
- if (newOrder.length < count) {
- analysisPriorityOrder = newOrder;
- }
- }
-
- /**
- * Create an entry for the newly added [source] and invalidate any sources
- * that referenced the source before it existed.
- */
- void _sourceAvailable(Source source) {
- CacheEntry entry = _cache.get(source);
- if (entry == null) {
- _createCacheEntry(source, true);
- } else {
- entry.modificationTime = getModificationStamp(source);
- entry.setState(CONTENT, CacheState.INVALID);
- }
- }
-
- /**
- * Invalidate the [source] that was changed and any sources that referenced
- * the source before it existed.
- */
- void _sourceChanged(Source source) {
- CacheEntry entry = _cache.get(source);
- // If the source is removed, we don't care about it.
- if (entry == null) {
- return;
- }
- // Check whether the content of the source is the same as it was the last
- // time.
- String sourceContent = entry.getValue(CONTENT);
- if (sourceContent != null) {
- entry.setState(CONTENT, CacheState.FLUSHED);
- try {
- TimestampedData<String> fileContents = getContents(source);
- if (fileContents.data == sourceContent) {
- int time = fileContents.modificationTime;
- for (CacheEntry entry in _entriesFor(source)) {
- entry.modificationTime = time;
- }
- return;
- }
- } catch (e) {}
- }
- // We need to invalidate the cache.
- {
- Object delta = null;
- if (AnalysisEngine.instance.limitInvalidationInTaskModel &&
- AnalysisEngine.isDartFileName(source.fullName)) {
- // TODO(scheglov) Incorrect implementation in general.
- entry.setState(TOKEN_STREAM, CacheState.FLUSHED);
- entry.setState(PARSED_UNIT, CacheState.FLUSHED);
- List<Source> librarySources = getLibrariesContaining(source);
- if (librarySources.length == 1) {
- Source librarySource = librarySources[0];
- CompilationUnit oldUnit =
- getResolvedCompilationUnit2(source, librarySource);
- if (oldUnit != null) {
- CompilationUnit newUnit = parseCompilationUnit(source);
- IncrementalCompilationUnitElementBuilder builder =
- new IncrementalCompilationUnitElementBuilder(oldUnit, newUnit);
- builder.build();
- CompilationUnitElementDelta unitDelta = builder.unitDelta;
- if (!unitDelta.hasDirectiveChange) {
- DartDelta dartDelta = new DartDelta(source);
- dartDelta.hasDirectiveChange = unitDelta.hasDirectiveChange;
- unitDelta.addedDeclarations.forEach(dartDelta.elementAdded);
- unitDelta.removedDeclarations.forEach(dartDelta.elementRemoved);
-// print(
-// 'dartDelta: add=${dartDelta.addedNames} remove=${dartDelta.removedNames}');
- delta = dartDelta;
- entry.setState(CONTENT, CacheState.INVALID, delta: delta);
- return;
- }
- }
- }
- }
- entry.setState(CONTENT, CacheState.INVALID);
- }
- dartWorkManager.applyChange(
- Source.EMPTY_LIST, <Source>[source], Source.EMPTY_LIST);
- htmlWorkManager.applyChange(
- Source.EMPTY_LIST, <Source>[source], Source.EMPTY_LIST);
- }
-
- /**
- * Record that the give [source] has been deleted.
- */
- void _sourceDeleted(Source source) {
- // TODO(brianwilkerson) Implement this.
-// SourceEntry sourceEntry = _cache.get(source);
-// if (sourceEntry is HtmlEntry) {
-// HtmlEntry htmlEntry = sourceEntry;
-// htmlEntry.recordContentError(new CaughtException(
-// new AnalysisException("This source was marked as being deleted"),
-// null));
-// } else if (sourceEntry is DartEntry) {
-// DartEntry dartEntry = sourceEntry;
-// HashSet<Source> libraries = new HashSet<Source>();
-// for (Source librarySource in getLibrariesContaining(source)) {
-// libraries.add(librarySource);
-// for (Source dependentLibrary
-// in getLibrariesDependingOn(librarySource)) {
-// libraries.add(dependentLibrary);
-// }
-// }
-// for (Source librarySource in libraries) {
-// _invalidateLibraryResolution(librarySource);
-// }
-// dartEntry.recordContentError(new CaughtException(
-// new AnalysisException("This source was marked as being deleted"),
-// null));
-// }
- _removeFromPriorityOrder(source);
- }
-
- /**
- * Record that the given [source] has been removed.
- */
- void _sourceRemoved(Source source) {
- _cache.remove(source);
- _removeFromPriorityOrder(source);
- }
-
- /**
- * TODO(scheglov) A hackish, limited incremental resolution implementation.
- */
- bool _tryPoorMansIncrementalResolution(Source unitSource, String newCode) {
- return PerformanceStatistics.incrementalAnalysis.makeCurrentWhile(() {
- incrementalResolutionValidation_lastUnitSource = null;
- incrementalResolutionValidation_lastLibrarySource = null;
- incrementalResolutionValidation_lastUnit = null;
- // prepare the entry
- CacheEntry sourceEntry = _cache.get(unitSource);
- if (sourceEntry == null) {
- return false;
- }
- // prepare the (only) library source
- List<Source> librarySources = getLibrariesContaining(unitSource);
- if (librarySources.length != 1) {
- return false;
- }
- Source librarySource = librarySources[0];
- CacheEntry unitEntry =
- _cache.get(new LibrarySpecificUnit(librarySource, unitSource));
- if (unitEntry == null) {
- return false;
- }
- // prepare the library element
- LibraryElement libraryElement = getLibraryElement(librarySource);
- if (libraryElement == null) {
- return false;
- }
- // prepare the existing unit
- CompilationUnit oldUnit =
- getResolvedCompilationUnit2(unitSource, librarySource);
- if (oldUnit == null) {
- return false;
- }
- // do resolution
- Stopwatch perfCounter = new Stopwatch()..start();
- PoorMansIncrementalResolver resolver = new PoorMansIncrementalResolver(
- typeProvider, unitSource, null, sourceEntry, unitEntry, oldUnit,
- analysisOptions.incrementalApi, analysisOptions);
- bool success = resolver.resolve(newCode);
- AnalysisEngine.instance.instrumentationService.logPerformance(
- AnalysisPerformanceKind.INCREMENTAL, perfCounter,
- 'success=$success,context_id=$_id,code_length=${newCode.length}');
- if (!success) {
- return false;
- }
- // if validation, remember the result, but throw it away
- if (analysisOptions.incrementalValidation) {
- incrementalResolutionValidation_lastUnitSource = oldUnit.element.source;
- incrementalResolutionValidation_lastLibrarySource =
- oldUnit.element.library.source;
- incrementalResolutionValidation_lastUnit = oldUnit;
- return false;
- }
- // prepare notice
- {
- ChangeNoticeImpl notice = getNotice(unitSource);
- notice.resolvedDartUnit = oldUnit;
- AnalysisErrorInfo errorInfo = getErrors(unitSource);
- notice.setErrors(errorInfo.errors, errorInfo.lineInfo);
- }
- // schedule
- dartWorkManager.unitIncrementallyResolved(librarySource, unitSource);
- // OK
- return true;
- });
- }
-}
-
-/**
- * An object that manages the partitions that can be shared between analysis
- * contexts.
- */
-class PartitionManager {
- /**
- * A table mapping SDK's to the partitions used for those SDK's.
- */
- HashMap<DartSdk, SdkCachePartition> _sdkPartitions =
- new HashMap<DartSdk, SdkCachePartition>();
-
- /**
- * Clear any cached data being maintained by this manager.
- */
- void clearCache() {
- _sdkPartitions.clear();
- }
-
- /**
- * Return the partition being used for the given [sdk], creating the partition
- * if necessary.
- */
- SdkCachePartition forSdk(DartSdk sdk) {
- // Call sdk.context now, because when it creates a new
- // InternalAnalysisContext instance, it calls forSdk() again, so creates an
- // SdkCachePartition instance.
- // So, if we initialize context after "partition == null", we end up
- // with two SdkCachePartition instances.
- InternalAnalysisContext sdkContext = sdk.context;
- // Check cache for an existing partition.
- SdkCachePartition partition = _sdkPartitions[sdk];
- if (partition == null) {
- partition = new SdkCachePartition(sdkContext);
- _sdkPartitions[sdk] = partition;
- }
- return partition;
- }
-}
-
-/**
- * Representation of a pending computation which is based on the results of
- * analysis that may or may not have been completed.
- */
-class PendingFuture<T> {
- /**
- * The context in which this computation runs.
- */
- final AnalysisContextImpl _context;
-
- /**
- * The target used by this computation to compute its value.
- */
- final AnalysisTarget target;
-
- /**
- * The function which implements the computation.
- */
- final PendingFutureComputer<T> _computeValue;
-
- /**
- * The completer that should be completed once the computation has succeeded.
- */
- CancelableCompleter<T> _completer;
-
- PendingFuture(this._context, this.target, this._computeValue) {
- _completer = new CancelableCompleter<T>(_onCancel);
- }
-
- /**
- * Retrieve the future which will be completed when this object is
- * successfully evaluated.
- */
- CancelableFuture<T> get future => _completer.future;
-
- /**
- * Execute [_computeValue], passing it the given [entry], and complete
- * the pending future if it's appropriate to do so. If the pending future is
- * completed by this call, true is returned; otherwise false is returned.
- *
- * Once this function has returned true, it should not be called again.
- *
- * Other than completing the future, this method is free of side effects.
- * Note that any code the client has attached to the future will be executed
- * in a microtask, so there is no danger of side effects occurring due to
- * client callbacks.
- */
- bool evaluate(CacheEntry entry) {
- assert(!_completer.isCompleted);
- try {
- T result = _computeValue(entry);
- if (result == null) {
- return false;
- } else {
- _completer.complete(result);
- return true;
- }
- } catch (exception, stackTrace) {
- _completer.completeError(exception, stackTrace);
- return true;
- }
- }
-
- /**
- * No further analysis updates are expected which affect this future, so
- * complete it with an AnalysisNotScheduledError in order to avoid
- * deadlocking the client.
- */
- void forciblyComplete() {
- try {
- throw new AnalysisNotScheduledError();
- } catch (exception, stackTrace) {
- _completer.completeError(exception, stackTrace);
- }
- }
-
- void _onCancel() {
- _context._cancelFuture(this);
- }
-}
-
-/**
- * An [AnalysisContext] that only contains sources for a Dart SDK.
- */
-class SdkAnalysisContext extends AnalysisContextImpl {
- @override
- AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
- if (factory == null) {
- return super.createCacheFromSourceFactory(factory);
- }
- DartSdk sdk = factory.dartSdk;
- if (sdk == null) {
- throw new IllegalArgumentException(
- "The source factory for an SDK analysis context must have a DartUriResolver");
- }
- return new AnalysisCache(<CachePartition>[
- AnalysisEngine.instance.partitionManager_new.forSdk(sdk)
- ]);
- }
-}
-
-/**
- * A helper class used to create futures for [AnalysisContextImpl].
- * Using a helper class allows us to preserve the generic parameter T.
- */
-class _AnalysisFutureHelper<T> {
- final AnalysisContextImpl _context;
-
- _AnalysisFutureHelper(this._context);
-
- /**
- * Return a future that will be completed with the result of calling
- * [computeValue]. If [computeValue] returns non-`null`, the future will be
- * completed immediately with the resulting value. If it returns `null`, then
- * [scheduleComputation] is invoked to schedule analysis that will produce
- * the required result, and [computeValue] will be re-executed in the future,
- * after the next time the cached information for [target] has changed. If
- * [computeValue] throws an exception, the future will fail with that
- * exception.
- *
- * If the [computeValue] still returns `null` after there is no further
- * analysis to be done for [target], then the future will be completed with
- * the error AnalysisNotScheduledError.
- *
- * Since [computeValue] will be called while the state of analysis is being
- * updated, it should be free of side effects so that it doesn't cause
- * reentrant changes to the analysis state.
- */
- CancelableFuture<T> computeAsync(AnalysisTarget target,
- T computeValue(CacheEntry entry), void scheduleComputation()) {
- if (_context.isDisposed) {
- // No further analysis is expected, so return a future that completes
- // immediately with AnalysisNotScheduledError.
- return new CancelableFuture.error(new AnalysisNotScheduledError());
- }
- CacheEntry entry = _context.getCacheEntry(target);
- PendingFuture pendingFuture =
- new PendingFuture<T>(_context, target, computeValue);
- if (!pendingFuture.evaluate(entry)) {
- _context._pendingFutureTargets
- .putIfAbsent(target, () => <PendingFuture>[])
- .add(pendingFuture);
- scheduleComputation();
- }
- return pendingFuture.future;
- }
-}
« no previous file with comments | « analyzer/lib/src/context/cache.dart ('k') | analyzer/lib/src/error.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698