Skip to content

Commit 36da3e4

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

20 files changed

+141
-182
lines changed

_test_common/lib/common.dart

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,11 @@ export 'sdk.dart';
2020
export 'test_phases.dart';
2121

2222
Digest computeDigest(AssetId id, String contents) {
23-
// Special handling for `$$` assets, these are generated under the .dart_tool
24-
// dir and unfortunately that leaks into the digest computations.
25-
if (id.package.startsWith(r'$$')) {
26-
var package = id.package.substring(2);
27-
id = AssetId(package, '.dart_tool/build/generated/$package/${id.path}');
28-
}
29-
return md5.convert([...utf8.encode(contents), ...id.toString().codeUnits]);
23+
// Tests use `$$` at the start of an ID to signal "generated", remove it.
24+
var idString = id.toString();
25+
if (idString.startsWith(r'$$')) idString = idString.substring(2);
26+
27+
return md5.convert([...utf8.encode(contents), ...idString.codeUnits]);
3028
}
3129

3230
class PlaceholderBuilder extends Builder {

_test_common/lib/matchers.dart

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,13 @@ class _AssetGraphMatcher extends Matcher {
189189
}
190190
}
191191
}
192-
if (!equals(_expected.packageLanguageVersions).matches(
193-
item.packageLanguageVersions,
194-
matchState['packageLanguageVersions'] = <String, LanguageVersion?>{},
195-
)) {
192+
if (!equals(
193+
_expected.packageLanguageVersions,
194+
).matches(item.packageLanguageVersions, matchState)) {
195+
matchState['packageLanguageVersions'] = [
196+
item.packageLanguageVersions,
197+
_expected.packageLanguageVersions,
198+
];
196199
matches = false;
197200
}
198201
return matches;

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;

0 commit comments

Comments
 (0)