Skip to content

Commit bf2326e

Browse files
committed
Refactor BuildCacheReader to BuildCacheAssetPathProvider.
1 parent d71fe7d commit bf2326e

18 files changed

+129
-171
lines changed

build/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
## 2.4.3-wip
22

3+
- `AssetNotFoundException` now also reports the missing `path`.
34
- Bump the min sdk to 3.7.0.
45
- Use `build_test` 3.0.0.
56
- Add `package:build/src/internal.dart` for use by `build_resolvers`,
@@ -9,6 +10,7 @@
910
- Add internal `Filesystem` that backs `AssetReader` and `AssetWriter`
1011
implementations.
1112
- Refactor `CachingAssetReader` to `FilesystemCache`.
13+
- Refactor `BuildCacheReader` to `BuildCacheAssetPathProvider`.
1214

1315
## 2.4.2
1416

build/lib/src/asset/exceptions.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ import 'id.dart';
55

66
class AssetNotFoundException implements Exception {
77
final AssetId assetId;
8+
final String? path;
89

9-
AssetNotFoundException(this.assetId);
10+
AssetNotFoundException(this.assetId, {this.path});
1011

1112
@override
12-
String toString() => 'AssetNotFoundException: $assetId';
13+
String toString() {
14+
if (path == null) return 'AssetNotFoundException: $assetId';
15+
return 'AssetNotFoundException: $assetId ($path)';
16+
}
1317
}
1418

1519
class PackageNotFoundException implements Exception {

build/lib/src/builder/build_step_impl.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,13 @@ class BuildStepImpl implements BuildStep, AssetReaderState {
8585
_reportUnusedAssets = reportUnusedAssets;
8686

8787
@override
88-
BuildStepImpl copyWith({FilesystemCache? cache}) => BuildStepImpl(
88+
BuildStepImpl copyWith({
89+
AssetPathProvider? assetPathProvider,
90+
FilesystemCache? cache,
91+
}) => BuildStepImpl(
8992
inputId,
9093
allowedOutputs,
91-
_reader.copyWith(cache: cache),
94+
_reader.copyWith(assetPathProvider: assetPathProvider, cache: cache),
9295
_writer,
9396
_resolvers,
9497
_resourceManager,
@@ -107,7 +110,7 @@ class BuildStepImpl implements BuildStep, AssetReaderState {
107110
AssetFinder get assetFinder => _reader.assetFinder;
108111

109112
@override
110-
AssetPathProvider? get assetPathProvider => _reader.assetPathProvider;
113+
AssetPathProvider get assetPathProvider => _reader.assetPathProvider;
111114

112115
@override
113116
InputTracker? get inputTracker => _reader.inputTracker;

build/lib/src/state/asset_path_provider.dart

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,7 @@
44

55
import '../asset/id.dart';
66

7-
/// Converts [AssetId] to paths.
7+
/// Converts [AssetId]s to paths.
88
abstract interface class AssetPathProvider {
99
String pathFor(AssetId id);
1010
}
11-
12-
/// Applies a function to an existing [AssetPathProvider].
13-
class OverlayAssetPathProvider implements AssetPathProvider {
14-
AssetPathProvider delegate;
15-
AssetId Function(AssetId) overlay;
16-
17-
OverlayAssetPathProvider({required this.delegate, required this.overlay});
18-
19-
@override
20-
String pathFor(AssetId id) => delegate.pathFor(overlay(id));
21-
}

build/lib/src/state/reader_state.dart

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,15 @@ import 'input_tracker.dart';
1212
/// Provides access to the state backing an [AssetReader].
1313
extension AssetReaderStateExtension on AssetReader {
1414
/// Returns a new instance with optionally updated [cache].
15-
AssetReader copyWith({FilesystemCache? cache}) {
15+
AssetReader copyWith({
16+
AssetPathProvider? assetPathProvider,
17+
FilesystemCache? cache,
18+
}) {
1619
_requireIsAssetReaderState();
17-
return (this as AssetReaderState).copyWith(cache: cache);
20+
return (this as AssetReaderState).copyWith(
21+
assetPathProvider: assetPathProvider,
22+
cache: cache,
23+
);
1824
}
1925

2026
Filesystem get filesystem {
@@ -35,6 +41,11 @@ extension AssetReaderStateExtension on AssetReader {
3541
InputTracker? get inputTracker =>
3642
this is AssetReaderState ? (this as AssetReaderState).inputTracker : null;
3743

44+
AssetPathProvider get assetPathProvider {
45+
_requireIsAssetReaderState();
46+
return (this as AssetReaderState).assetPathProvider;
47+
}
48+
3849
/// Gets [inputTracker] or throws a descriptive error if it is `null`.
3950
InputTracker get requireInputTracker {
4051
final result = inputTracker;
@@ -47,11 +58,6 @@ extension AssetReaderStateExtension on AssetReader {
4758
return result;
4859
}
4960

50-
AssetPathProvider? get assetPathProvider =>
51-
this is AssetReaderState
52-
? (this as AssetReaderState).assetPathProvider
53-
: null;
54-
5561
/// Throws if `this` is not an [AssetReaderState].
5662
void _requireIsAssetReaderState() {
5763
if (this is! AssetReaderState) {
@@ -64,8 +70,11 @@ extension AssetReaderStateExtension on AssetReader {
6470

6571
/// The state backing an [AssetReader].
6672
abstract interface class AssetReaderState {
67-
/// Returns a new instance with optionally updated [cache].
68-
AssetReader copyWith({FilesystemCache? cache});
73+
/// Returns a new instance with optionally updated [assetPathProvider] and/or [cache].
74+
AssetReader copyWith({
75+
AssetPathProvider? assetPathProvider,
76+
FilesystemCache? cache,
77+
});
6978

7079
/// The [Filesystem] that this reader reads from.
7180
///
@@ -86,7 +95,6 @@ abstract interface class AssetReaderState {
8695
/// not have one.
8796
InputTracker? get inputTracker;
8897

89-
/// The [AssetPathProvider] associated with this reader, or `null` if it does
90-
/// not have one.
91-
AssetPathProvider? get assetPathProvider;
98+
/// The [AssetPathProvider] associated with this reader.
99+
AssetPathProvider get assetPathProvider;
92100
}

build_runner_core/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- Add internal `Filesystem` that backs `AssetReader` and `AssetWriter`
1111
implementations.
1212
- Refactor `CachingAssetReader` to `FilesystemCache`.
13+
- Refactor `BuildCacheReader` to `BuildCacheAssetPathProvider`.
1314

1415
## 8.0.0
1516

build_runner_core/lib/build_runner_core.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
export 'package:build/build.dart' show PostProcessBuildStep, PostProcessBuilder;
66

7-
export 'src/asset/batch.dart' show wrapInBatch;
87
export 'src/asset/file_based.dart';
98
export 'src/asset/finalized_reader.dart';
109
export 'src/asset/writer.dart';

build_runner_core/lib/src/asset/batch.dart

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import 'writer.dart';
2525
///
2626
/// The default [IOEnvironment] uses readers and writes that are batch-aware
2727
/// outside of low-memory mode.
28+
///
29+
/// TODO(davidmorgan): this is not currently used, refactor into `Filesystem`.
2830
final class _FileSystemWriteBatch {
2931
final Map<AssetId, _PendingFileState> _pendingWrites = {};
3032

@@ -54,7 +56,7 @@ final class _FileSystemWriteBatch {
5456
///
5557
/// The returned reader will see pending writes by the returned writer before
5658
/// they are flushed to the file system.
57-
(AssetReader, RunnerAssetWriter) wrapInBatch({
59+
(BatchReader, BatchWriter) wrapInBatch({
5860
required AssetReader reader,
5961
required RunnerAssetWriter writer,
6062
}) {
@@ -72,35 +74,18 @@ final class _PendingFileState {
7274
}
7375

7476
@internal
75-
final class BatchReader extends AssetReader implements AssetReaderState {
76-
@override
77+
final class BatchReader {
7778
late final AssetFinder assetFinder = FunctionAssetFinder(_findAssets);
79+
7880
final AssetReader _inner;
7981
final _FileSystemWriteBatch _batch;
8082

8183
BatchReader(this._inner, this._batch);
8284

83-
@override
84-
BatchReader copyWith({FilesystemCache? cache}) =>
85-
BatchReader(_inner.copyWith(cache: cache), _batch);
86-
87-
@override
88-
Filesystem get filesystem => _inner.filesystem;
89-
90-
@override
91-
FilesystemCache get cache => _inner.cache;
92-
93-
@override
94-
AssetPathProvider? get assetPathProvider => _inner.assetPathProvider;
95-
96-
@override
97-
InputTracker? get inputTracker => _inner.inputTracker;
98-
9985
_PendingFileState? _stateFor(AssetId id) {
10086
return _batch._pendingWrites[id];
10187
}
10288

103-
@override
10489
Future<bool> canRead(AssetId id) async {
10590
if (_stateFor(id) case final state?) {
10691
return !state.isDeleted;
@@ -110,7 +95,6 @@ final class BatchReader extends AssetReader implements AssetReaderState {
11095
}
11196

11297
// This is only for generators, so only `BuildStep` needs to implement it.
113-
@override
11498
Stream<AssetId> findAssets(Glob glob) => throw UnimplementedError();
11599

116100
Stream<AssetId> _findAssets(Glob glob, String? package) {
@@ -119,7 +103,6 @@ final class BatchReader extends AssetReader implements AssetReaderState {
119103
.where((asset) => _stateFor(asset)?.isDeleted != true);
120104
}
121105

122-
@override
123106
Future<List<int>> readAsBytes(AssetId id) async {
124107
if (_stateFor(id) case final state?) {
125108
if (state.isDeleted) {
@@ -132,7 +115,6 @@ final class BatchReader extends AssetReader implements AssetReaderState {
132115
}
133116
}
134117

135-
@override
136118
Future<String> readAsString(AssetId id, {Encoding encoding = utf8}) async {
137119
if (_stateFor(id) case final state?) {
138120
if (state.isDeleted) {

build_runner_core/lib/src/asset/build_cache.dart

Lines changed: 18 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -4,84 +4,37 @@ import 'dart:convert';
44
import 'package:build/build.dart';
55
// ignore: implementation_imports
66
import 'package:build/src/internal.dart';
7-
import 'package:crypto/crypto.dart';
8-
import 'package:glob/glob.dart';
97

108
import '../asset_graph/graph.dart';
119
import '../asset_graph/node.dart';
1210
import '../util/constants.dart';
1311
import 'writer.dart';
1412

15-
/// Wraps an [AssetReader] and translates reads for generated files into reads
16-
/// from the build cache directory
17-
class BuildCacheReader implements AssetReader, AssetReaderState {
18-
@override
19-
final AssetPathProvider? assetPathProvider;
20-
21-
final AssetReader _delegate;
13+
/// Wraps an [AssetPathProvider] to place hidden generated files in the build
14+
/// cache directory.
15+
///
16+
/// Assets that are in the provided [AssetGraph], have node type
17+
/// [GeneratedAssetNode] and have `isHidden == true` are mapped to
18+
/// [generatedOutputDirectory].
19+
class BuildCacheAssetPathProvider implements AssetPathProvider {
20+
final AssetPathProvider _delegate;
2221
final AssetGraph _assetGraph;
2322
final String _rootPackage;
2423

25-
BuildCacheReader(
26-
AssetReader delegate,
27-
AssetGraph assetGraph,
28-
String rootPackage,
29-
) : _delegate = delegate,
30-
_assetGraph = assetGraph,
31-
_rootPackage = rootPackage,
32-
assetPathProvider =
33-
delegate.assetPathProvider == null
34-
? null
35-
: OverlayAssetPathProvider(
36-
delegate: delegate.assetPathProvider!,
37-
overlay: (id) => _cacheLocation(id, assetGraph, rootPackage),
38-
);
39-
40-
@override
41-
BuildCacheReader copyWith({FilesystemCache? cache}) => BuildCacheReader(
42-
_delegate.copyWith(cache: cache),
43-
_assetGraph,
44-
_rootPackage,
45-
);
46-
47-
@override
48-
Filesystem get filesystem => _delegate.filesystem;
49-
50-
@override
51-
FilesystemCache get cache => _delegate.cache;
52-
53-
@override
54-
AssetFinder get assetFinder => _delegate.assetFinder;
55-
56-
@override
57-
InputTracker? get inputTracker => _delegate.inputTracker;
58-
59-
@override
60-
Future<bool> canRead(AssetId id) =>
61-
_delegate.canRead(_cacheLocation(id, _assetGraph, _rootPackage));
62-
63-
@override
64-
Future<Digest> digest(AssetId id) =>
65-
_delegate.digest(_cacheLocation(id, _assetGraph, _rootPackage));
66-
67-
@override
68-
Future<List<int>> readAsBytes(AssetId id) =>
69-
_delegate.readAsBytes(_cacheLocation(id, _assetGraph, _rootPackage));
70-
71-
@override
72-
Future<String> readAsString(AssetId id, {Encoding encoding = utf8}) =>
73-
_delegate.readAsString(
74-
_cacheLocation(id, _assetGraph, _rootPackage),
75-
encoding: encoding,
76-
);
24+
BuildCacheAssetPathProvider({
25+
required AssetPathProvider delegate,
26+
required AssetGraph assetGraph,
27+
required String rootPackage,
28+
}) : _delegate = delegate,
29+
_assetGraph = assetGraph,
30+
_rootPackage = rootPackage;
7731

7832
@override
79-
Stream<AssetId> findAssets(Glob glob) =>
80-
throw UnimplementedError(
81-
'Asset globbing should be done per phase with the AssetGraph',
82-
);
33+
String pathFor(AssetId id) =>
34+
_delegate.pathFor(_cacheLocation(id, _assetGraph, _rootPackage));
8335
}
8436

37+
// TODO(davidmorgan): refactor in the same way as the reader.
8538
class BuildCacheWriter implements RunnerAssetWriter {
8639
final AssetGraph _assetGraph;
8740
final RunnerAssetWriter _delegate;

build_runner_core/lib/src/asset/file_based.dart

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,23 @@ class FileBasedAssetReader extends AssetReader implements AssetReaderState {
3131

3232
FileBasedAssetReader(
3333
this.packageGraph, {
34+
AssetPathProvider? assetPathProvider,
3435
Filesystem? filesystem,
3536
FilesystemCache? cache,
3637
}) : filesystem = filesystem ?? IoFilesystem(),
3738
cache = cache ?? const PassthroughFilesystemCache(),
38-
assetPathProvider = packageGraph;
39+
assetPathProvider = assetPathProvider ?? packageGraph;
3940

4041
@override
41-
FileBasedAssetReader copyWith({FilesystemCache? cache}) =>
42-
FileBasedAssetReader(packageGraph, filesystem: filesystem, cache: cache);
42+
FileBasedAssetReader copyWith({
43+
AssetPathProvider? assetPathProvider,
44+
FilesystemCache? cache,
45+
}) => FileBasedAssetReader(
46+
packageGraph,
47+
assetPathProvider: assetPathProvider ?? this.assetPathProvider,
48+
filesystem: filesystem,
49+
cache: cache ?? this.cache,
50+
);
4351

4452
@override
4553
InputTracker? get inputTracker => null;
@@ -62,8 +70,7 @@ class FileBasedAssetReader extends AssetReader implements AssetReaderState {
6270
ifAbsent: () async {
6371
final path = assetPathProvider.pathFor(id);
6472
if (!await filesystem.exists(path)) {
65-
// TODO(davidmorgan): report the path as well?
66-
throw AssetNotFoundException(id);
73+
throw AssetNotFoundException(id, path: path);
6774
}
6875
return filesystem.readAsBytes(path);
6976
},
@@ -78,7 +85,7 @@ class FileBasedAssetReader extends AssetReader implements AssetReaderState {
7885
ifAbsent: () async {
7986
final path = assetPathProvider.pathFor(id);
8087
if (!await filesystem.exists(path)) {
81-
throw AssetNotFoundException(id);
88+
throw AssetNotFoundException(id, path: path);
8289
}
8390
return filesystem.readAsBytes(path);
8491
},
@@ -153,5 +160,7 @@ class FileBasedAssetWriter implements RunnerAssetWriter {
153160
}
154161

155162
@override
156-
Future<void> completeBuild() async {}
163+
Future<void> completeBuild() async {
164+
// TODO(davidmorgan): add back write caching, "batching".
165+
}
157166
}

0 commit comments

Comments
 (0)