Jak uruchomić generator kodu na innym generatorze kodu?

14

Używając stosu source_gen do stworzenia generatora kodu, jak mogę stworzyć generator, który generuje kod, który byłby wejściem innego generatora (a dokładniej json_serializable)?

Rozważ na przykład:

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

To jest przykład generatora kodu, który generuje kod wyjściowy, który należy następnie wysłać json_serializable

Co mogę zrobić, aby json_serializablepoprawnie generować tutaj?

Rémi Rousselet
źródło
Nie mam odpowiedzi, ale ten link może skierować Cię w dobrym kierunku? Jestem również zainteresowany. Dodałem do zakładek ten link do dalszych badań
Frank Treacy,
Jestem w połowie drogi, aby zrozumieć argument na twoje pytanie. czy możesz rozwinąć więcej? można to rozwiązać na dwa sposoby albo przez wywołanie rzeczywistej metody, która wyprowadza plik części tego JSON, albo przez wykonanie ręcznego kroku w celu skonfigurowania i wywołania naszego konstruktora części. Istnieje trzeci sposób uruchomienia polecenia za pomocą strzałki, await Process.start('bash',arguments,runInShell: true);ale jest to rodzaj ostateczności. właściwie próbowałem już całą logikę generowania kodu jeden dzień temu na tym linku repo, więc .. Myślę, że mogę być pomocny.
Parth Dave
Chodzi o skomponowanie generatora kodu, tak że mogę napisać taki, który zależy od innego. W ten sposób nie będę musiał rozwidlać źródeł w celu utrzymania.
Rémi Rousselet
Etap generowania musi działać pojedynczo flutter generate/ pub run build_runner build. W przeciwnym razie użycie tego byłoby bardzo nietypowe.
Rémi Rousselet

Odpowiedzi:

3

Sprawdź dokumentację pliku konfiguracyjnego build.yaml, aby uzyskać więcej informacji, ale myślę, że powinieneś użyć applies_buildersparametru, który pozwala wykonać inną kompilację po zdefiniowanej.

Przykład pokazuje program budujący, który generuje pliki .tar.gz, a następnie wykonuje inną kompilację, która przyjmuje pliki .tar.gz jako dane wejściowe

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

więc source_genpowinieneś wdrożyć dla swojej kompilacji

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

i skonfiguruj drugiego konstruktora

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
źródło
Co powinienem przekazać we właściwości [Apply_builders]?
Pedro Massango
2

Nie jest to możliwe tylko z adnotacją, ponieważ może dwa pakiety mają @JsonSerializableadnotację

Istnieją dwie situtacje:

  • Wiesz, jakie inne generatory powinny działać za twoim generatorem.


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

}
  • Nie wiesz, jakie inne generatory powinny działać za twoim generatorem.

Niestety obecnie nie ma sposobu, aby powiedzieć źródłowemu genowi, że Twój generator może wygenerować kod, który wymaga wygenerowania kodu.

Stworzyłem tutaj problem https://github.com/dart-lang/source_gen/issues/442, jeśli chcesz subskrybować

Sahandevs
źródło
-2

Możesz zdekodować JSON, wywołując jsonDecode()funkcję, z łańcuchem JSON jako argumentem metody.

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

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

Teraz użyj User.fromJson()konstruktora do skonstruowania nowej instancji użytkownika ze struktury mapy i toJson()metody, która konwertuje instancję użytkownika w mapę.

pracownik.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 jest zautomatyzowanym generatorem kodu źródłowego, który generuje dla Ciebie szablon szeregowania JSON.

Potrzebujesz jednej regularnej zależności i dwóch zależności deweloperskich, które chcesz uwzględnić json_serializablew swoim projekcie.

dependencies:
  json_annotation: ^0.2.3

dev_dependencies:
  build_runner: ^0.8.0
  json_serializable: ^0.5.0

Więcej informacji na temat serializacji JSON można znaleźć tutaj

możesz także skorzystać z biblioteki Smoke .

Jest to podzbiór funkcji Mirrors, ale ma zarówno implementację opartą na Mirrors, jak i opartą na Codegen. Jest napisany przez zespół PolymerDart, więc jest tak zbliżony do „Official”, jak to tylko możliwe.

Podczas opracowywania będzie korzystał z kodowania / dekodowania opartego na lustrach; ale do publikacji możesz stworzyć mały transformator, który wygeneruje kod.

Seth Ladd utworzył tutaj przykładowy kod , który nieco rozszerzyłem, aby obsługiwał obiekty potomne:

Sreeram Nair
źródło
Nie, tak naprawdę tworzy własną wtyczkę build_runner, z której musi uruchomić inny rodzaj biegacza, taki jak układanie runnera.
Parth Dave
To jest nie na temat. json_serializablejest tylko przykładem i może być czymkolwiek
Rémi Rousselet
Dałem