Como executar um gerador de código na parte superior de outro gerador de código?


14

Usando a pilha source_gen para criar um gerador de código, como posso criar um gerador que gere código que seria a entrada de outro gerador (mais especificamente json_serializable)?

Por exemplo, considere:

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);
}
''';
  }
}

Este é um exemplo de um gerador de código que gera o código que precisa ser enviado para json_serializable

O que posso fazer para que seja json_serializablegerado corretamente aqui?


Não tenho uma resposta, mas esse link pode indicar uma boa direção? Eu também estou interessado. Eu tinha marcado esse link para fazer pesquisas adicionais
— Frank Treacy

Estou no meio do caminho para entender o caso da sua pergunta. você pode elaborar mais? há duas maneiras de resolver isso, chamando o método real que gera o arquivo de peça desse JSON ou usando uma etapa manual para configurar e chamar nosso construtor de peças. Existe uma terceira maneira de executar o comando usando dardo, await Process.start('bash',arguments,runInShell: true);mas é o último recurso para jogar. na verdade, eu tentei todas as lógicas de geração de código um dia atrás neste link de repo, então acho que posso ser útil.
— Parth Dave

É sobre compor um gerador de código, para que eu possa escrever um que dependa de outro. Dessa forma, não precisarei usar suas fontes para fins de manutenção.
— Rémi Rousselet

A etapa de geração deve funcionar em um único flutter generate/ pub run build_runner build. Caso contrário, seria muito incomum de usar.
— Rémi Rousselet

Respostas:


3

Verifique a documentação do arquivo de configuração build.yaml para obter mais informações, mas acho que você deve usar o applies_buildersparâmetro que permite executar outra compilação após a definida.

O exemplo mostra um construtor que gera arquivos .tar.gz e, em seguida, executa outra construção que usa os arquivos .tar.gz como entrada

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"]

então com source_genvocê deve implementar para sua compilação

applies_builders: ["source_gen|combining_builder", "json_serializable"]

e configure o outro construtor

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"]

O que devo passar na propriedade [apply_builders]?
— Pedro Massango 19/03

2

Não é possível apenas com anotação, porque talvez haja dois pacotes que tenham a @JsonSerializableanotação

Existem duas situações:

  • Você sabe o que outros geradores devem executar após o seu gerador.


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);
          }
        ''');
     }

}
  • Você não sabe o que outros geradores devem executar após o seu gerador.

Infelizmente, atualmente não há como dizer ao source_gen que seu gerador pode produzir um código que precisa de geração de código.

Criei um problema aqui https://github.com/dart-lang/source_gen/issues/442 se você deseja se inscrever


-2

Você pode decodificar o JSON chamando a jsonDecode()função, com a cadeia JSON como argumento do método.

Map<String, dynamic> user = jsonDecode(jsonString);

print('Howdy, ${user['name']}!');
print('We sent the verification link to ${user['email']}.');

Agora, use o User.fromJson()construtor, para construir uma nova instância de Usuário a partir de uma estrutura de mapa e um toJson()método, que converte uma instância de Usuário em um mapa.

employee.dart

class Employee {
  final String name;
  final String id;

  Employee(this.name, this.id);

  Employee.fromJson(Map<String, dynamic> json)
      : name = json['name'],
        id = json['id'];

  Map<String, dynamic> toJson() =>
    {
      'name': name,
      'id': id,
    };
}

json_serializable é um gerador de código-fonte automatizado que gera o padrão da serialização JSON para você.

Você precisa de uma dependência regular e duas dependências de desenvolvimento para incluir json_serializableno seu projeto.

dependencies:
  json_annotation: ^0.2.3

dev_dependencies:
  build_runner: ^0.8.0
  json_serializable: ^0.5.0

Para mais detalhes sobre serialização JSON, você pode consultar aqui

você também pode usar a biblioteca Smoke .

É um subconjunto da funcionalidade Mirrors, mas tem uma implementação baseada em Mirrors e em Codegen. É escrito pela equipe PolymerDart, portanto é o mais próximo de "Oficial" que vamos chegar.

Durante o desenvolvimento, ele usará a codificação / decodificação baseada em Mirrors; mas para publicar, você pode criar um pequeno transformador que irá gerar código.

Seth Ladd criou um exemplo de código aqui , que estendi um pouco para oferecer suporte a objetos filho:


Não, na verdade ele está criando seu próprio plug-in build_runner e do qual precisa executar outro runner, como o empilhamento do build runner.
— Parth Dave

Isso é fora de tópico. json_serializableé apenas um exemplo e pode ser qualquer coisa
— Rémi Rousselet

Eu estava apenas dando um exemplo de como a biblioteca de fumaça pode ser usada.
— Sreeram Nair 04/01
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.