Come eseguire un generatore di codice sulla parte superiore di un altro generatore di codice?


14

Utilizzando lo stack source_gen per creare un generatore di codice, come posso creare un generatore che generi codice che sarebbe l'input di un altro generatore (più specificamente json_serializable)?

Ad esempio, considera:

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

Questo è un esempio di un generatore di codice a cui emette il codice che deve quindi essere inviato json_serializable

Cosa posso fare in modo che json_serializablevenga generato correttamente qui?


Non ho una risposta ma questo link potrebbe indicarti una buona direzione? Sono anche interessato. Avevo aggiunto quel link ai segnalibri per fare ulteriori ricerche
Frank Treacy,

Sono a metà strada per capire il caso della tua domanda. puoi approfondire di più? c'è un modo per risolverlo o chiamando il metodo effettivo che genera il file di parti di quel JSON o usando un passaggio manuale per configurare e invocare il costruttore di parti noi stessi. C'è un terzo modo per eseguire il comando usando dart await Process.start('bash',arguments,runInShell: true);ma è una specie di ultima risorsa da giocare. in realtà ho appena provato tutte le logiche di generazione del codice un giorno fa su questo collegamento repository quindi .. Penso di poter essere utile.
Parth Dave,

Si tratta di comporre un generatore di codice, in modo che io possa scriverne uno che dipende da un altro. In questo modo non dovrò sborsare le sue fonti a scopo di manutenibilità.
Rémi Rousselet,

Il passaggio di generazione deve funzionare in un unico flutter generate/ pub run build_runner build. Altrimenti sarebbe molto insolito da usare.
Rémi Rousselet,

Risposte:


3

Controlla la documentazione del file di configurazione build.yaml per ulteriori informazioni, ma penso che dovresti usare il applies_buildersparametro che consente di eseguire un'altra build dopo quella definita.

L'esempio mostra un builder che genera file .tar.gz e quindi esegue un'altra build che accetta i file .tar.gz come input

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

quindi con source_gente dovresti implementare per la tua build

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

e configurare l'altro 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"]

Cosa dovrei passare nella proprietà [apply_builders]?
Pedro Massango,

2

Non è possibile solo con l'annotazione perché forse ci sono due pacchetti che hanno entrambi l' @JsonSerializableannotazione

Esistono due situtations:

  • Sai quali altri generatori dovrebbero funzionare dopo il tuo generatore.


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

}
  • Non sai cosa dovrebbero funzionare altri generatori dopo il tuo generatore.

Sfortunatamente al momento non c'è modo di dire a source_gen che il tuo generatore potrebbe produrre un codice che necessita di generazione di codice.

Ho creato un problema qui https://github.com/dart-lang/source_gen/issues/442 se vuoi iscriverti


-2

È possibile decodificare JSON chiamando la jsonDecode()funzione, con la stringa JSON come argomento del metodo.

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

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

Ora, usa il User.fromJson()costruttore, per costruire una nuova istanza utente da una struttura di mappa e un toJson()metodo, che converte un'istanza utente in una mappa.

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 è un generatore di codice sorgente automatizzato che genera la piastra di caldaia di serializzazione JSON per te.

Hai bisogno di una dipendenza regolare e due dipendenze per gli sviluppatori da includere json_serializablenel tuo progetto.

dependencies:
  json_annotation: ^0.2.3

dev_dependencies:
  build_runner: ^0.8.0
  json_serializable: ^0.5.0

Per maggiori dettagli sulla serializzazione JSON è possibile fare riferimento qui

puoi anche usare la libreria Smoke .

È un sottoinsieme della funzionalità Mirrors ma ha un'implementazione basata su Mirrors e basata su Codegen. È stato scritto dal team PolymerDart, quindi è il più vicino possibile a "Ufficiale".

Durante lo sviluppo, utilizzerà la codifica / decodifica basata su mirror; ma per la pubblicazione puoi creare un piccolo trasformatore che genererà codice.

Seth Ladd ha creato qui un esempio di codice , che ho esteso leggermente per supportare gli oggetti figlio:


No, in realtà sta creando il suo plug-in build_runner e dal quale deve eseguire un altro tipo di runner come impilare il build runner.
Parth Dave,

Questo è fuori tema. json_serializableè solo un esempio e potrebbe essere qualsiasi cosa
Rémi Rousselet il

stavo solo facendo un esempio di come usare la biblioteca del fumo
Sreeram Nair il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.