From 49ab04b62ca7d9d15432234ac0dc89134a7840ad Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 6 Jun 2023 17:14:06 +0000 Subject: [PATCH 1/2] Allow single builder cycles Fixes #3531 When a builder outputs a file with the same extension as a `required_input` it will be in a cycle with itself. When builders were ordered with `stronglyConnectedComponents` cycles were detected by looking for a component (cycle) with more than one builder. With the move to `topologicalSort` the single builder cycle causes an exception during the sort. Exclude the builder itself from the list of dependencies for the graph algorithm call. --- build_runner/CHANGELOG.md | 5 +++++ .../builder_ordering.dart | 5 +++-- build_runner/pubspec.yaml | 2 +- .../builder_ordering_test.dart | 20 +++++++++++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/build_runner/CHANGELOG.md b/build_runner/CHANGELOG.md index 0935bacd0c..8b9ec81854 100644 --- a/build_runner/CHANGELOG.md +++ b/build_runner/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.4.5 + +- Fix a bug handling a builder which has a `required_input` that matches it's + own output. + ## 2.4.4 - Use a stable order for builders without an order defined by dependencies. diff --git a/build_runner/lib/src/build_script_generate/builder_ordering.dart b/build_runner/lib/src/build_script_generate/builder_ordering.dart index 2c3a593dd6..d418837bcf 100644 --- a/build_runner/lib/src/build_script_generate/builder_ordering.dart +++ b/build_runner/lib/src/build_script_generate/builder_ordering.dart @@ -18,8 +18,9 @@ Iterable findBuilderOrder( ..sort((a, b) => a.key.compareTo(b.key)); Iterable dependencies(BuilderDefinition parent) => consistentOrderBuilders.where((child) => - _hasInputDependency(parent, child) || - _mustRunBefore(parent, child, globalBuilderConfigs)); + parent != child && + (_hasInputDependency(parent, child) || + _mustRunBefore(parent, child, globalBuilderConfigs))); try { return topologicalSort( consistentOrderBuilders, diff --git a/build_runner/pubspec.yaml b/build_runner/pubspec.yaml index b0aa298acf..7a7461d184 100644 --- a/build_runner/pubspec.yaml +++ b/build_runner/pubspec.yaml @@ -1,5 +1,5 @@ name: build_runner -version: 2.4.4 +version: 2.4.5 description: A build system for Dart code generation and modular compilation. repository: https://github.com/dart-lang/build/tree/master/build_runner diff --git a/build_runner/test/build_script_generate/builder_ordering_test.dart b/build_runner/test/build_script_generate/builder_ordering_test.dart index fcceadf687..fe0d570c0d 100644 --- a/build_runner/test/build_script_generate/builder_ordering_test.dart +++ b/build_runner/test/build_script_generate/builder_ordering_test.dart @@ -185,5 +185,25 @@ void main() { {}), throwsA(anything)); }); + + test('allows self cycles with `required_inputs`', () async { + final buildConfigs = parseBuildConfigs({ + 'a': { + 'builders': { + 'self_cycle': { + 'builder_factories': ['createBuilder'], + 'build_extensions': {'.in': ['.out'], '.out': ['.another']}, + 'target': '', + 'import': '', + 'required_inputs': ['.out'], + }, + } + } + }); + final orderedBuilders = findBuilderOrder( + buildConfigs.values.expand((v) => v.builderDefinitions.values), {}); + final orderedKeys = orderedBuilders.map((b) => b.key); + expect(orderedKeys, ['a:self_cycle']); + }); }); } From 33ee211d40bd9d4ed4885af3a7df2c176745c393 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 6 Jun 2023 17:27:18 +0000 Subject: [PATCH 2/2] format --- .../test/build_script_generate/builder_ordering_test.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build_runner/test/build_script_generate/builder_ordering_test.dart b/build_runner/test/build_script_generate/builder_ordering_test.dart index fe0d570c0d..c0c013bb60 100644 --- a/build_runner/test/build_script_generate/builder_ordering_test.dart +++ b/build_runner/test/build_script_generate/builder_ordering_test.dart @@ -192,7 +192,10 @@ void main() { 'builders': { 'self_cycle': { 'builder_factories': ['createBuilder'], - 'build_extensions': {'.in': ['.out'], '.out': ['.another']}, + 'build_extensions': { + '.in': ['.out'], + '.out': ['.another'] + }, 'target': '', 'import': '', 'required_inputs': ['.out'],