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?

Rémi Rousselet
fonte
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"]
jamesblasco
fonte
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

Sahandevs
fonte
-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:

Sreeram Nair
fonte
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