Skip to content

Commit 1a6c8b1

Browse files
committed
Hacking.
1 parent 7a964f3 commit 1a6c8b1

File tree

9 files changed

+110
-57
lines changed

9 files changed

+110
-57
lines changed

build/lib/src/state/filesystem.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ class IoFilesystem implements Filesystem {
159159
class InMemoryFilesystem implements Filesystem {
160160
final Map<String, Uint8List> _files = {};
161161

162+
Iterable<String> get paths => _files.keys;
163+
162164
@override
163165
Future<bool> exists(String path) async => _files.containsKey(path);
164166

build/lib/src/state/filesystem_cache.dart

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,10 @@ abstract interface class FilesystemCache {
3434
/// Reads [id] as a `String`.
3535
///
3636
/// Returns a cached result if available, or caches and returns `ifAbsent()`.
37-
///
38-
/// The encoding used is always `utf8`. For other encodings, use
39-
/// [readAsBytes].
4037
Future<String> readAsString(
4138
AssetId id, {
42-
required Future<String> Function() ifAbsent,
39+
Encoding encoding = utf8,
40+
required Future<Uint8List> Function() ifAbsent,
4341
});
4442
}
4543

@@ -65,8 +63,9 @@ class PassthroughFilesystemCache implements FilesystemCache {
6563
@override
6664
Future<String> readAsString(
6765
AssetId id, {
68-
required Future<String> Function() ifAbsent,
69-
}) => ifAbsent();
66+
Encoding encoding = utf8,
67+
required Future<Uint8List> Function() ifAbsent,
68+
}) async => encoding.decode(await ifAbsent());
7069
}
7170

7271
/// [FilesystemCache] that stores data in memory.
@@ -139,14 +138,20 @@ class InMemoryFilesystemCache implements FilesystemCache {
139138
@override
140139
Future<String> readAsString(
141140
AssetId id, {
142-
required Future<String> Function() ifAbsent,
141+
Encoding encoding = utf8,
142+
required Future<Uint8List> Function() ifAbsent,
143143
}) async {
144+
if (encoding != utf8) {
145+
final bytes = await readAsBytes(id, ifAbsent: ifAbsent);
146+
return encoding.decode(bytes);
147+
}
148+
144149
var cached = _stringContentCache[id];
145150
if (cached != null) return cached;
146151

147152
return _pendingStringContentCache.putIfAbsent(id, () async {
148-
final result = await ifAbsent();
149-
_stringContentCache[id] = result;
153+
final bytes = await ifAbsent();
154+
final result = _stringContentCache[id] = utf8.decode(bytes);
150155
unawaited(_pendingStringContentCache.remove(id));
151156
return result;
152157
});

build/test/state/filesystem_cache_test.dart

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,20 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'dart:typed_data';
5+
import 'dart:convert';
66

77
import 'package:build/build.dart';
88
import 'package:build/src/state/filesystem_cache.dart';
99
import 'package:test/test.dart';
1010

1111
void main() {
1212
final txt1 = AssetId('a', 'foo.txt');
13-
final txt2 = AssetId('a', 'missing.txt');
13+
final txt1String = 'txt1';
14+
final txt1Bytes = utf8.encode(txt1String);
1415

15-
final txt1Bytes = Uint8List.fromList([1, 2, 3]);
16-
final txt2Bytes = Uint8List.fromList([4, 5, 6]);
16+
final txt2 = AssetId('a', 'missing.txt');
17+
final txt2String = 'txt2';
18+
final txt2Bytes = utf8.encode(txt2String);
1719

1820
late FilesystemCache cache;
1921

@@ -79,23 +81,32 @@ void main() {
7981

8082
group('readAsString', () {
8183
test('reads from isAbsent', () async {
82-
expect(await cache.readAsString(txt1, ifAbsent: () async => '1'), '1');
84+
expect(
85+
await cache.readAsString(txt1, ifAbsent: () async => txt1Bytes),
86+
txt1String,
87+
);
8388
});
8489

8590
test('does not re-read from isAbsent', () async {
86-
expect(await cache.readAsString(txt1, ifAbsent: () async => '1'), '1');
8791
expect(
88-
await cache.readAsString(txt1, ifAbsent: () async => '2'),
89-
'1' /* cached value */,
92+
await cache.readAsString(txt1, ifAbsent: () async => txt1Bytes),
93+
txt1String,
94+
);
95+
expect(
96+
await cache.readAsString(txt1, ifAbsent: () async => txt2Bytes),
97+
txt1String /* cached value */,
9098
);
9199
});
92100

93101
test('can be invalidated with invalidate', () async {
94-
expect(await cache.readAsString(txt1, ifAbsent: () async => '1'), '1');
102+
expect(
103+
await cache.readAsString(txt1, ifAbsent: () async => txt1Bytes),
104+
txt1String,
105+
);
95106
await cache.invalidate([txt1]);
96107
expect(
97-
await cache.readAsString(txt1, ifAbsent: () async => '2'),
98-
'2' /* updated value */,
108+
await cache.readAsString(txt1, ifAbsent: () async => txt2Bytes),
109+
txt2String /* updated value */,
99110
);
100111
});
101112
});

build_modules/test/util.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ Future<void> testBuilderAndCollectAssets(
2727
onLog: onLog,
2828
reportUnusedAssetsForInput: reportUnusedAssetsForInput,
2929
);
30-
result.readerWriter.assets.forEach((id, value) {
30+
for (var id in result.readerWriter.testing.assets) {
31+
final value = result.readerWriter.testing.readBytes(id);
3132
assets['${id.package}|${id.path}'] = value;
32-
});
33+
}
3334
}

build_runner_core/lib/src/asset/file_based.dart

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,27 +46,44 @@ class FileBasedAssetReader extends AssetReader implements AssetReaderState {
4646

4747
@override
4848
Future<bool> canRead(AssetId id) {
49-
final path = assetPathProvider.pathFor(id);
50-
return filesystem.exists(path);
49+
return cache.exists(
50+
id,
51+
ifAbsent: () async {
52+
final path = assetPathProvider.pathFor(id);
53+
return filesystem.exists(path);
54+
},
55+
);
5156
}
5257

5358
@override
5459
Future<List<int>> readAsBytes(AssetId id) async {
55-
final path = assetPathProvider.pathFor(id);
56-
if (!await filesystem.exists(path)) {
57-
// TODO(davidmorgan): report the path as well?
58-
throw AssetNotFoundException(id);
59-
}
60-
return filesystem.readAsBytes(path);
60+
var x;
61+
return cache.readAsBytes(
62+
id,
63+
ifAbsent: () async {
64+
final path = assetPathProvider.pathFor(id);
65+
if (!await filesystem.exists(path)) {
66+
// TODO(davidmorgan): report the path as well?
67+
throw AssetNotFoundException(id);
68+
}
69+
return filesystem.readAsBytes(path);
70+
},
71+
);
6172
}
6273

6374
@override
6475
Future<String> readAsString(AssetId id, {Encoding encoding = utf8}) async {
65-
final path = assetPathProvider.pathFor(id);
66-
if (!await filesystem.exists(path)) {
67-
throw AssetNotFoundException(id);
68-
}
69-
return filesystem.readAsString(path, encoding: encoding);
76+
return cache.readAsString(
77+
id,
78+
encoding: encoding,
79+
ifAbsent: () async {
80+
final path = assetPathProvider.pathFor(id);
81+
if (!await filesystem.exists(path)) {
82+
throw AssetNotFoundException(id);
83+
}
84+
return filesystem.readAsBytes(path);
85+
},
86+
);
7087
}
7188

7289
// This is only for generators, so only `BuildStep` needs to implement it.

build_test/lib/src/in_memory_reader_writer.dart

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ abstract interface class TestReaderWriter implements AssetReader, AssetWriter {
2121
}
2222

2323
abstract interface class ReaderWriterTesting {
24+
Iterable<AssetId> get assets;
25+
2426
Iterable<AssetId> get assetsRead;
2527

2628
bool exists(AssetId id);
@@ -101,25 +103,40 @@ class InMemoryAssetReaderWriterImpl extends AssetReader
101103
@override
102104
Future<bool> canRead(AssetId id) async {
103105
inputTracker.assetsRead.add(id);
104-
// TODO(davidmorgan): caching.
105-
final path = assetPathProvider.pathFor(id);
106-
return filesystem.exists(path);
106+
return cache.exists(
107+
id,
108+
ifAbsent: () async {
109+
final path = assetPathProvider.pathFor(id);
110+
return filesystem.exists(path);
111+
},
112+
);
107113
}
108114

109115
@override
110116
Future<List<int>> readAsBytes(AssetId id) async {
111117
if (!await canRead(id)) throw AssetNotFoundException(id);
112118
inputTracker.assetsRead.add(id);
113-
final path = assetPathProvider.pathFor(id);
114-
return filesystem.readAsBytes(path);
119+
return cache.readAsBytes(
120+
id,
121+
ifAbsent: () async {
122+
final path = assetPathProvider.pathFor(id);
123+
return filesystem.readAsBytes(path);
124+
},
125+
);
115126
}
116127

117128
@override
118129
Future<String> readAsString(AssetId id, {Encoding encoding = utf8}) async {
119130
if (!await canRead(id)) throw AssetNotFoundException(id);
120131
inputTracker.assetsRead.add(id);
121-
final path = assetPathProvider.pathFor(id);
122-
return filesystem.readAsString(path, encoding: encoding);
132+
return cache.readAsString(
133+
id,
134+
encoding: encoding,
135+
ifAbsent: () async {
136+
final path = assetPathProvider.pathFor(id);
137+
return filesystem.readAsBytes(path);
138+
},
139+
);
123140
}
124141

125142
// This is only for generators, so only `BuildStep` needs to implement it.
@@ -135,7 +152,9 @@ class InMemoryAssetReaderWriterImpl extends AssetReader
135152
);
136153
}
137154
return Stream.fromIterable(
138-
assets.keys.where((id) => id.package == package && glob.matches(id.path)),
155+
testing.assets.where(
156+
(id) => id.package == package && glob.matches(id.path),
157+
),
139158
);
140159
}
141160

@@ -167,7 +186,10 @@ class _ReaderWriterTestingImpl implements ReaderWriterTesting {
167186

168187
_ReaderWriterTestingImpl(this._readerWriter);
169188

170-
// `TestReaderWriter` methods.
189+
@override
190+
Iterable<AssetId> get assets =>
191+
_readerWriter._filesystem.paths.map(AssetId.parse);
192+
171193
@override
172194
Iterable<AssetId> get assetsRead => _readerWriter.inputTracker.assetsRead;
173195

build_test/lib/src/test_builder.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ Future<TestBuilderResult> testBuilder(
174174
? AnalyzerResolvers.sharedInstance
175175
: AnalyzerResolvers.custom(packageConfig: packageConfig);
176176

177-
final startingFiles = readerWriter.assets.keys.toList();
177+
final startingFiles = readerWriter.testing.assets.toList();
178178
for (var input in inputIds) {
179179
// Create a reader that can read initial files plus anything written by the
180180
// builder during the step; outputs by other builders during the step are

build_test/lib/src/written_asset_reader.dart

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class WrittenAssetReader extends AssetReader implements AssetReaderState {
7171
Stream<AssetId> findAssets(Glob glob) => throw UnimplementedError();
7272

7373
Stream<AssetId> _findAssets(Glob glob, String? package) async* {
74-
var available = source.assets.keys.toSet();
74+
var available = source.testing.assets.toSet();
7575
if (filterSpy != null) {
7676
available = available.intersection(
7777
filterSpy!.assetsWritten.toSet().union(_additionallyAllowed),
@@ -87,15 +87,9 @@ class WrittenAssetReader extends AssetReader implements AssetReaderState {
8787
}
8888

8989
@override
90-
Future<List<int>> readAsBytes(AssetId id) {
91-
if (!source.assets.containsKey(id)) {
92-
throw AssetNotFoundException(id);
93-
}
94-
return Future.value(source.assets[id]!);
95-
}
90+
Future<List<int>> readAsBytes(AssetId id) => source.readAsBytes(id);
9691

9792
@override
98-
Future<String> readAsString(AssetId id, {Encoding encoding = utf8}) async {
99-
return encoding.decode(await readAsBytes(id));
100-
}
93+
Future<String> readAsString(AssetId id, {Encoding encoding = utf8}) =>
94+
source.readAsString(id, encoding: encoding);
10195
}

build_web_compilers/test/util.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ Future<void> testBuilderAndCollectAssets(
1818
assets,
1919
onLog: (log) => printOnFailure('${log.level}: ${log.message}'),
2020
);
21-
result.readerWriter.assets.forEach((id, value) {
21+
for (var id in result.readerWriter.testing.assets) {
22+
final value = result.readerWriter.testing.readBytes(id);
2223
assets['${id.package}|${id.path}'] = value;
23-
});
24+
}
2425
}

0 commit comments

Comments
 (0)