Skip to content

Commit bca292a

Browse files
committed
Refactor MultiPackagesAssetReader to AssetFinder.
1 parent 94e000f commit bca292a

35 files changed

+197
-108
lines changed

_test_common/lib/in_memory_reader_writer.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import 'package:path/path.dart' as p;
1111
import 'package:watcher/watcher.dart';
1212

1313
class InMemoryRunnerAssetReaderWriter extends InMemoryAssetReaderWriter
14-
implements RunnerAssetReader, RunnerAssetWriter {
14+
implements AssetReader, RunnerAssetWriter {
1515
final _onCanReadController = StreamController<AssetId>.broadcast();
1616
Stream<AssetId> get onCanRead => _onCanReadController.stream;
1717
void Function(AssetId)? onDelete;

_test_common/lib/test_environment.dart

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

55
import 'dart:async';
66

7+
import 'package:build/build.dart';
78
import 'package:build_runner_core/build_runner_core.dart';
89
import 'package:logging/logging.dart';
910

@@ -21,7 +22,7 @@ class TestBuildEnvironment extends BuildEnvironment {
2122
final InMemoryRunnerAssetReaderWriter _readerWriter;
2223

2324
@override
24-
RunnerAssetReader get reader => _readerWriter;
25+
AssetReader get reader => _readerWriter;
2526
@override
2627
RunnerAssetWriter get writer => _readerWriter;
2728

build/lib/src/asset/reader.dart

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,3 @@ abstract class AssetReader {
5656
return digestSink.events.first;
5757
}
5858
}
59-
60-
/// The same as an `AssetReader`, except that `findAssets` takes an optional
61-
/// argument `package` which allows you to glob any package.
62-
///
63-
/// This should not be exposed to end users generally, but can be used by
64-
/// different build system implementations.
65-
abstract class MultiPackageAssetReader extends AssetReader {
66-
/// Returns all readable assets matching [glob] under [package].
67-
///
68-
/// Some implementations may require the [package] argument, while others
69-
/// may have a sane default.
70-
@override
71-
Stream<AssetId> findAssets(Glob glob, {String? package});
72-
}

build/lib/src/builder/build_step_impl.dart

Lines changed: 5 additions & 5 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_finder.dart';
2122
import '../state/asset_path_provider.dart';
2223
import '../state/input_tracker.dart';
2324
import '../state/reader_state.dart';
@@ -81,6 +82,9 @@ class BuildStepImpl implements BuildStep, AssetReaderState {
8182
_stageTracker = stageTracker ?? NoOpStageTracker.instance,
8283
_reportUnusedAssets = reportUnusedAssets;
8384

85+
@override
86+
AssetFinder get assetFinder => _reader.assetFinder;
87+
8488
@override
8589
AssetPathProvider? get assetPathProvider => _reader.assetPathProvider;
8690

@@ -135,11 +139,7 @@ class BuildStepImpl implements BuildStep, AssetReaderState {
135139
@override
136140
Stream<AssetId> findAssets(Glob glob) {
137141
if (_isComplete) throw BuildStepCompletedException();
138-
if (_reader is MultiPackageAssetReader) {
139-
return _reader.findAssets(glob, package: inputId.package);
140-
} else {
141-
return _reader.findAssets(glob);
142-
}
142+
return _reader.assetFinder.find(glob, package: inputId.package);
143143
}
144144

145145
@override

build/lib/src/internal.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
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-
/// Internal build state for `build_resolvers`, `build_runner_core` and
6-
/// `build_test` only.
5+
/// Internal build state for `build_resolvers`, `build_runner`,
6+
/// `build_runner_core` and `build_test` only.
77
library;
88

9+
export 'state/asset_finder.dart';
910
export 'state/asset_path_provider.dart';
1011
export 'state/input_tracker.dart';
1112
export 'state/reader_state.dart';

build/lib/src/state/asset_finder.dart

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
import 'dart:async';
5+
6+
import 'package:glob/glob.dart';
7+
8+
import '../asset/id.dart';
9+
10+
abstract interface class AssetFinder {
11+
/// Returns all readable assets matching [glob] under [package].
12+
///
13+
/// `Reader.findAssets` exposes this funcionality without allowing controlling
14+
/// [package].
15+
Stream<AssetId> find(Glob glob, {String? package});
16+
}
17+
18+
class FunctionAssetFinder implements AssetFinder {
19+
final Stream<AssetId> Function(Glob, String?) function;
20+
21+
FunctionAssetFinder(this.function);
22+
23+
@override
24+
Stream<AssetId> find(Glob glob, {String? package}) => function(glob, package);
25+
}

build/lib/src/state/reader_state.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@
33
// BSD-style license that can be found in the LICENSE file.
44

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

910
/// Provides access to the state backing an [AssetReader].
1011
extension AssetReaderStateExtension on AssetReader {
12+
AssetFinder get assetFinder {
13+
_requireIsAssetReaderState();
14+
return (this as AssetReaderState).assetFinder;
15+
}
16+
1117
InputTracker? get inputTracker =>
1218
this is AssetReaderState ? (this as AssetReaderState).inputTracker : null;
1319

@@ -37,6 +43,12 @@ extension AssetReaderStateExtension on AssetReader {
3743

3844
/// The state backing an [AssetReader].
3945
abstract interface class AssetReaderState {
46+
/// The [AssetFinder] associated with this reader.
47+
///
48+
/// All readers have an [AssetFinder], but the functionality it provides,
49+
/// globbing in arbitrary packages, is hidden from generators.
50+
AssetFinder get assetFinder;
51+
4052
/// The [InputTracker] that this reader records reads to; or `null` if it does
4153
/// not have one.
4254
InputTracker? get inputTracker;

build_runner/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## 2.4.16-wip
22

33
- Use `build_test` 3.0.0.
4+
- Start using `package:build/src/internal.dart'.
45

56
## 2.4.15
67

build_runner/lib/src/generate/build.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Future<BuildResult> build(List<BuilderApplication> builders,
5353
bool? assumeTty,
5454
String? configKey,
5555
PackageGraph? packageGraph,
56-
RunnerAssetReader? reader,
56+
AssetReader? reader,
5757
RunnerAssetWriter? writer,
5858
Resolvers? resolvers,
5959
Level? logLevel,
@@ -148,7 +148,7 @@ Future<ServeHandler> watch(List<BuilderApplication> builders,
148148
bool? assumeTty,
149149
String? configKey,
150150
PackageGraph? packageGraph,
151-
RunnerAssetReader? reader,
151+
AssetReader? reader,
152152
RunnerAssetWriter? writer,
153153
Resolvers? resolvers,
154154
Level? logLevel,

build_runner/lib/src/generate/watch_impl.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Future<ServeHandler> watch(
3636
bool? assumeTty,
3737
String? configKey,
3838
PackageGraph? packageGraph,
39-
RunnerAssetReader? reader,
39+
AssetReader? reader,
4040
RunnerAssetWriter? writer,
4141
Resolvers? resolvers,
4242
Level? logLevel,

build_runner/lib/src/package_graph/build_config_overrides.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import 'dart:async';
66

77
import 'package:build/build.dart';
8+
// ignore: implementation_imports
9+
import 'package:build/src/internal.dart';
810
import 'package:build_config/build_config.dart';
911
import 'package:build_runner_core/build_runner_core.dart';
1012
import 'package:glob/glob.dart';
@@ -14,11 +16,11 @@ import 'package:path/path.dart' as p;
1416
final _log = Logger('BuildConfigOverrides');
1517

1618
Future<Map<String, BuildConfig>> findBuildConfigOverrides(
17-
PackageGraph packageGraph, RunnerAssetReader reader,
19+
PackageGraph packageGraph, AssetReader reader,
1820
{String? configKey}) async {
1921
final configs = <String, BuildConfig>{};
20-
final configFiles =
21-
reader.findAssets(Glob('*.build.yaml'), package: packageGraph.root.name);
22+
final configFiles = reader.assetFinder
23+
.find(Glob('*.build.yaml'), package: packageGraph.root.name);
2224
await for (final id in configFiles) {
2325
final packageName = p.basename(id.path).split('.').first;
2426
final packageNode = packageGraph.allPackages[packageName];

build_runner/lib/src/server/server.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ class AssetHandler {
381381
var directoryPath = p.url.dirname(from.path);
382382
var glob = p.url.join(directoryPath, '*');
383383
var result =
384-
await _reader.findAssets(Glob(glob)).map((a) => a.path).toList();
384+
await _reader.assetFinder.find(Glob(glob)).map((a) => a.path).toList();
385385
var message = StringBuffer('Could not find ${from.path}');
386386
if (result.isEmpty) {
387387
message.write(' or any files in $directoryPath. ');

build_runner/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ dependencies:
1616
analyzer: '>=4.4.0 <8.0.0'
1717
args: ^2.0.0
1818
async: ^2.5.0
19-
build: ">=2.1.0 <2.5.0"
19+
build: ^2.3.4-wip
2020
build_config: ">=1.1.0 <1.2.0"
2121
build_daemon: ^4.0.0
2222
build_resolvers: ^2.4.4

build_runner_core/lib/build_runner_core.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ export 'package:build/build.dart' show PostProcessBuildStep, PostProcessBuilder;
77
export 'src/asset/batch.dart' show wrapInBatch;
88
export 'src/asset/file_based.dart';
99
export 'src/asset/finalized_reader.dart';
10-
export 'src/asset/reader.dart' show RunnerAssetReader;
1110
export 'src/asset/writer.dart';
1211
export 'src/environment/build_environment.dart';
1312
export 'src/environment/io_environment.dart';

build_runner_core/lib/src/asset/batch.dart

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import 'package:glob/glob.dart';
1212
import 'package:meta/meta.dart';
1313

1414
import '../environment/io_environment.dart';
15-
import 'reader.dart';
1615
import 'writer.dart';
1716

1817
/// A batch of file system writes that should be committed at once instead of
@@ -46,15 +45,15 @@ final class _FileSystemWriteBatch {
4645
}
4746
}
4847

49-
/// Wraps a pair of a [RunnerAssetReader] with path-prividing capabilities and
48+
/// Wraps a pair of a [AssetReader] with path-providing capabilities and
5049
/// a [RunnerAssetWriter] into a pair of readers and writers that will
5150
/// internally buffer writes and only flush them in
5251
/// [RunnerAssetWriter.completeBuild].
5352
///
5453
/// The returned reader will see pending writes by the returned writer before
5554
/// they are flushed to the file system.
56-
(RunnerAssetReader, RunnerAssetWriter) wrapInBatch({
57-
required RunnerAssetReader reader,
55+
(AssetReader, RunnerAssetWriter) wrapInBatch({
56+
required AssetReader reader,
5857
required RunnerAssetWriter writer,
5958
}) {
6059
final batch = _FileSystemWriteBatch._();
@@ -74,9 +73,10 @@ final class _PendingFileState {
7473
}
7574

7675
@internal
77-
final class BatchReader extends AssetReader
78-
implements AssetReaderState, RunnerAssetReader {
79-
final RunnerAssetReader _inner;
76+
final class BatchReader extends AssetReader implements AssetReaderState {
77+
@override
78+
late final AssetFinder assetFinder = FunctionAssetFinder(_findAssets);
79+
final AssetReader _inner;
8080
final _FileSystemWriteBatch _batch;
8181

8282
BatchReader(this._inner, this._batch);
@@ -87,6 +87,12 @@ final class BatchReader extends AssetReader
8787
@override
8888
InputTracker? get inputTracker => _inner.inputTracker;
8989

90+
@override
91+
AssetPathProvider? get assetPathProvider => _inner.assetPathProvider;
92+
93+
@override
94+
InputTracker? get inputTracker => _inner.inputTracker;
95+
9096
_PendingFileState? _stateFor(AssetId id) {
9197
return _batch._pendingWrites[id];
9298
}
@@ -100,10 +106,13 @@ final class BatchReader extends AssetReader
100106
}
101107
}
102108

109+
// This is only for generators, so only `BuildStep` needs to implement it.
103110
@override
104-
Stream<AssetId> findAssets(Glob glob, {String? package}) {
105-
return _inner
106-
.findAssets(glob, package: package)
111+
Stream<AssetId> findAssets(Glob glob) => throw UnimplementedError();
112+
113+
Stream<AssetId> _findAssets(Glob glob, String? package) {
114+
return _inner.assetFinder
115+
.find(glob, package: package)
107116
.where((asset) => _stateFor(asset)?.isDeleted != true);
108117
}
109118

build_runner_core/lib/src/asset/build_cache.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class BuildCacheReader implements AssetReader, AssetReaderState {
3333
delegate: delegate.assetPathProvider!,
3434
overlay: (id) => _cacheLocation(id, assetGraph, rootPackage));
3535

36+
@override
37+
AssetFinder get assetFinder => _delegate.assetFinder;
38+
3639
@override
3740
InputTracker? get inputTracker => _delegate.inputTracker;
3841

build_runner_core/lib/src/asset/cache.dart

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ import 'lru_cache.dart';
1717
/// An [AssetReader] that caches all results from the delegate.
1818
///
1919
/// Assets are cached until [invalidate] is invoked.
20-
///
21-
/// Does not implement [findAssets].
2220
class CachingAssetReader implements AssetReader, AssetReaderState {
2321
/// Cached results of [readAsBytes].
2422
final _bytesContentCache = LruCache<AssetId, List<int>>(
@@ -55,16 +53,25 @@ class CachingAssetReader implements AssetReader, AssetReaderState {
5553
@override
5654
InputTracker? get inputTracker => _delegate.inputTracker;
5755

56+
@override
57+
AssetFinder get assetFinder => _delegate.assetFinder;
58+
59+
@override
60+
AssetPathProvider? get assetPathProvider => _delegate.assetPathProvider;
61+
62+
@override
63+
InputTracker? get inputTracker => _delegate.inputTracker;
64+
5865
@override
5966
Future<bool> canRead(AssetId id) =>
6067
_canReadCache.putIfAbsent(id, () => _delegate.canRead(id));
6168

6269
@override
6370
Future<Digest> digest(AssetId id) => _delegate.digest(id);
6471

72+
// This is only for generators, so only `BuildStep` needs to implement it.
6573
@override
66-
Stream<AssetId> findAssets(Glob glob) =>
67-
throw UnimplementedError('unimplemented!');
74+
Stream<AssetId> findAssets(Glob glob) => throw UnimplementedError();
6875

6976
@override
7077
Future<List<int>> readAsBytes(AssetId id, {bool cache = true}) {

build_runner_core/lib/src/asset/file_based.dart

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,17 @@ import 'package:path/path.dart' as path;
1414
import 'package:pool/pool.dart';
1515

1616
import '../package_graph/package_graph.dart';
17-
import 'reader.dart';
1817
import 'writer.dart';
1918

2019
/// Pool for async file operations, we don't want to use too many file handles.
2120
final _descriptorPool = Pool(32);
2221

2322
/// Basic [AssetReader] which uses a [PackageGraph] to look up where to read
2423
/// files from disk.
25-
class FileBasedAssetReader extends AssetReader
26-
implements AssetReaderState, RunnerAssetReader {
24+
class FileBasedAssetReader extends AssetReader implements AssetReaderState {
25+
@override
26+
late final AssetFinder assetFinder = FunctionAssetFinder(_findAssets);
27+
2728
final PackageGraph packageGraph;
2829

2930
FileBasedAssetReader(this.packageGraph);
@@ -34,6 +35,13 @@ class FileBasedAssetReader extends AssetReader
3435
@override
3536
InputTracker? get inputTracker => null;
3637

38+
@override
39+
AssetPathProvider get assetPathProvider => packageGraph;
40+
41+
@override
42+
// TODO: implement inputTracker
43+
InputTracker? get inputTracker => throw UnimplementedError();
44+
3745
@override
3846
Future<bool> canRead(AssetId id) =>
3947
_descriptorPool.withResource(() => _fileFor(id, packageGraph).exists());
@@ -47,8 +55,11 @@ class FileBasedAssetReader extends AssetReader
4755
_fileForOrThrow(id, packageGraph).then((file) => _descriptorPool
4856
.withResource(() => file.readAsString(encoding: encoding)));
4957

58+
// This is only for generators, so only `BuildStep` needs to implement it.
5059
@override
51-
Stream<AssetId> findAssets(Glob glob, {String? package}) {
60+
Stream<AssetId> findAssets(Glob glob) => throw UnimplementedError();
61+
62+
Stream<AssetId> _findAssets(Glob glob, String? package) {
5263
var packageNode =
5364
package == null ? packageGraph.root : packageGraph[package];
5465
if (packageNode == null) {

0 commit comments

Comments
 (0)