Skip to content

Commit b51036a

Browse files
authored
[pub_formats] Make nullable params optional (#2459)
For the generated syntax inside `package:hooks`, `code_assets`, and `data_assets` all nullable parameters are `required`. This is to help us ensure that we don't forget a param in the semantic API. (The generated syntax is wrapped with an API handcrafted to be nice for our users.) However, in `package:pub_formats` we don't have a semantic API wrapping the syntax, we directly use the syntax classes in `dartdev` and friends. In such case it's unwanted to have to provide every param. (For example when constructing a `pubspec.yaml` we want to omit all the optional sections.) So, we add a param to the generator to control this.
1 parent bac30b1 commit b51036a

File tree

6 files changed

+55
-26
lines changed

6 files changed

+55
-26
lines changed

pkgs/hooks/tool/generate_syntax.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ void main(List<String> args) {
9090

9191
final output = SyntaxGenerator(
9292
analyzedSchema,
93+
requireNullableParameters: true,
9394
header:
9495
'''
9596
// This file is generated, do not edit.

pkgs/json_syntax_generator/lib/src/generator/normal_class_generator.dart

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ import 'property_generator.dart';
99
class ClassGenerator {
1010
final NormalClassInfo classInfo;
1111

12-
ClassGenerator(this.classInfo);
12+
/// If true, also generate `required` named parameters for nullable fields.
13+
///
14+
/// This is useful for ensuring that all fields are set when writing a
15+
/// semantic Dart API that wraps a generated syntax.
16+
final bool requireNullableParameters;
17+
18+
ClassGenerator(this.classInfo, {required this.requireNullableParameters});
1319

1420
String generate() {
1521
final buffer = StringBuffer();
@@ -143,6 +149,11 @@ static const ${tagProperty}Value = '$tagValue';
143149
for (final propertyName in propertyNames) {
144150
final superClassProperty = superclass?.getProperty(propertyName);
145151
final thisClassProperty = classInfo.getProperty(propertyName);
152+
final required =
153+
!(thisClassProperty ?? superClassProperty)!.type.isNullable ||
154+
requireNullableParameters
155+
? 'required'
156+
: '';
146157

147158
if (superClassProperty != null) {
148159
if (propertyName != classInfo.superclass?.taggedUnionProperty) {
@@ -152,17 +163,17 @@ static const ${tagProperty}Value = '$tagValue';
152163
// Must be passed to super constructor call.
153164
final dartType = thisClassProperty.type;
154165
final propertyName = thisClassProperty.name;
155-
result.add('required $dartType $propertyName');
166+
result.add('$required $dartType $propertyName');
156167
} else {
157168
// Same type on this class, emit super parameter.
158169
final propertyName = superClassProperty.name;
159-
result.add('required super.$propertyName');
170+
result.add('$required super.$propertyName');
160171
}
161172
}
162173
} else {
163174
final dartType = thisClassProperty!.type;
164175
final propertyName = thisClassProperty.name;
165-
result.add('required $dartType $propertyName');
176+
result.add('$required $dartType $propertyName');
166177
}
167178
}
168179
result.add('super.path = const []');

pkgs/json_syntax_generator/lib/src/generator/syntax_generator.dart

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,21 @@ import 'normal_class_generator.dart';
1212
class SyntaxGenerator {
1313
final SchemaInfo schemaInfo;
1414

15+
/// If `true`, also generate `required` named parameters for nullable fields.
16+
///
17+
/// This is useful for ensuring that all fields are set when writing a
18+
/// semantic Dart API that wraps a generated syntax.
19+
///
20+
/// If the generated syntax is used directly, prefer `false`.
21+
final bool requireNullableParameters;
22+
1523
final String header;
1624

17-
SyntaxGenerator(this.schemaInfo, {this.header = ''});
25+
SyntaxGenerator(
26+
this.schemaInfo, {
27+
this.header = '',
28+
this.requireNullableParameters = false,
29+
});
1830

1931
String generate() {
2032
final buffer = StringBuffer();
@@ -34,7 +46,12 @@ import 'dart:io';
3446
for (final classInfo in schemaInfo.classes) {
3547
switch (classInfo) {
3648
case NormalClassInfo():
37-
buffer.writeln(ClassGenerator(classInfo).generate());
49+
buffer.writeln(
50+
ClassGenerator(
51+
classInfo,
52+
requireNullableParameters: requireNullableParameters,
53+
).generate(),
54+
);
3855
case EnumClassInfo():
3956
buffer.writeln(EnumGenerator(classInfo).generate());
4057
}

pkgs/pub_formats/lib/src/package_graph_syntax.g.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class GraphPackageSyntax extends JsonObjectSyntax {
1616

1717
GraphPackageSyntax({
1818
required List<String> dependencies,
19-
required List<String>? devDependencies,
19+
List<String>? devDependencies,
2020
required String name,
2121
required String version,
2222
super.path = const [],
@@ -90,7 +90,7 @@ class PackageGraphFileSyntax extends JsonObjectSyntax {
9090
: super.fromJson();
9191

9292
PackageGraphFileSyntax({
93-
required int? configVersion,
93+
int? configVersion,
9494
required List<GraphPackageSyntax> packages,
9595
required List<String> roots,
9696
super.path = const [],

pkgs/pub_formats/lib/src/pubspec_lock_syntax.g.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ class PubspecLockFileSyntax extends JsonObjectSyntax {
407407
: super.fromJson();
408408

409409
PubspecLockFileSyntax({
410-
required Map<String, PackageSyntax>? packages,
410+
Map<String, PackageSyntax>? packages,
411411
required SDKsSyntax sdks,
412412
super.path = const [],
413413
}) : super() {

pkgs/pub_formats/lib/src/pubspec_syntax.g.dart

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class EnvironmentSyntax extends JsonObjectSyntax {
2828
: super.fromJson();
2929

3030
EnvironmentSyntax({
31-
required String? flutter,
31+
String? flutter,
3232
required String sdk,
3333
super.path = const [],
3434
}) : super() {
@@ -68,8 +68,8 @@ class GitSyntax extends JsonObjectSyntax {
6868
GitSyntax.fromJson(super.json, {super.path = const []}) : super.fromJson();
6969

7070
GitSyntax({
71-
required String? path$,
72-
required String? ref,
71+
String? path$,
72+
String? ref,
7373
required String url,
7474
super.path = const [],
7575
}) : super() {
@@ -160,7 +160,7 @@ class HooksSyntax extends JsonObjectSyntax {
160160
HooksSyntax.fromJson(super.json, {super.path = const []}) : super.fromJson();
161161

162162
HooksSyntax({
163-
required Map<String, Map<String, Object?>>? userDefines,
163+
Map<String, Map<String, Object?>>? userDefines,
164164
super.path = const [],
165165
}) : super() {
166166
_userDefines = userDefines;
@@ -198,7 +198,7 @@ class HostedDependencySourceSyntax extends DependencySourceSyntax {
198198
: super.fromJson();
199199

200200
HostedDependencySourceSyntax({
201-
required String? hosted,
201+
String? hosted,
202202
required String version,
203203
super.path = const [],
204204
}) : super() {
@@ -279,20 +279,20 @@ class PubspecYamlFileSyntax extends JsonObjectSyntax {
279279
: super.fromJson();
280280

281281
PubspecYamlFileSyntax({
282-
required Map<String, DependencySourceSyntax>? dependencies,
283-
required Map<String, DependencySourceSyntax>? dependencyOverrides,
284-
required String? description,
285-
required Map<String, DependencySourceSyntax>? devDependencies,
286-
required String? documentation,
282+
Map<String, DependencySourceSyntax>? dependencies,
283+
Map<String, DependencySourceSyntax>? dependencyOverrides,
284+
String? description,
285+
Map<String, DependencySourceSyntax>? devDependencies,
286+
String? documentation,
287287
required EnvironmentSyntax environment,
288-
required Map<String, String?>? executables,
289-
required String? homepage,
290-
required HooksSyntax? hooks,
291-
required String? issueTracker,
288+
Map<String, String?>? executables,
289+
String? homepage,
290+
HooksSyntax? hooks,
291+
String? issueTracker,
292292
required String name,
293-
required String? publishTo,
294-
required String? repository,
295-
required String? version,
293+
String? publishTo,
294+
String? repository,
295+
String? version,
296296
super.path = const [],
297297
}) : super() {
298298
this.dependencies = dependencies;

0 commit comments

Comments
 (0)