blob: 4e1e989030704da9c8dc4b0599d1e87556718146 [file] [log] [blame]
// 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) {
List<int> 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();
}
}