| // Copyright (c) 2021, 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. |
| |
| import 'dart:convert'; |
| import 'dart:typed_data'; |
| |
| import 'package:analyzer/file_system/file_system.dart'; |
| import 'package:convert/convert.dart'; |
| import 'package:crypto/crypto.dart'; |
| |
| /// Information about the content of a file. |
| class FileContent { |
| final String path; |
| final bool exists; |
| final String content; |
| final String contentHash; |
| |
| FileContent._(this.path, this.exists, this.content, this.contentHash); |
| } |
| |
| /// The cache of information about content of files. |
| abstract class FileContentCache { |
| final ResourceProvider _resourceProvider; |
| |
| factory FileContentCache(ResourceProvider resourceProvider) { |
| return _FileContentCacheImpl(resourceProvider); |
| } |
| |
| factory FileContentCache.ephemeral(ResourceProvider resourceProvider) { |
| return _FileContentCacheEphemeral(resourceProvider); |
| } |
| |
| FileContentCache._(this._resourceProvider); |
| |
| /// Return the content of the file with the given [path]. |
| FileContent get(String path); |
| |
| /// Discard the cache value for the file with the given [path]. |
| void invalidate(String path) {} |
| |
| void invalidateAll() {} |
| |
| FileContent _read(String path) { |
| Uint8List contentBytes; |
| String content; |
| bool exists; |
| try { |
| contentBytes = _resourceProvider.getFile(path).readAsBytesSync(); |
| content = utf8.decode(contentBytes); |
| exists = true; |
| } catch (_) { |
| contentBytes = Uint8List(0); |
| content = ''; |
| exists = false; |
| } |
| |
| List<int> contentHashBytes = md5.convert(contentBytes).bytes; |
| String contentHash = hex.encode(contentHashBytes); |
| |
| return FileContent._(path, exists, content, contentHash); |
| } |
| } |
| |
| /// [FileContentCache] that caches never. |
| class _FileContentCacheEphemeral extends FileContentCache { |
| _FileContentCacheEphemeral(ResourceProvider resourceProvider) |
| : super._(resourceProvider); |
| |
| @override |
| FileContent get(String path) { |
| return _read(path); |
| } |
| } |
| |
| /// [FileContentCache] that caches forever. |
| class _FileContentCacheImpl extends FileContentCache { |
| final Map<String, FileContent> _pathToFile = {}; |
| |
| _FileContentCacheImpl(ResourceProvider resourceProvider) |
| : super._(resourceProvider); |
| |
| @override |
| FileContent get(String path) { |
| var file = _pathToFile[path]; |
| |
| if (file != null) { |
| return file; |
| } |
| |
| file = _read(path); |
| _pathToFile[path] = file; |
| return file; |
| } |
| |
| @override |
| void invalidate(String path) { |
| _pathToFile.remove(path); |
| } |
| |
| @override |
| void invalidateAll() { |
| _pathToFile.clear(); |
| } |
| } |