Skip to content

[native_assets_cli] Make generated syntax files stand on their own #2102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions pkgs/json_syntax_generator/lib/src/generator/helper_library.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// Helper methods for the code generator that are added to the generated file.
///
/// This simplifies the code generator.
const helperLib = r'''
extension on Map<String, Object?> {
T get<T extends Object?>(String key) {
final value = this[key];
if (value is T) return value;
if (value == null) {
throw FormatException('No value was provided for required key: $key');
}
throw FormatException(
'Unexpected value \'$value\' for key \'.$key\'. '
'Expected a $T.',
);
}

List<T> list<T extends Object?>(String key) =>
_castList<T>(get<List<Object?>>(key), key);

List<T>? optionalList<T extends Object?>(String key) =>
switch (get<List<Object?>?>(key)?.cast<T>()) {
null => null,
final l => _castList<T>(l, key),
};

/// [List.cast] but with [FormatException]s.
static List<T> _castList<T extends Object?>(List<Object?> list, String key) {
for (final value in list) {
if (value is! T) {
throw FormatException(
'Unexpected value \'$list\' (${list.runtimeType}) for key \'.$key\'. '
'Expected a ${List<T>}.',
);
}
}
return list.cast();
}

Map<String, T> map$<T extends Object?>(String key) =>
_castMap<T>(get<Map<String, Object?>>(key), key);

Map<String, T>? optionalMap<T extends Object?>(String key) =>
switch (get<Map<String, Object?>?>(key)) {
null => null,
final m => _castMap<T>(m, key),
};

/// [Map.cast] but with [FormatException]s.
static Map<String, T> _castMap<T extends Object?>(
Map<String, Object?> map_,
String key,
) {
for (final value in map_.values) {
if (value is! T) {
throw FormatException(
'Unexpected value \'$map_\' (${map_.runtimeType}) for key \'.$key\'.'
'Expected a ${Map<String, T>}.',
);
}
}
return map_.cast();
}

List<String>? optionalStringList(String key) => optionalList<String>(key);

List<String> stringList(String key) => list<String>(key);

Uri path(String key) => _fileSystemPathToUri(get<String>(key));

Uri? optionalPath(String key) {
final value = get<String?>(key);
if (value == null) return null;
return _fileSystemPathToUri(value);
}

List<Uri>? optionalPathList(String key) {
final strings = optionalStringList(key);
if (strings == null) {
return null;
}
return [for (final string in strings) _fileSystemPathToUri(string)];
}

static Uri _fileSystemPathToUri(String path) {
if (path.endsWith(Platform.pathSeparator)) {
return Uri.directory(path);
}
return Uri.file(path);
}
}

extension on List<Uri> {
List<String> toJson() => [for (final uri in this) uri.toFilePath()];
}

extension <K extends Comparable<K>, V extends Object?> on Map<K, V> {
void sortOnKey() {
final result = <K, V>{};
final keysSorted = keys.toList()..sort();
for (final key in keysSorted) {
result[key] = this[key] as V;
}
clear();
addAll(result);
}
}
''';
19 changes: 12 additions & 7 deletions pkgs/json_syntax_generator/lib/src/generator/syntax_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import '../model/class_info.dart';
import '../model/dart_type.dart';
import '../model/property_info.dart';
import '../model/schema_info.dart';
import 'helper_library.dart';

/// Generates Dart code from a [SchemaInfo].
///
Expand Down Expand Up @@ -35,13 +36,17 @@ class SyntaxGenerator {

// This file is generated, do not edit.

import '../utils/json.dart';
// ignore_for_file: unused_element

import 'dart:io';
''');

for (final classInfo in schemaInfo.classes) {
buffer.writeln(_generateClass(classInfo));
}

buffer.writeln(helperLib);

return buffer.toString();
}

Expand Down Expand Up @@ -301,7 +306,7 @@ class $className {
case EnumClassInfo():
if (required) {
buffer.writeln('''
$dartType get $fieldName => $classType.fromJson( json.string('$jsonKey') );
$dartType get $fieldName => $classType.fromJson( json.get<String>('$jsonKey') );
''');
if (!property.isOverride) {
buffer.writeln('''
Expand All @@ -313,7 +318,7 @@ set $setterName($dartType value) {
} else {
buffer.writeln('''
$dartType get $fieldName {
final string = json.optionalString('$jsonKey');
final string = json.get<String?>('$jsonKey');
if(string == null) return null;
return $classType.fromJson(string);
}
Expand Down Expand Up @@ -384,7 +389,7 @@ set $setterName($dartType value) {
case 'String':
if (required) {
buffer.writeln('''
String get $fieldName => json.string('$jsonKey');
String get $fieldName => json.get<String>('$jsonKey');

set $setterName(String value) {
json['$jsonKey'] = value;
Expand All @@ -393,7 +398,7 @@ set $setterName(String value) {
''');
} else {
buffer.writeln('''
String? get $fieldName => json.optionalString('$jsonKey');
String? get $fieldName => json.get<String?>('$jsonKey');

set $setterName(String? value) {
if (value == null) {
Expand All @@ -415,7 +420,7 @@ set $setterName(int value) => json['$jsonKey'] = value;
''');
} else {
buffer.writeln('''
int? get $fieldName => json.getOptional<int>('$jsonKey');
int? get $fieldName => json.get<int?>('$jsonKey');

set $setterName(int? value) {
if (value == null) {
Expand All @@ -440,7 +445,7 @@ set $setterName(bool value) {
''');
} else {
buffer.writeln('''
bool? get $fieldName => json.getOptional<bool>('$jsonKey');
bool? get $fieldName => json.get<bool?>('$jsonKey');

set $setterName(bool? value) {
if (value == null) {
Expand Down
Loading