Skip to content

Commit 85e0861

Browse files
committed
Cleanup.
1 parent 167f115 commit 85e0861

File tree

8 files changed

+79
-92
lines changed

8 files changed

+79
-92
lines changed

build_runner_core/lib/src/asset_graph/graph.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ class AssetGraph implements GeneratedAssetHider {
7474
/// Digests from the current build's [BuildPhases].
7575
BuiltList<Digest> postBuildActionsOptionsDigests;
7676

77+
/// Imports of resolved assets in the previous build, or `null` if this is a
78+
/// clean build.
7779
PhasedAssetDeps? previousPhasedAssetDeps;
7880

7981
AssetGraph._(

build_runner_core/lib/src/asset_graph/node.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,8 @@ abstract class GeneratedNodeState
274274
/// to generate it.
275275
BuiltSet<AssetId> get inputs;
276276

277-
/// Dependency graphs used in analysis.
278-
BuiltSet<AssetId> get inputGraphs;
277+
/// Entrypoints used for resolution with the analyzer.
278+
BuiltSet<AssetId> get resolverEntrypoints;
279279

280280
/// Whether the generation succeded, or `null` if it did not run.
281281
///

build_runner_core/lib/src/asset_graph/node.g.dart

Lines changed: 20 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build_runner_core/lib/src/generate/build.dart

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@ class Build {
114114
/// checked against the digest from the previous build.
115115
final Set<AssetId> changedOutputs = {};
116116

117-
final Map<LibraryCycleGraph, bool> hasGraphChanged = Map.identity();
117+
/// Whether a graph from [previousLibraryCycleGraphLoader] has any changed
118+
/// transitive source.
119+
final Map<LibraryCycleGraph, bool> changedGraphs = Map.identity();
118120

119121
Build({
120122
required this.environment,
@@ -904,7 +906,7 @@ class Build {
904906
}
905907
}
906908

907-
for (final graphId in firstOutputState.inputGraphs) {
909+
for (final graphId in firstOutputState.resolverEntrypoints) {
908910
if (await _hasInputGraphChanged(
909911
phaseNumber: phaseNumber,
910912
entrypointId: graphId,
@@ -927,19 +929,24 @@ class Build {
927929
return false;
928930
}
929931

930-
/// Returns whether any source in the _previous build_ transitive import graph
931-
/// of [entrypointId] has changed.
932+
/// Whether any source in the _previous build_ transitive import graph
933+
/// of [entrypointId] has a change visible at [phaseNumber].
934+
///
935+
/// There is a tradeoff between returning early when a first change is
936+
/// encountered and continuing to process the graph to produce results that
937+
/// might be useful later. This implementation is eager, it computes whether
938+
/// every subgraph reachable from [entrypointId] has changed.
932939
Future<bool> _hasInputGraphChanged({
933-
required int phaseNumber,
934940
required AssetId entrypointId,
941+
required int phaseNumber,
935942
}) async {
936943
// If the result has already been calculated, return it.
937944
final entrypointGraph = (await previousLibraryCycleGraphLoader
938945
.libraryCycleGraphOf(
939946
previousDepsLoader!,
940947
entrypointId,
941948
)).valueAt(phase: phaseNumber);
942-
final maybeResult = hasGraphChanged[entrypointGraph];
949+
final maybeResult = changedGraphs[entrypointGraph];
943950
if (maybeResult != null) {
944951
return maybeResult;
945952
}
@@ -951,7 +958,7 @@ class Build {
951958

952959
// If there are multiple paths to a node, it might have been calculated
953960
// for another path.
954-
if (hasGraphChanged.containsKey(nextGraph)) {
961+
if (changedGraphs.containsKey(nextGraph)) {
955962
graphsToCheckStack.removeLast();
956963
continue;
957964
}
@@ -962,7 +969,7 @@ class Build {
962969
// returning to this graph.
963970
final childGraphsWithWorkToDo = <LibraryCycleGraph>[];
964971
for (final childGraph in nextGraph.children) {
965-
final maybeChildResult = hasGraphChanged[childGraph];
972+
final maybeChildResult = changedGraphs[childGraph];
966973
if (maybeChildResult == null) {
967974
childGraphsWithWorkToDo.add(childGraph);
968975
}
@@ -983,29 +990,30 @@ class Build {
983990
}
984991
}
985992
if (rootLibraryCycleHasChanged) {
986-
hasGraphChanged[nextGraph] = true;
993+
changedGraphs[nextGraph] = true;
987994
} else {
988995
var anyChildHasChanged = false;
989996
for (final childGraph in nextGraph.children) {
990-
final childResult = hasGraphChanged[childGraph];
997+
final childResult = changedGraphs[childGraph];
991998
if (childResult == null) {
992999
throw StateError('Child graphs should have been checked.');
9931000
} else if (childResult) {
9941001
anyChildHasChanged = true;
9951002
break;
9961003
}
9971004
}
998-
hasGraphChanged[nextGraph] = anyChildHasChanged;
1005+
changedGraphs[nextGraph] = anyChildHasChanged;
9991006
}
10001007
graphsToCheckStack.removeLast();
10011008
}
10021009

1003-
return hasGraphChanged[entrypointGraph]!;
1010+
return changedGraphs[entrypointGraph]!;
10041011
}
10051012

1013+
/// Whether [input] has a change visible at [phaseNumber].
10061014
Future<bool> _hasInputChanged({
1007-
required int phaseNumber,
10081015
required AssetId input,
1016+
required int phaseNumber,
10091017
}) async {
10101018
final inputNode = assetGraph.get(input)!;
10111019
if (inputNode.type == NodeType.generated) {
@@ -1223,7 +1231,7 @@ class Build {
12231231
outputNode = assetGraph.updateNode(output, (nodeBuilder) {
12241232
nodeBuilder.generatedNodeState
12251233
..inputs.replace(usedInputs)
1226-
..inputGraphs.replace(inputTracker.resolverEntrypoints)
1234+
..resolverEntrypoints.replace(inputTracker.resolverEntrypoints)
12271235
..result = result;
12281236
nodeBuilder.digest = digest;
12291237
});

build_runner_core/lib/src/generate/single_step_reader_writer.dart

Lines changed: 22 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ class SingleStepReaderWriter extends AssetReader
222222
Future<bool> _isReadable(
223223
AssetId id, {
224224
bool catchInvalidInputs = false,
225+
bool track = true,
225226
}) async {
226227
try {
227228
_checkInvalidInput(id);
@@ -234,13 +235,13 @@ class SingleStepReaderWriter extends AssetReader
234235
}
235236

236237
if (_runningBuild == null) {
237-
inputTracker.add(id);
238+
if (track) inputTracker.add(id);
238239
return _delegate.canRead(id);
239240
}
240241

241242
final node = _runningBuild.assetGraph.get(id);
242243
if (node == null) {
243-
inputTracker.add(id);
244+
if (track) inputTracker.add(id);
244245
_runningBuild.assetGraph.add(AssetNode.missingSource(id));
245246
return false;
246247
}
@@ -252,15 +253,19 @@ class SingleStepReaderWriter extends AssetReader
252253
// it's an output of a generator running in parallel, which means it's
253254
// hidden and can't be an input.
254255
if (!readability.inSamePhase) {
255-
inputTracker.add(id);
256+
if (track) inputTracker.add(id);
256257
}
257258

258259
return readability.canRead;
259260
}
260261

261262
@override
262-
Future<bool> canRead(AssetId id) async {
263-
final isReadable = await _isReadable(id, catchInvalidInputs: true);
263+
Future<bool> canRead(AssetId id, {bool track = true}) async {
264+
final isReadable = await _isReadable(
265+
id,
266+
catchInvalidInputs: true,
267+
track: track,
268+
);
264269
if (!isReadable) return false;
265270
if (_runningBuild == null) return true;
266271

@@ -299,8 +304,12 @@ class SingleStepReaderWriter extends AssetReader
299304
}
300305

301306
@override
302-
Future<String> readAsString(AssetId id, {Encoding encoding = utf8}) async {
303-
final isReadable = await _isReadable(id);
307+
Future<String> readAsString(
308+
AssetId id, {
309+
Encoding encoding = utf8,
310+
bool track = true,
311+
}) async {
312+
final isReadable = await _isReadable(id, track: track);
304313
if (!isReadable) {
305314
throw AssetNotFoundException(id);
306315
}
@@ -442,8 +451,6 @@ class SingleStepReaderWriter extends AssetReader
442451

443452
var node = _runningBuild.assetGraph.get(id);
444453
if (node == null) {
445-
// TODO(davidmorgan): test coverage.
446-
_runningBuild.assetGraph.add(AssetNode.missingSource(id));
447454
return PhasedValue.fixed('');
448455
}
449456

@@ -467,55 +474,16 @@ class SingleStepReaderWriter extends AssetReader
467474
}
468475
}
469476

470-
final canRead = await _delegate.canRead(id);
471-
if (canRead && node.digest == null) {
472-
await _ensureDigest(id);
473-
}
474-
475-
return PhasedValue.fixed(canRead ? await _delegate.readAsString(id) : '');
477+
return PhasedValue.fixed(
478+
await _delegate.canRead(id) ? await _delegate.readAsString(id) : '',
479+
);
476480
}
477481

478482
@override
479483
Future<String?> readAtPhase(AssetId id) async {
480-
// TODO(davidmorgan): dedupe.
481-
if (_runningBuild == null) {
482-
final exists = await _delegate.canRead(id);
483-
if (exists) {
484-
return await _delegate.readAsString(id);
485-
} else {
486-
return null;
487-
}
488-
}
489-
490-
var node = _runningBuild.assetGraph.get(id);
491-
if (node == null) {
492-
// TODO(davidmorgan): test coverage.
493-
_runningBuild.assetGraph.add(AssetNode.missingSource(id));
494-
return null;
495-
}
496-
497-
if (node.type == NodeType.generated) {
498-
final nodePhase = node.generatedNodeConfiguration!.phaseNumber;
499-
if (nodePhase >= phase) {
500-
return null;
501-
} else {
502-
// If needed, trigger a build at an earlier phase.
503-
if (!_runningBuild.assetIsProcessedOutput(id)) {
504-
await _runningBuild.nodeBuilder(id);
505-
node = _runningBuild.assetGraph.get(id)!;
506-
}
507-
return (node.wasOutput && node.generatedNodeState!.result == true)
508-
? await _delegate.readAsString(id)
509-
: null;
510-
}
511-
}
512-
513-
final canRead = await _delegate.canRead(id);
514-
if (canRead && node.digest == null) {
515-
await _ensureDigest(id);
516-
}
517-
518-
return canRead ? await _delegate.readAsString(id) : null;
484+
return await canRead(id, track: false)
485+
? await readAsString(id, track: false)
486+
: null;
519487
}
520488

521489
@override

build_runner_core/test/invalidation/huge_resolved_graph_invalidation_test.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ void main() {
1717
tester = InvalidationTester();
1818
});
1919

20+
// This was sufficient to cause a stack overflow when `Build` used a recursive
21+
// algorithm to check for changes to graphs.
2022
final size = 1500;
2123

2224
group('a.1 <== a.2, a.2 resolves z1 --> ... --> z$size', () {

0 commit comments

Comments
 (0)