Skip to content

Guidance on how to create our own BuilderΒ #745

@Hinageshi

Description

@Hinageshi

Hi, I am writing this seeking for help, since it's quite complicated to find resources on the best way to create Builders πŸ™‚

For our project, we created our own Builder for a specific task. From an input file containing annotated elements, we'd like to obtain a .rpc.dart generated file. Then, we want to apply the retrofit builder on this generated file, to obtain the output, a generated file with .g.dart extension.

For this, we created rpc_generator using source_gen. The build.yaml file looks like this:

builders:
  rpc_generator:
    import: "package:rpc_generator/rpc_generator.dart"
    builder_factories: ["rpcBuilder"]
    build_extensions: { ".dart": [".rpc.dart"] }
    auto_apply: dependents
    build_to: source
    runs_before: ["retrofit_generator"]
    applies_builders: ["retrofit_generator"]

rpc_generator.dart contains the following:
Builder rpcBuilder(BuilderOptions options) => generatorFactoryBuilder(options);

And finally, the builder and generator themselves:

Builder generatorFactoryBuilder(BuilderOptions _) {
  return PartBuilder(
    [const RpcGenerator()],
    '.rpc.dart',
    header: '''
    // coverage:ignore-file
    // GENERATED CODE - DO NOT MODIFY BY HAND
        ''',
  );
}

class RpcGenerator extends Generator {
  const RpcGenerator();

  @override
  Future<String> generate(LibraryReader library, BuildStep buildStep) async {
     ...
  }
}

In local, we have this build.yaml file to call our Builder on our files:

global_options:
  freezed:
    runs_before:
      - json_serializable
  json_serializable:
    runs_before:
      - retrofit_generator
      - rpc_generator

targets:
  $default:
    builders:
      ...
      rpc_generator:rpcBuilder:
        generate_for:
          - lib/api/rpc/*.api.dart;
          - lib/api/*.api.dart

My questions are the following:

  1. We used a PartBuilder because we have to keep both outputs from our Builder and retrofit builder. But is it possible to do better for this task? Like have a SharedPartBuilder that first generate a .g.dart containing our generated code, then run retrofit builder on this generated code and combine both outputs in a single .g.dart file ?
  2. When launching dart run build_runner build --delete-conflicting-outputs in local, a warning appears: Warning: Configuring `rpc_generator:rpcBuilder` in target `data:data` but this is not a known Builder. Yet, our files are generating correctly. However, when our CI launches the same command through GitHub Actions, the files are not generated. I do not understand why this warning is triggered and why the build_runner behavior changes from local to remote ?
  3. In our local build.yaml file, we HAVE to call the builder like this: rpc_generator:rpcBuilder:, otherwise the files are not generated if we only put rpc_generator:. From what I understood, if the builder has the same name as its package, we should be able to call rpc_generator: directly without having to specify the builder factory. Do you have an idea why this is happening?

Thanks in advance for your help πŸ™‚ I can provide more details if needed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions