Skip to content

Commit cf9ba8d

Browse files
committed
Refactor PathProvidingAssetReader to AssetPathProvider.
1 parent aa8e27a commit cf9ba8d

File tree

14 files changed

+84
-91
lines changed

14 files changed

+84
-91
lines changed

build/lib/src/builder/build_step_impl.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import '../asset/id.dart';
1818
import '../asset/reader.dart';
1919
import '../asset/writer.dart';
2020
import '../resource/resource.dart';
21+
import '../state/asset_path_provider.dart';
2122
import '../state/input_tracker.dart';
2223
import '../state/reader_state.dart';
2324
import 'build_step.dart';
@@ -80,6 +81,9 @@ class BuildStepImpl implements BuildStep, AssetReaderState {
8081
_stageTracker = stageTracker ?? NoOpStageTracker.instance,
8182
_reportUnusedAssets = reportUnusedAssets;
8283

84+
@override
85+
AssetPathProvider? get assetPathProvider => _reader.assetPathProvider;
86+
8387
@override
8488
InputTracker? get inputTracker => _reader.inputTracker;
8589

build/lib/src/internal.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
/// `build_test` only.
77
library;
88

9+
export 'state/asset_path_provider.dart';
910
export 'state/input_tracker.dart';
1011
export 'state/reader_state.dart';
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import '../asset/id.dart';
6+
7+
/// Converts [AssetId] to paths.
8+
abstract interface class AssetPathProvider {
9+
String pathFor(AssetId id);
10+
}
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: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import '../asset/reader.dart';
6+
import 'asset_path_provider.dart';
67
import 'input_tracker.dart';
78

89
/// Provides access to the state backing an [AssetReader].
@@ -21,6 +22,10 @@ extension AssetReaderStateExtension on AssetReader {
2122
return result;
2223
}
2324

25+
AssetPathProvider? get assetPathProvider => this is AssetReaderState
26+
? (this as AssetReaderState).assetPathProvider
27+
: null;
28+
2429
/// Throws if `this` is not an [AssetReaderState].
2530
void _requireIsAssetReaderState() {
2631
if (this is! AssetReaderState) {
@@ -35,4 +40,8 @@ abstract interface class AssetReaderState {
3540
/// The [InputTracker] that this reader records reads to; or `null` if it does
3641
/// not have one.
3742
InputTracker? get inputTracker;
43+
44+
/// The [AssetPathProvider] associated with this reader, or `null` if it does
45+
/// not have one.
46+
AssetPathProvider? get assetPathProvider;
3847
}

build_runner_core/lib/src/asset/batch.dart

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,12 @@ final class _FileSystemWriteBatch {
5353
/// they are flushed to the file system.
5454
(RunnerAssetReader, RunnerAssetWriter) wrapInBatch({
5555
required RunnerAssetReader reader,
56-
required PathProvidingAssetReader pathProvidingReader,
5756
required RunnerAssetWriter writer,
5857
}) {
5958
final batch = _FileSystemWriteBatch._();
6059

6160
return (
62-
BatchReader(reader, pathProvidingReader, batch),
61+
BatchReader(reader, batch),
6362
BatchWriter(writer, batch),
6463
);
6564
}
@@ -73,13 +72,11 @@ final class _PendingFileState {
7372
}
7473

7574
@internal
76-
final class BatchReader extends AssetReader
77-
implements RunnerAssetReader, PathProvidingAssetReader {
75+
final class BatchReader extends AssetReader implements RunnerAssetReader {
7876
final RunnerAssetReader _inner;
79-
final PathProvidingAssetReader _innerPathProviding;
8077
final _FileSystemWriteBatch _batch;
8178

82-
BatchReader(this._inner, this._innerPathProviding, this._batch);
79+
BatchReader(this._inner, this._batch);
8380

8481
_PendingFileState? _stateFor(AssetId id) {
8582
return _batch._pendingWrites[id];
@@ -101,11 +98,6 @@ final class BatchReader extends AssetReader
10198
.where((asset) => _stateFor(asset)?.isDeleted != true);
10299
}
103100

104-
@override
105-
String pathTo(AssetId id) {
106-
return _innerPathProviding.pathTo(id);
107-
}
108-
109101
@override
110102
Future<List<int>> readAsBytes(AssetId id) async {
111103
if (_stateFor(id) case final state?) {

build_runner_core/lib/src/asset/build_cache.dart

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,39 @@ import 'dart:async';
22
import 'dart:convert';
33

44
import 'package:build/build.dart';
5+
// ignore: implementation_imports
6+
import 'package:build/src/internal.dart';
57
import 'package:crypto/crypto.dart';
68
import 'package:glob/glob.dart';
79

810
import '../asset_graph/graph.dart';
911
import '../asset_graph/node.dart';
1012
import '../util/constants.dart';
11-
import 'reader.dart';
1213
import 'writer.dart';
1314

1415
/// Wraps an [AssetReader] and translates reads for generated files into reads
1516
/// from the build cache directory
16-
class BuildCacheReader implements AssetReader {
17-
final AssetGraph _assetGraph;
17+
class BuildCacheReader implements AssetReader, AssetReaderState {
18+
@override
19+
final AssetPathProvider? assetPathProvider;
20+
1821
final AssetReader _delegate;
22+
final AssetGraph _assetGraph;
1923
final String _rootPackage;
2024

21-
BuildCacheReader._(this._delegate, this._assetGraph, this._rootPackage);
25+
BuildCacheReader(
26+
AssetReader delegate, AssetGraph assetGraph, String rootPackage)
27+
: _delegate = delegate,
28+
_assetGraph = assetGraph,
29+
_rootPackage = rootPackage,
30+
assetPathProvider = delegate.assetPathProvider == null
31+
? null
32+
: OverlayAssetPathProvider(
33+
delegate: delegate.assetPathProvider!,
34+
overlay: (id) => _cacheLocation(id, assetGraph, rootPackage));
2235

23-
factory BuildCacheReader(
24-
AssetReader delegate, AssetGraph assetGraph, String rootPackage) =>
25-
delegate is PathProvidingAssetReader
26-
? _PathProvidingBuildCacheReader._(delegate, assetGraph, rootPackage)
27-
: BuildCacheReader._(delegate, assetGraph, rootPackage);
36+
@override
37+
InputTracker? get inputTracker => _delegate.inputTracker;
2838

2939
@override
3040
Future<bool> canRead(AssetId id) =>
@@ -48,21 +58,6 @@ class BuildCacheReader implements AssetReader {
4858
'Asset globbing should be done per phase with the AssetGraph');
4959
}
5060

51-
class _PathProvidingBuildCacheReader extends BuildCacheReader
52-
implements PathProvidingAssetReader {
53-
@override
54-
PathProvidingAssetReader get _delegate =>
55-
super._delegate as PathProvidingAssetReader;
56-
57-
_PathProvidingBuildCacheReader._(PathProvidingAssetReader super.delegate,
58-
super.assetGraph, super.rootPackage)
59-
: super._();
60-
61-
@override
62-
String pathTo(AssetId id) =>
63-
_delegate.pathTo(_cacheLocation(id, _assetGraph, _rootPackage));
64-
}
65-
6661
class BuildCacheWriter implements RunnerAssetWriter {
6762
final AssetGraph _assetGraph;
6863
final RunnerAssetWriter _delegate;

build_runner_core/lib/src/asset/cache.dart

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import 'package:crypto/crypto.dart';
1111
import 'package:glob/glob.dart';
1212

1313
import 'lru_cache.dart';
14-
import 'reader.dart';
1514

1615
/// An [AssetReader] that caches all results from the delegate.
1716
///
@@ -46,12 +45,7 @@ class CachingAssetReader implements AssetReader {
4645

4746
final AssetReader _delegate;
4847

49-
CachingAssetReader._(this._delegate);
50-
51-
factory CachingAssetReader(AssetReader delegate) =>
52-
delegate is PathProvidingAssetReader
53-
? _PathProvidingCachingAssetReader._(delegate)
54-
: CachingAssetReader._(delegate);
48+
CachingAssetReader(this._delegate);
5549

5650
@override
5751
Future<bool> canRead(AssetId id) =>
@@ -111,17 +105,3 @@ class CachingAssetReader implements AssetReader {
111105
}
112106
}
113107
}
114-
115-
/// A version of a [CachingAssetReader] that implements
116-
/// [PathProvidingAssetReader].
117-
class _PathProvidingCachingAssetReader extends CachingAssetReader
118-
implements PathProvidingAssetReader {
119-
@override
120-
PathProvidingAssetReader get _delegate =>
121-
super._delegate as PathProvidingAssetReader;
122-
123-
_PathProvidingCachingAssetReader._(super.delegate) : super._();
124-
125-
@override
126-
String pathTo(AssetId id) => _delegate.pathTo(id);
127-
}

build_runner_core/lib/src/asset/file_based.dart

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ final _descriptorPool = Pool(32);
2020

2121
/// Basic [AssetReader] which uses a [PackageGraph] to look up where to read
2222
/// files from disk.
23-
class FileBasedAssetReader extends AssetReader
24-
implements RunnerAssetReader, PathProvidingAssetReader {
23+
class FileBasedAssetReader extends AssetReader implements RunnerAssetReader {
2524
final PackageGraph packageGraph;
2625

2726
FileBasedAssetReader(this.packageGraph);
@@ -55,9 +54,6 @@ class FileBasedAssetReader extends AssetReader
5554
.cast<File>()
5655
.map((file) => _fileToAssetId(file, packageNode));
5756
}
58-
59-
@override
60-
String pathTo(AssetId id) => _filePathFor(id, packageGraph);
6157
}
6258

6359
/// Creates an [AssetId] for [file], which is a part of [packageNode].
@@ -112,18 +108,9 @@ class FileBasedAssetWriter implements RunnerAssetWriter {
112108
Future<void> completeBuild() async {}
113109
}
114110

115-
/// Returns the path to [id] for a given [packageGraph].
116-
String _filePathFor(AssetId id, PackageGraph packageGraph) {
117-
var package = packageGraph[id.package];
118-
if (package == null) {
119-
throw PackageNotFoundException(id.package);
120-
}
121-
return path.join(package.path, id.path);
122-
}
123-
124111
/// Returns a [File] for [id] given [packageGraph].
125112
File _fileFor(AssetId id, PackageGraph packageGraph) {
126-
return File(_filePathFor(id, packageGraph));
113+
return File(packageGraph.pathFor(id));
127114
}
128115

129116
/// Returns a `File` for the asset reference by [id] given [packageGraph].

build_runner_core/lib/src/asset/reader.dart

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,6 @@ import '../util/async.dart';
1919
/// A [RunnerAssetReader] must implement [MultiPackageAssetReader].
2020
abstract class RunnerAssetReader implements MultiPackageAssetReader {}
2121

22-
/// An [AssetReader] that can provide actual paths to assets on disk.
23-
abstract class PathProvidingAssetReader implements AssetReader {
24-
String pathTo(AssetId id);
25-
}
26-
2722
/// Describes if and how a [SingleStepReader] should read an [AssetId].
2823
class Readability {
2924
final bool canRead;
@@ -80,6 +75,9 @@ class SingleStepReader implements AssetReader, AssetReaderState {
8075
this._primaryPackage, this._isReadableNode, this._checkInvalidInput,
8176
[this._getGlobNode, this._writtenAssets]);
8277

78+
@override
79+
AssetPathProvider? get assetPathProvider => _delegate.assetPathProvider;
80+
8381
/// Checks whether [id] can be read by this step - attempting to build the
8482
/// asset if necessary.
8583
///

build_runner_core/lib/src/environment/create_merged_dir.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import 'dart:convert';
77
import 'dart:io';
88

99
import 'package:build/build.dart';
10+
// ignore: implementation_imports
11+
import 'package:build/src/internal.dart';
1012
import 'package:logging/logging.dart';
1113
import 'package:path/path.dart' as p;
1214
import 'package:pool/pool.dart';
1315

14-
import '../asset/reader.dart';
1516
import '../environment/build_environment.dart';
1617
import '../generate/build_directory.dart';
1718
import '../generate/finalized_assets_view.dart';
@@ -35,7 +36,7 @@ Future<bool> createMergedOutputDirectories(
3536
AssetReader reader,
3637
FinalizedAssetsView finalizedAssetsView,
3738
bool outputSymlinksOnly) async {
38-
if (outputSymlinksOnly && reader is! PathProvidingAssetReader) {
39+
if (outputSymlinksOnly && reader.assetPathProvider == null) {
3940
_logger.severe(
4041
'The current environment does not support symlinks, but symlinks were '
4142
'requested.');
@@ -229,7 +230,7 @@ Future<AssetId> _writeAsset(
229230
await Link(_filePathFor(outputDir, outputId)).create(
230231
// We assert at the top of `createMergedOutputDirectories` that the
231232
// reader implements this type when requesting symlinks.
232-
(reader as PathProvidingAssetReader).pathTo(id),
233+
reader.assetPathProvider!.pathFor(id),
233234
recursive: true);
234235
} else {
235236
await _writeAsBytes(outputDir, outputId, await reader.readAsBytes(id));

build_runner_core/lib/src/environment/io_environment.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,7 @@ class IOEnvironment implements BuildEnvironment {
5555

5656
var (reader, writer) = lowResourcesMode
5757
? (fileReader, fileWriter)
58-
: wrapInBatch(
59-
reader: fileReader,
60-
pathProvidingReader: fileReader,
61-
writer: fileWriter);
58+
: wrapInBatch(reader: fileReader, writer: fileWriter);
6259

6360
return IOEnvironment._(reader, writer, assumeTty == true || _canPrompt(),
6461
outputSymlinksOnly, packageGraph);

build_runner_core/lib/src/package_graph/package_graph.dart

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

55
import 'dart:io';
66

7+
import 'package:build/build.dart';
8+
// ignore: implementation_imports
9+
import 'package:build/src/internal.dart';
710
import 'package:package_config/package_config.dart';
811
import 'package:path/path.dart' as p;
912
import 'package:yaml/yaml.dart';
@@ -16,7 +19,7 @@ final _sdkPackageNode =
1619
PackageNode(r'$sdk', sdkPath, DependencyType.hosted, null);
1720

1821
/// A graph of the package dependencies for an application.
19-
class PackageGraph {
22+
class PackageGraph implements AssetPathProvider {
2023
/// The root application package.
2124
final PackageNode root;
2225

@@ -167,6 +170,15 @@ class PackageGraph {
167170
/// Shorthand to get a package by name.
168171
PackageNode? operator [](String packageName) => allPackages[packageName];
169172

173+
@override
174+
String pathFor(AssetId id) {
175+
var package = this[id.package];
176+
if (package == null) {
177+
throw PackageNotFoundException(id.package);
178+
}
179+
return p.join(package.path, id.path);
180+
}
181+
170182
@override
171183
String toString() {
172184
var buffer = StringBuffer();

build_runner_core/test/asset/batch_test.dart

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import 'dart:io';
88

99
import 'package:build/build.dart';
1010
import 'package:build_runner_core/build_runner_core.dart';
11-
1211
import 'package:glob/glob.dart';
1312
import 'package:package_config/package_config_types.dart';
1413
import 'package:test/test.dart';
@@ -24,10 +23,7 @@ void main() {
2423
final fileReader = FileBasedAssetReader(packageGraph);
2524
final fileWriter = FileBasedAssetWriter(packageGraph);
2625

27-
(reader, writer) = wrapInBatch(
28-
reader: fileReader,
29-
pathProvidingReader: fileReader,
30-
writer: fileWriter);
26+
(reader, writer) = wrapInBatch(reader: fileReader, writer: fileWriter);
3127
});
3228

3329
test('delays writes until end', () async {

0 commit comments

Comments
 (0)