Index: pkg/analysis_server/lib/src/source/caching_pub_package_map_provider.dart |
diff --git a/pkg/analysis_server/lib/src/source/caching_pub_package_map_provider.dart b/pkg/analysis_server/lib/src/source/caching_pub_package_map_provider.dart |
deleted file mode 100644 |
index 964e7dec57871bac973570ad62e4869d9b13ec1f..0000000000000000000000000000000000000000 |
--- a/pkg/analysis_server/lib/src/source/caching_pub_package_map_provider.dart |
+++ /dev/null |
@@ -1,260 +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 source.caching_pub_package_map_provider; |
- |
-import 'dart:convert'; |
-import 'dart:core'; |
-import 'dart:io' as io; |
- |
-import 'package:analyzer/file_system/file_system.dart'; |
-import 'package:analyzer/source/package_map_provider.dart'; |
-import 'package:analyzer/source/pub_package_map_provider.dart'; |
-import 'package:analyzer/src/dart/sdk/sdk.dart'; |
-import 'package:analyzer/src/generated/engine.dart'; |
-import 'package:analyzer/src/generated/source.dart'; |
- |
-/** |
- * The function used to write the cache file. |
- * Returns the modification stamp for the newly written file. |
- */ |
-typedef int WriteFile(File file, String content); |
- |
-/** |
- * [PubPackageMapProvider] extension which caches pub list results. |
- * These results are cached in memory and in a single place on disk that is |
- * shared cross session and between different simultaneous sessions. |
- * |
- * TODO(paulberry): before this class is used again, it should be ported over |
- * to extend OptimizingPubPackageMapProvider instead of PubPackageMapProvider. |
- */ |
-class CachingPubPackageMapProvider extends PubPackageMapProvider { |
- static const cacheKey = 'pub_list_cache'; |
- static const cacheVersion = 1; |
- static const cacheVersionKey = 'pub_list_cache_version'; |
- static const pubListResultKey = 'pub_list_result'; |
- static const modificationStampsKey = 'modification_stamps'; |
- |
- /** |
- * A cache of folder path to pub list information as shown below |
- * or `null` if the cache has not yet been initialized. |
- * |
- * { |
- * "path/to/folder": { |
- * "pub_list_result": { |
- * "packages": { |
- * "foo": "path/to/foo", |
- * "bar": ["path/to/bar1", "path/to/bar2"], |
- * "myapp": "path/to/myapp", // self link is included |
- * }, |
- * "input_files": [ |
- * "path/to/myapp/pubspec.lock" |
- * ] |
- * }, |
- * "modification_stamps": { |
- * "path/to/myapp/pubspec.lock": 1424305309 |
- * } |
- * } |
- * "path/to/another/folder": { |
- * ... |
- * } |
- * ... |
- * } |
- */ |
- Map<String, Map> _cache; |
- |
- /** |
- * The modification time of the cache file |
- * or `null` if it has not yet been read. |
- */ |
- int _cacheModificationTime; |
- |
- /** |
- * The function used to write the cache file. |
- */ |
- WriteFile _writeFile; |
- |
- /** |
- * Construct a new instance. |
- * [RunPubList] and [WriteFile] implementations may be injected for testing |
- */ |
- CachingPubPackageMapProvider( |
- ResourceProvider resourceProvider, FolderBasedDartSdk sdk, |
- [RunPubList runPubList, this._writeFile]) |
- : super(resourceProvider, sdk, runPubList) { |
- if (_writeFile == null) { |
- _writeFile = _writeFileDefault; |
- } |
- } |
- |
- File get cacheFile => _cacheDir.getChild('cache'); |
- Folder get _cacheDir => resourceProvider.getStateLocation('.pub-list'); |
- File get _touchFile => _cacheDir.getChild('touch'); |
- |
- @override |
- PackageMapInfo computePackageMap(Folder folder) { |
- // |
- // Return error if folder does not exist, but don't remove previously |
- // cached result because folder may be only temporarily inaccessible |
- // |
- if (!folder.exists) { |
- return computePackageMapError(folder); |
- } |
- // Ensure cache is up to date |
- _readCache(); |
- // Check for cached entry |
- Map entry = _cache[folder.path]; |
- if (entry != null) { |
- Map<String, int> modificationStamps = |
- entry[modificationStampsKey] as Map<String, int>; |
- if (modificationStamps != null) { |
- // |
- // Check to see if any dependencies have changed |
- // before returning cached result |
- // |
- if (!_haveDependenciesChanged(modificationStamps)) { |
- return parsePackageMap(entry[pubListResultKey], folder); |
- } |
- } |
- } |
- int runCount = 0; |
- PackageMapInfo info; |
- while (true) { |
- // Capture the current time so that we can tell if an input file |
- // has changed while running pub list. This is done |
- // by writing to a file rather than getting millisecondsSinceEpoch |
- // because file modification time has different granularity |
- // on diferent systems. |
- int startStamp; |
- try { |
- startStamp = _writeFile(_touchFile, 'touch'); |
- } catch (exception, stackTrace) { |
- AnalysisEngine.instance.logger.logInformation( |
- 'Exception writing $_touchFile\n$exception\n$stackTrace'); |
- startStamp = new DateTime.now().millisecondsSinceEpoch; |
- } |
- // computePackageMap calls parsePackageMap which caches the result |
- info = super.computePackageMap(folder); |
- ++runCount; |
- if (!_haveDependenciesChangedSince(info, startStamp)) { |
- // If no dependencies have changed while running pub then finished |
- break; |
- } |
- if (runCount == 4) { |
- // Don't run forever |
- AnalysisEngine.instance.logger |
- .logInformation('pub list called $runCount times: $folder'); |
- break; |
- } |
- } |
- _writeCache(); |
- return info; |
- } |
- |
- @override |
- PackageMapInfo parsePackageMap(Map obj, Folder folder) { |
- PackageMapInfo info = super.parsePackageMap(obj, folder); |
- Map<String, int> modificationStamps = new Map<String, int>(); |
- for (String path in info.dependencies) { |
- Resource res = resourceProvider.getResource(path); |
- if (res is File && res.exists) { |
- modificationStamps[path] = res.createSource().modificationStamp; |
- } |
- } |
- // Assumes entry has been initialized by computePackageMap |
- _cache[folder.path] = <String, Map>{ |
- pubListResultKey: obj, |
- modificationStampsKey: modificationStamps |
- }; |
- return info; |
- } |
- |
- /** |
- * Determine if any of the dependencies have changed. |
- */ |
- bool _haveDependenciesChanged(Map<String, int> modificationStamps) { |
- for (String path in modificationStamps.keys) { |
- Resource res = resourceProvider.getResource(path); |
- if (res is File) { |
- if (!res.exists || |
- res.createSource().modificationStamp != modificationStamps[path]) { |
- return true; |
- } |
- } else { |
- return true; |
- } |
- } |
- return false; |
- } |
- |
- /** |
- * Determine if any of the dependencies have changed since the given time. |
- */ |
- bool _haveDependenciesChangedSince(PackageMapInfo info, int startStamp) { |
- for (String path in info.dependencies) { |
- Resource res = resourceProvider.getResource(path); |
- if (res is File) { |
- int modStamp = res.createSource().modificationStamp; |
- if (modStamp != null && modStamp >= startStamp) { |
- return true; |
- } |
- } |
- } |
- return false; |
- } |
- |
- /** |
- * Read the cache from disk if it has not been read before. |
- */ |
- void _readCache() { |
- // TODO(danrubel) This implementation assumes that |
- // two separate processes are not accessing the cache file at the same time |
- Source source = cacheFile.createSource(); |
- if (source.exists() && |
- (_cache == null || |
- _cacheModificationTime != source.modificationStamp)) { |
- try { |
- TimestampedData<String> data = source.contents; |
- Map map = JSON.decode(data.data); |
- if (map[cacheVersionKey] == cacheVersion) { |
- _cache = map[cacheKey] as Map<String, Map>; |
- _cacheModificationTime = data.modificationTime; |
- } |
- } catch (exception, stackTrace) { |
- AnalysisEngine.instance.logger.logInformation( |
- 'Exception reading $cacheFile\n$exception\n$stackTrace'); |
- } |
- } |
- if (_cache == null) { |
- _cache = new Map<String, Map>(); |
- } |
- } |
- |
- /** |
- * Write the cache to disk. |
- */ |
- void _writeCache() { |
- try { |
- _cacheModificationTime = _writeFile(cacheFile, |
- JSON.encode({cacheVersionKey: cacheVersion, cacheKey: _cache})); |
- } catch (exception, stackTrace) { |
- AnalysisEngine.instance.logger.logInformation( |
- 'Exception writing $cacheFile\n$exception\n$stackTrace'); |
- } |
- } |
- |
- /** |
- * Update the given file with the specified content. |
- */ |
- int _writeFileDefault(File cacheFile, String content) { |
- // TODO(danrubel) This implementation assumes that |
- // two separate processes are not accessing the cache file at the same time |
- io.File file = new io.File(cacheFile.path); |
- if (!file.parent.existsSync()) { |
- file.parent.createSync(recursive: true); |
- } |
- file.writeAsStringSync(content, flush: true); |
- return file.lastModifiedSync().millisecondsSinceEpoch; |
- } |
-} |