Як запустити генератор коду у верхній частині іншого генератора коду?


14

Використовуючи стек source_gen для створення генератора коду, як я можу зробити генератор, який генерує код, який був би входом іншого генератора (точніше json_serializable)?

Наприклад, врахуйте:

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

Це приклад генератора коду, який виводить код, який потім потрібно надіслати json_serializable

Що я можу зробити, щоб json_serializableтут генерувались правильно?


Я не маю відповіді, але це посилання може вказувати на вас у хорошому напрямку? Мені теж цікаво. Я зробив закладку цього посилання для подальшого дослідження
Френк

Я на півдорозі, щоб зрозуміти справу вашого питання. Ви можете детальніше розробити? Є два способи вирішити це або за допомогою виклику фактичного методу, який видає файл частини цього JSON, або за допомогою кроку вручну для налаштування та виклику конструктора частин. Існує третій спосіб запустити команду за допомогою dart, await Process.start('bash',arguments,runInShell: true);але це начебто в крайньому випадку. насправді я просто спробував усі логіки генерування коду один день тому на цьому посиланні на репо, так що ... я думаю, я можу бути корисним.
Parth Dave

Йдеться про створення генератора коду таким чином, що я можу записати той, який залежить від іншого. Таким чином, мені не доведеться роздрібнювати його джерела з метою ремонту.
Ремі Русселет

Крок генерації повинен працювати в єдиному flutter generate/ pub run build_runner build. Інакше це було б дуже незвично у використанні.
Ремі Русселет

Відповіді:


3

Перевірте документацію конфігураційного файлу build.yaml для отримання додаткової інформації, але я думаю, ви повинні використовувати applies_buildersпарам, який дозволяє виконати іншу збірку після визначеної.

У прикладі показаний конструктор, який генерує файли .tar.gz, а потім виконує іншу збірку, яка приймає файли .tar.gz як вхід

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

тож з source_genвами слід реалізувати для своєї збірки

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

і налаштувати інший конструктор

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

Що мені потрібно передати у властивості [apply_builders]?
Педро Массанго

2

Це неможливо лише з анотацією, оскільки може бути два пакети, на яких обоє мають @JsonSerializableанотацію

Є дві ситуації:

  • Ви знаєте, які інші генератори повинні працювати після вашого генератора.

    • https://stackoverflow.com/a/59605830/6877472 - одне з рішень
    • ви можете використовувати код іншого генератора у власному генераторі та викликати функцію генератора. приклад коду:

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

}
  • Ви не знаєте, які інші генератори повинні працювати після вашого генератора.

На жаль, наразі немає можливості сказати source_gen, що ваш генератор може створити код, який потребує генерації коду.

Я створив тут проблему https://github.com/dart-lang/source_gen/isissue/442, якщо ви хочете підписатися


-2

Ви можете розшифрувати JSON, зателефонувавши до jsonDecode()функції, при цьому аргумент методу має рядок JSON.

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

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

Тепер використовуйте User.fromJson()конструктор для побудови нового екземпляра користувача зі структури карти та toJson()методу, який перетворює примірник користувача у карту.

співробітник.дарт

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 - це автоматизований генератор вихідного коду, який генерує для вас котло для серіалізації JSON.

Вам потрібна одна регулярна залежність і дві залежності від розробників, які потрібно включити json_serializableу ваш проект.

dependencies:
  json_annotation: ^0.2.3

dev_dependencies:
  build_runner: ^0.8.0
  json_serializable: ^0.5.0

Більш детальну інформацію про серіалізацію JSON можна переглянути тут

ви також можете використовувати бібліотеку Smoke .

Це підмножина функцій дзеркал, але має як на основі дзеркал, так і на основі Codegen. Це написано командою PolymerDart, тож воно наближене до "Офіційного", як ми збираємось отримати.

Під час розробки він використовуватиме кодування / декодування на основі дзеркал; але для публікації ви можете створити невеликий трансформатор, який створить код.

Сет Ладд створив тут зразок коду , який я трохи розширив, щоб підтримати дочірні об’єкти:


Насправді він не створює власний плагін build_runner і з якого йому потрібно запустити інший тип бігуна, як, наприклад, укладання бігуна збірки.
Parth Dave

Це поза темою. json_serializableце лише приклад і може бути чим завгодно
Ремі Русселет

Я тільки давав приклад того, як можна використовувати бібліотеку диму
Sreeram Nair
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.