Wie führe ich einen Codegenerator über einem anderen Codegenerator aus?

14

Wie kann ich mithilfe des Stacks source_gen einen Codegenerator erstellen, der Code generiert, der (genauer gesagt json_serializable) die Eingabe eines anderen Generators ist ?

Betrachten Sie zum Beispiel:

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

Dies ist ein Beispiel für einen Codegenerator, der Code ausgibt, an den dann gesendet werden muss json_serializable

Was kann ich tun, damit json_serializablehier richtig generiert wird?

Rémi Rousselet
quelle
Ich habe keine Antwort, aber dieser Link könnte Sie in eine gute Richtung weisen? Ich bin auch interessiert. Ich hatte diesen Link mit einem Lesezeichen versehen, um weitere Nachforschungen
anzustellen
Ich bin auf halbem Weg, um den Fall für Ihre Frage zu verstehen. Können Sie mehr ausarbeiten? Es gibt zwei Möglichkeiten, dies zu lösen, indem Sie entweder die eigentliche Methode aufrufen, die die Teiledatei dieses JSON ausgibt, oder indem Sie einen manuellen Schritt verwenden, um den Teileersteller selbst zu konfigurieren und aufzurufen. Es gibt eine dritte Möglichkeit, den Befehl mit Dart auszuführen, await Process.start('bash',arguments,runInShell: true);aber es ist eine Art letzter Ausweg. Eigentlich habe ich vor einem Tag alle Logiken zur Codegenerierung über diesen Repo- Link ausprobiert . Ich denke, ich kann hilfreich sein.
Parth Dave
Es geht darum, einen Codegenerator so zu komponieren, dass ich einen schreiben kann, der von einem anderen abhängt. Auf diese Weise muss ich die Quellen nicht aus Gründen der Wartbarkeit aufteilen.
Rémi Rousselet
Der Generierungsschritt muss in einem einzigen flutter generate/ funktionieren pub run build_runner build. Andernfalls wäre die Verwendung sehr ungewöhnlich.
Rémi Rousselet

Antworten:

3

Weitere Informationen finden Sie in der Dokumentation zur Konfigurationsdatei build.yaml. Sie sollten jedoch den applies_buildersParameter verwenden , mit dem ein weiterer Build nach dem definierten ausgeführt werden kann.

Das Beispiel zeigt einen Builder, der .tar.gz-Dateien generiert und dann einen anderen Build ausführt, der die .tar.gz-Dateien als Eingabe verwendet

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

Also mit source_gensollten Sie für Ihren Build implementieren

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

und konfigurieren Sie den anderen 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"]
Jamesblasco
quelle
Was soll ich in der Eigenschaft [apply_builders] übergeben?
Pedro Massango
2

Es ist nicht nur mit Annotation möglich, da es möglicherweise zwei Pakete gibt, die beide die @JsonSerializableAnnotation haben

Es gibt zwei Situationen:

  • Sie wissen, welche anderen Generatoren nach Ihrem Generator laufen sollen.


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

}
  • Sie wissen nicht, welche anderen Generatoren nach Ihrem Generator laufen sollen.

Leider gibt es derzeit keine Möglichkeit, source_gen mitzuteilen, dass Ihr Generator möglicherweise einen Code erzeugt, der Code generiert werden muss.

Ich habe hier ein Problem erstellt: https://github.com/dart-lang/source_gen/issues/442, wenn Sie sich anmelden möchten

Sahandevs
quelle
-2

Sie können JSON dekodieren, indem Sie die jsonDecode()Funktion mit der JSON-Zeichenfolge als Methodenargument aufrufen .

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

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

Verwenden Sie jetzt den User.fromJson()Konstruktor, um eine neue Benutzerinstanz aus einer Kartenstruktur und einer toJson()Methode zu erstellen, die eine Benutzerinstanz in eine Karte konvertiert.

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 ist ein automatisierter Quellcode-Generator, der das JSON-Serialisierungs-Boilerplate für Sie generiert.

Sie benötigen eine reguläre Abhängigkeit und zwei json_serializableEntwicklungsabhängigkeiten , um sie in Ihr Projekt aufzunehmen.

dependencies:
  json_annotation: ^0.2.3

dev_dependencies:
  build_runner: ^0.8.0
  json_serializable: ^0.5.0

Weitere Informationen zur JSON-Serialisierung finden Sie hier

Sie können auch die Rauchbibliothek verwenden.

Es ist eine Teilmenge der Mirrors-Funktionalität, verfügt jedoch sowohl über eine Mirrors-basierte als auch eine Codegen-basierte Implementierung. Es wurde vom PolymerDart-Team geschrieben und ist daher so nah wie möglich an "Official".

Während der Entwicklung wird die spiegelbasierte Codierung / Decodierung verwendet. Zum Veröffentlichen können Sie jedoch einen kleinen Transformator erstellen, der Code generiert.

Seth Ladd hat hier ein Codebeispiel erstellt , das ich leicht erweitert habe , um untergeordnete Objekte zu unterstützen:

Sreeram Nair
quelle
Nein, tatsächlich erstellt er sein eigenes build_runner-Plugin, von dem aus er einen anderen Runner ausführen muss, ähnlich wie das Stapeln von Build Runner.
Parth Dave
Dies ist nicht zum Thema. json_serializableist nur ein Beispiel und könnte alles sein
Rémi Rousselet
Ich gab nur ein Beispiel dafür, wie
Rauchbibliothek