Comment exécuter un générateur de code sur le dessus d'un autre générateur de code?

14

En utilisant la pile source_gen pour créer un générateur de code, comment puis-je créer un générateur qui génère du code qui serait l'entrée d'un autre générateur (plus spécifiquement json_serializable)?

Par exemple, considérez:

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

Ceci est un exemple de générateur de code qui génère un code qui doit ensuite être envoyé à json_serializable

Que puis-je faire pour json_serializablegénérer correctement ici?

Rémi Rousselet
la source
Je n'ai pas de réponse mais ce lien pourrait vous orienter dans la bonne direction? Ça m'intéresse aussi. J'avais mis ce lien en signet pour faire d'autres recherches
Frank Treacy
Je suis à mi-chemin pour comprendre le cas de votre question. pouvez-vous en dire plus? il y a deux façons de résoudre ce problème soit en appelant la méthode réelle qui génère le fichier de pièce de ce JSON, soit en utilisant une étape manuelle pour configurer et invoquer le générateur de pièces nous-mêmes. Il y a une troisième façon d'exécuter la commande en utilisant dart await Process.start('bash',arguments,runInShell: true);mais c'est une sorte de dernier recours à jouer. en fait, j'ai juste essayé toutes les logiques de génération de code il y a un jour sur ce lien repo donc .. Je pense que je peux être utile.
Parth Dave
Il s'agit de composer un générateur de code, de sorte que je puisse en écrire un qui dépend d'un autre. De cette façon, je n'aurai pas à bifurquer ses sources à des fins de maintenabilité.
Rémi Rousselet
L'étape de génération doit fonctionner dans un seul flutter generate/ pub run build_runner build. Sinon, ce serait très inhabituel à utiliser.
Rémi Rousselet

Réponses:

3

Consultez la documentation du fichier de configuration build.yaml pour plus d'informations, mais je pense que vous devriez utiliser le applies_buildersparamètre qui permet d'exécuter une autre génération après celle définie.

L'exemple montre un générateur qui génère des fichiers .tar.gz puis exécute une autre génération qui prend les fichiers .tar.gz en entrée

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

donc avec source_genvous devez implémenter pour votre build

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

et configurer l'autre constructeur

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
la source
Que dois-je transmettre dans la propriété [apply_builders]?
Pedro Massango
2

Ce n'est pas possible uniquement avec l'annotation car il y a peut-être deux packages qui ont tous les deux l' @JsonSerializableannotation

Il existe deux situtations:

  • Vous savez quels autres générateurs doivent fonctionner après votre générateur.


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

}
  • Vous ne savez pas quels autres générateurs devraient fonctionner après votre générateur.

Malheureusement, il n'existe actuellement aucun moyen de dire au source_gen que votre générateur peut produire un code qui nécessite une génération de code.

J'ai créé un problème ici https://github.com/dart-lang/source_gen/issues/442 si vous souhaitez vous abonner

Sahandevs
la source
-2

Vous pouvez décoder le JSON en appelant la jsonDecode()fonction, avec la chaîne JSON comme argument de méthode.

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

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

Maintenant, utilisez le User.fromJson()constructeur pour construire une nouvelle instance User à partir d'une structure de carte et d'une toJson()méthode, qui convertit une instance User en carte.

employé.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 est un générateur de code source automatisé qui génère pour vous le passe-partout de sérialisation JSON.

Vous avez besoin d'une dépendance régulière et de deux dépendances de développement à inclure json_serializabledans votre projet.

dependencies:
  json_annotation: ^0.2.3

dev_dependencies:
  build_runner: ^0.8.0
  json_serializable: ^0.5.0

Pour plus de détails sur la sérialisation JSON, vous pouvez vous référer ici

vous pouvez également utiliser la bibliothèque Smoke .

Il s'agit d'un sous-ensemble de la fonctionnalité Mirrors, mais il possède à la fois une implémentation basée sur Mirrors et basée sur Codegen. C'est écrit par l'équipe de PolymerDart, donc c'est aussi proche de "Officiel" que nous allons le faire.

Pendant le développement, il utilisera l'encodage / décodage basé sur les miroirs; mais pour la publication, vous pouvez créer un petit transformateur qui générera du code.

Seth Ladd a créé un exemple de code ici , que j'ai légèrement étendu pour prendre en charge les objets enfants:

Sreeram Nair
la source
Non, en fait, il crée son propre plugin build_runner et à partir duquel il doit exécuter un autre type de runner, comme l'empilement de build runner.
Parth Dave
C'est hors sujet. json_serializablen'est qu'un exemple et pourrait être n'importe quoi
Rémi Rousselet
je
donnais