diff --git a/example_usage/build.yaml b/example_usage/build.yaml index f6724d97..2baa5861 100644 --- a/example_usage/build.yaml +++ b/example_usage/build.yaml @@ -14,3 +14,10 @@ targets: source_gen_example|property_product: generate_for: - lib/*.dart + # The end-user of a builder which applies "source_gen|combining_builder" + # may configure the builder to ignore specific lints for their project + source_gen|combining_builder: + options: + ignore_for_file: + - lint_a + - lint_b diff --git a/example_usage/lib/library_source.g.dart b/example_usage/lib/library_source.g.dart index cfd49d6a..482ec38e 100644 --- a/example_usage/lib/library_source.g.dart +++ b/example_usage/lib/library_source.g.dart @@ -1,5 +1,7 @@ // GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: lint_a, lint_b + part of 'library_source.dart'; // ************************************************************************** diff --git a/source_gen/CHANGELOG.md b/source_gen/CHANGELOG.md index 07d206da..5964f349 100644 --- a/source_gen/CHANGELOG.md +++ b/source_gen/CHANGELOG.md @@ -1,5 +1,7 @@ ## 0.9.5-dev +* Add support for an `ignore_for_file` option to `combining_builder`. + * Expand documentation for `GeneratorForAnnotation` to make it clear that it only targets elements at the top level of a library. diff --git a/source_gen/README.md b/source_gen/README.md index 9a35691f..4fab69c3 100644 --- a/source_gen/README.md +++ b/source_gen/README.md @@ -93,6 +93,30 @@ builders: applies_builders: ["source_gen|combining_builder"] ``` +### Configuring `combining_builder` `ignore_for_file` + +Sometimes generated code does not support all of the +[lints](https://dart-lang.github.io/linter/) specified in the target package. +When using a `Builder` based on `package:source_gen` which applies +`combining_builder`, set the `ignore_for_file` option to a list of lints you +wish to be ignored in all generated libraries. + +_Example `build.yaml` configuration:_ + +```yaml +targets: + $default": + builders: + source_gen|combining_builder: + options: + ignore_for_file: + - lint_alpha + - lint_beta +``` + +If you provide a builder that uses `SharedPartBuilder` and `combining_builder`, +you should document this feature for your users. + ## FAQ ### What is the difference between `source_gen` and [build][]? diff --git a/source_gen/lib/builder.dart b/source_gen/lib/builder.dart index b17216c7..b4188559 100644 --- a/source_gen/lib/builder.dart +++ b/source_gen/lib/builder.dart @@ -27,8 +27,15 @@ const _partFiles = '.g.part'; Builder combiningBuilder([BuilderOptions options]) { final optionsMap = Map.from(options?.config ?? {}); + final includePartName = optionsMap.remove('include_part_name') as bool; + final ignoreForFile = Set.from( + optionsMap.remove('ignore_for_file') as List ?? [], + ); + final builder = CombiningBuilder( - includePartName: optionsMap.remove('include_part_name') as bool); + includePartName: includePartName, + ignoreForFile: ignoreForFile, + ); if (optionsMap.isNotEmpty) { if (log == null) { @@ -49,6 +56,8 @@ PostProcessBuilder partCleanup(BuilderOptions options) => class CombiningBuilder implements Builder { final bool _includePartName; + final Set _ignoreForFile; + @override Map> get buildExtensions => const { '.dart': [_outputExtensions] @@ -59,8 +68,11 @@ class CombiningBuilder implements Builder { /// If [includePartName] is `true`, the name of each source part file /// is output as a comment before its content. This can be useful when /// debugging build issues. - const CombiningBuilder({bool includePartName = false}) - : _includePartName = includePartName ?? false; + const CombiningBuilder({ + bool includePartName = false, + Set ignoreForFile, + }) : _includePartName = includePartName ?? false, + _ignoreForFile = ignoreForFile ?? const {}; @override Future build(BuildStep buildStep) async { @@ -100,9 +112,13 @@ class CombiningBuilder implements Builder { if (assets.isEmpty) return; final partOf = nameOfPartial(await buildStep.inputLibrary, buildStep.inputId); + + final ignoreForFile = _ignoreForFile.isEmpty + ? '' + : '\n// ignore_for_file: ${_ignoreForFile.join(', ')}\n'; final output = ''' $defaultFileHeader - +$ignoreForFile part of $partOf; $assets diff --git a/source_gen/test/builder_test.dart b/source_gen/test/builder_test.dart index 5c15703a..a5cc25fa 100644 --- a/source_gen/test/builder_test.dart +++ b/source_gen/test/builder_test.dart @@ -388,6 +388,33 @@ void main() { '// Part: a.only_whitespace.g.part\n\n')), }); }); + + test('includes ignore for file if enabled', () async { + await testBuilder( + const CombiningBuilder(ignoreForFile: { + 'lines_longer_than_80_chars', + 'prefer_expression_function_bodies', + }), + { + '$_pkgName|lib/a.dart': 'library a; part "a.g.dart";', + '$_pkgName|lib/a.foo.g.part': '\n\nfoo generated content\n', + '$_pkgName|lib/a.only_whitespace.g.part': '\n\n\t \n \n', + '$_pkgName|lib/a.bar.g.part': '\nbar generated content', + }, + generateFor: {'$_pkgName|lib/a.dart'}, + outputs: { + '$_pkgName|lib/a.g.dart': decodedMatches(endsWith(r''' +// ignore_for_file: lines_longer_than_80_chars, prefer_expression_function_bodies + +part of a; + +bar generated content + +foo generated content +''')), + }, + ); + }); }); test('can skip formatting with a trivial lambda', () async {