Using the source_gen stack to make a code generator, how can I make a generator that generates code that would be the input of another generator (more specifically json_serializable
)?
For example, consider:
class Example extends Generator {
@override
String generate(LibraryReader library, BuildStep buildStep) {
return '''
@JsonSerializable(nullable: false)
class Person {
final String firstName;
final String lastName;
final DateTime dateOfBirth;
Person({this.firstName, this.lastName, this.dateOfBirth});
factory Person.fromJson(Map<String, dynamic> json) => _PersonFromJson(json);
Map<String, dynamic> toJson() => _PersonToJson(this);
}
''';
}
}
This is an example of a code-generator that output code which then needs to be sent to json_serializable
What can I do so that json_serializable
correctly generates here?
Check the build.yaml config file documentation for more info, but I think you should use the applies_builders
param that allows to execute another build after the defined one.
The example shows a builder that generates .tar.gz files and then executes another build that takes the .tar.gz files as input
builders:
# The regular builder config, creates .tar.gz files.
regular_builder:
import: "package:my_package/builder.dart"
builder_factories: ["myBuilder"]
build_extensions: {".dart": [".tar.gz"]}
auto_apply: dependents
apply_builders: [":archive_extract_builder"]
post_process_builders:
# The post process builder config, extracts .tar.gz files.
extract_archive_builder:
import: "package:my_package/extract_archive_builder.dart"
builder_factory: "myExtractArchiveBuilder"
input_extensions: [".tar.gz"]
so with source_gen
you should implement for your build
applies_builders: ["source_gen|combining_builder", "json_serializable"]
and configure the other builder
json_serializable:
import: "package:json_serializable/builder.dart"
builder_factories: ["jsonSerializable"]
build_extensions: {".dart": ["json_serializable.g.part"]}
auto_apply: dependents
build_to: cache
applies_builders: ["source_gen|combining_builder"]
It's not possible just with annotation because there maybe two packages that both have the @JsonSerializable
annotation
There are two situtations :
You know what other generators should run after your generator.
class Example extends Generator {
@override
String generate(LibraryReader library, BuildStep buildStep) {
return JsonSerializable().generate('''
@JsonSerializable(nullable: false)
class Person {
final String firstName;
final String lastName;
final DateTime dateOfBirth;
Person({this.firstName, this.lastName, this.dateOfBirth});
factory Person.fromJson(Map<String, dynamic> json) => _PersonFromJson(json);
Map<String, dynamic> toJson() => _PersonToJson(this);
}
''');
}
}
Unfortunately currently there is no way to tell the source_gen that your generator may produce a code that needs code generation.
I created an issue here https://github.com/dart-lang/source_gen/issues/442 if you want to subscribe
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With