Как запустить генератор кода поверх другого генератора кода?

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, либо вручную выполнить настройку и вызвать конструктор деталей. Существует третий способ запуска команды с помощью дротика, 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"]
jamesblasco
источник
Что я должен передать в свойстве [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/issues/442, если вы хотите подписаться

Sahandevs
источник
-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()метод, который преобразует экземпляр пользователя в карту.

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 это автоматический генератор исходного кода, который генерирует шаблон сериализации JSON для вас.

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

dependencies:
  json_annotation: ^0.2.3

dev_dependencies:
  build_runner: ^0.8.0
  json_serializable: ^0.5.0

Более подробную информацию о сериализации JSON вы можете найти здесь

Вы также можете использовать библиотеку Smoke .

Это подмножество функций Mirrors, но имеет реализацию на основе Mirrors и Codegen. Он написан командой PolymerDart, поэтому он настолько близок к «Официальному», насколько мы собираемся получить.

При разработке будет использоваться кодировка / декодирование на основе зеркал; но для публикации вы можете создать небольшой преобразователь, который будет генерировать код.

Сет Лэдд создал здесь пример кода , который я немного расширил для поддержки дочерних объектов:

Срирам Наир
источник
Нет, на самом деле он создает свой собственный плагин build_runner, из которого ему нужно запустить другой бегун, вроде стекирования бегуна.
Парт Дэйв
Это не по теме. json_serializableэто просто пример и может быть чем угодно
Rémi Rousselet
я просто привел пример того, как можно использовать библиотеку дыма
приводил