¿Cómo ejecutar un generador de códigos en la parte superior de otro generador de códigos?

14

Usando la pila source_gen para hacer un generador de código, ¿cómo puedo hacer un generador que genere código que sería la entrada de otro generador (más específicamente json_serializable)?

Por ejemplo, considere:

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

Este es un ejemplo de un generador de código que genera un código que luego debe enviarse a json_serializable

¿Qué puedo hacer para que json_serializablese genere correctamente aquí?

Rémi Rousselet
fuente
No tengo una respuesta, pero este enlace podría indicarle una buena dirección. También estoy interesado Había marcado ese enlace para hacer más investigaciones
Frank Treacy,
Estoy a mitad de camino para entender el caso de su pregunta. ¿puedes elaborar más? hay dos maneras de resolver esto, ya sea llamando al método real que genera el archivo de parte de ese JSON o utilizando un paso manual para configurar e invocar el generador de partes nosotros mismos. Hay una tercera forma de ejecutar el comando usando el dardo, await Process.start('bash',arguments,runInShell: true);pero es un último recurso para jugar. En realidad, acabo de probar todas las lógicas de generación de código hace un día en este enlace de repositorio, así que ... creo que puedo ser útil.
Parth Dave
Se trata de componer un generador de código, de modo que pueda escribir uno que dependa de otro. De esta manera no tendré que bifurcar sus fuentes para fines de mantenimiento.
Rémi Rousselet
El paso de generación debe funcionar en un solo flutter generate/ pub run build_runner build. De lo contrario, sería muy inusual de usar.
Rémi Rousselet

Respuestas:

3

Consulte la documentación del archivo de configuración build.yaml para obtener más información, pero creo que debería usar el applies_buildersparámetro que permite ejecutar otra compilación después de la definida.

El ejemplo muestra un generador que genera archivos .tar.gz y luego ejecuta otra compilación que toma los archivos .tar.gz como entrada

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

así que con source_genusted debe implementar para su compilación

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

y configurar el otro constructor

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
fuente
¿Qué debo pasar en la propiedad [apply_builders]?
Pedro Massango
2

No es posible solo con la anotación porque puede haber dos paquetes que tienen la @JsonSerializableanotación

Hay dos situaciones:

  • Sabes qué otros generadores deberían funcionar después de tu generador.


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

}
  • No sabes qué otros generadores deberían funcionar después de tu generador.

Desafortunadamente, actualmente no hay forma de decirle a source_gen que su generador puede producir un código que necesita generación de código.

Creé un problema aquí https://github.com/dart-lang/source_gen/issues/442 si quieres suscribirte

Sahandevs
fuente
-2

Puede decodificar el JSON llamando a la jsonDecode()función, con la cadena JSON como argumento del método.

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

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

Ahora, use el User.fromJson()constructor, para construir una nueva instancia de Usuario a partir de una estructura de mapa y un toJson()método, que convierte una instancia de Usuario en un mapa.

empleado.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 es un generador de código fuente automatizado que genera la plantilla de serialización JSON para usted.

Necesita una dependencia regular y dos dependencias de desarrollo para incluir json_serializableen su proyecto.

dependencies:
  json_annotation: ^0.2.3

dev_dependencies:
  build_runner: ^0.8.0
  json_serializable: ^0.5.0

Para obtener más detalles sobre la serialización JSON, puede consultar aquí

También puede utilizar la biblioteca de humo .

Es un subconjunto de la funcionalidad Mirrors, pero tiene una implementación basada en Mirrors y Codegen. Está escrito por el equipo de PolymerDart, por lo que es lo más cercano a "Oficial" que vamos a obtener.

Durante el desarrollo, utilizará la codificación / decodificación basada en Mirrors; pero para publicar puedes crear un pequeño transformador que generará código.

Seth Ladd creó una muestra de código aquí , que extendí ligeramente para admitir objetos secundarios:

Sreeram Nair
fuente
No, en realidad está creando su propio plugin build_runner y desde el cual necesita ejecutar otro tipo de corredor, como apilarlo.
Parth Dave
Esto está fuera de tema. json_serializablees solo un ejemplo y podría ser cualquier cosa
Rémi Rousselet
Solo estaba dando un ejemplo de cómo se puede usar la biblioteca de humo
Sreeram Nair