| Index: pkg/analyzer_cli/lib/src/incremental_analyzer.dart
|
| diff --git a/pkg/analyzer_cli/lib/src/incremental_analyzer.dart b/pkg/analyzer_cli/lib/src/incremental_analyzer.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..be2316537d3b9b60b458e1d5c9520d8f2142fd84
|
| --- /dev/null
|
| +++ b/pkg/analyzer_cli/lib/src/incremental_analyzer.dart
|
| @@ -0,0 +1,162 @@
|
| +// Copyright (c) 2016, 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_cli.src.incremental_analyzer;
|
| +
|
| +import 'dart:io' as io;
|
| +
|
| +import 'package:analyzer/dart/element/element.dart';
|
| +import 'package:analyzer/file_system/physical_file_system.dart';
|
| +import 'package:analyzer/src/context/cache.dart';
|
| +import 'package:analyzer/src/context/context.dart';
|
| +import 'package:analyzer/src/generated/engine.dart';
|
| +import 'package:analyzer/src/generated/error.dart';
|
| +import 'package:analyzer/src/generated/sdk.dart';
|
| +import 'package:analyzer/src/generated/sdk_io.dart';
|
| +import 'package:analyzer/src/generated/source.dart';
|
| +import 'package:analyzer/src/summary/incremental_cache.dart';
|
| +import 'package:analyzer/src/summary/package_bundle_reader.dart';
|
| +import 'package:analyzer/src/task/dart.dart';
|
| +import 'package:analyzer/task/dart.dart';
|
| +import 'package:analyzer/task/model.dart';
|
| +import 'package:analyzer_cli/src/options.dart';
|
| +
|
| +/**
|
| + * If the given [options] enables incremental analysis and [context] and Dart
|
| + * SDK implementations support incremental analysis, configure it for the
|
| + * given [context] and return the handle to work with it.
|
| + */
|
| +IncrementalAnalysisData configureIncrementalAnalysis(
|
| + CommandLineOptions options, AnalysisContext context) {
|
| + String cachePath = options.incrementalCachePath;
|
| + DartSdk sdk = context.sourceFactory.dartSdk;
|
| + // If supported implementations, configure for incremental analysis.
|
| + if (cachePath != null &&
|
| + context is InternalAnalysisContext &&
|
| + sdk is DirectoryBasedDartSdk) {
|
| + context.typeProvider = sdk.context.typeProvider;
|
| + // Set the result provide from the cache.
|
| + CacheStorage storage = new FolderCacheStorage(
|
| + PhysicalResourceProvider.INSTANCE.getFolder(cachePath),
|
| + '${io.pid}.temp');
|
| + List<int> configSalt = <int>[
|
| + context.analysisOptions.encodeCrossContextOptions()
|
| + ];
|
| + IncrementalCache cache = new IncrementalCache(storage, context, configSalt);
|
| + context.resultProvider = new _CacheBasedResultProvider(context, cache);
|
| + // Listen for new libraries to put into the cache.
|
| + _IncrementalAnalysisData incrementalData =
|
| + new _IncrementalAnalysisData(options, cache, context);
|
| + context
|
| + .onResultChanged(LIBRARY_ELEMENT1)
|
| + .listen((ResultChangedEvent event) {
|
| + if (event.wasComputed) {
|
| + incrementalData.librarySources.add(event.target.source);
|
| + }
|
| + });
|
| + return incrementalData;
|
| + }
|
| + // Incremental analysis cannot be used.
|
| + return null;
|
| +}
|
| +
|
| +/**
|
| + * Interface that is exposed to the clients of incremental analysis.
|
| + */
|
| +abstract class IncrementalAnalysisData {
|
| + /**
|
| + * Finish tasks required after incremental analysis - save results into the
|
| + * cache, evict old results, etc.
|
| + */
|
| + void finish();
|
| +}
|
| +
|
| +/**
|
| + * The [ResultProvider] that provides results from [IncrementalCache].
|
| + */
|
| +class _CacheBasedResultProvider extends ResynthesizerResultProvider {
|
| + final IncrementalCache cache;
|
| +
|
| + final Set<Source> sourcesWithSummaries = new Set<Source>();
|
| + final Set<Source> sourcesWithoutSummaries = new Set<Source>();
|
| + final Set<String> addedLibraryBundleIds = new Set<String>();
|
| +
|
| + _CacheBasedResultProvider(InternalAnalysisContext context, this.cache)
|
| + : super(context, new SummaryDataStore(<String>[])) {
|
| + AnalysisContext sdkContext = context.sourceFactory.dartSdk.context;
|
| + createResynthesizer(sdkContext, sdkContext.typeProvider);
|
| + }
|
| +
|
| + @override
|
| + bool compute(CacheEntry entry, ResultDescriptor result) {
|
| + AnalysisTarget target = entry.target;
|
| + // TODO(scheglov) remove the check after finishing optimizations.
|
| + if (target.source != null &&
|
| + target.source.fullName
|
| + .endsWith('analysis_server/lib/src/computer/computer_hover.dart')) {
|
| + return false;
|
| + }
|
| + // Source based results.
|
| + if (target is Source) {
|
| + if (result == DART_ERRORS) {
|
| + // TODO(scheglov) provide actual errors
|
| + entry.setValue(result, <AnalysisError>[], TargetedResult.EMPTY_LIST);
|
| + return true;
|
| + }
|
| + }
|
| + return super.compute(entry, result);
|
| + }
|
| +
|
| + @override
|
| + bool hasResultsForSource(Source source) {
|
| + // Check cache states.
|
| + if (sourcesWithSummaries.contains(source)) {
|
| + return true;
|
| + }
|
| + if (sourcesWithoutSummaries.contains(source)) {
|
| + return false;
|
| + }
|
| + // Try to load bundles.
|
| + List<LibraryBundleWithId> bundles = cache.getLibraryClosureBundles(source);
|
| + if (bundles == null) {
|
| + sourcesWithoutSummaries.add(source);
|
| + return false;
|
| + }
|
| + // Fill the resynthesizer.
|
| + sourcesWithSummaries.add(source);
|
| + for (LibraryBundleWithId bundleWithId in bundles) {
|
| + if (addedLibraryBundleIds.add(bundleWithId.id)) {
|
| + addBundle(null, bundleWithId.bundle);
|
| + }
|
| + }
|
| + return true;
|
| + }
|
| +}
|
| +
|
| +class _IncrementalAnalysisData implements IncrementalAnalysisData {
|
| + final CommandLineOptions commandLineOptions;
|
| + final IncrementalCache cache;
|
| + final AnalysisContext context;
|
| +
|
| + final Set<Source> librarySources = new Set<Source>();
|
| +
|
| + _IncrementalAnalysisData(this.commandLineOptions, this.cache, this.context);
|
| +
|
| + @override
|
| + void finish() {
|
| + // Finish computing new libraries and put them into the cache.
|
| + for (Source librarySource in librarySources) {
|
| + if (!commandLineOptions.machineFormat) {
|
| + print('Compute library element for $librarySource');
|
| + }
|
| + LibraryElement libraryElement =
|
| + context.computeResult(librarySource, LIBRARY_ELEMENT);
|
| + // TODO(scheglov) compute and store errors
|
| +// context.computeResult(librarySource, DART_ERRORS);
|
| + try {
|
| + cache.putLibrary(libraryElement);
|
| + } catch (e) {}
|
| + }
|
| + }
|
| +}
|
|
|