Skip to content

Commit

Permalink
Add a flag to generate constructor arguments
Browse files Browse the repository at this point in the history
Fixes google#850.
  • Loading branch information
osa1 committed Jun 27, 2023
1 parent 2996e1d commit fc7b5a8
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 5 deletions.
12 changes: 12 additions & 0 deletions protoc_plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## 21.0.3

* New protoc_plugin flag `generate_constructor_arguments` added to bring back
the old message factory methods with arguments. These arguments were removed
in 21.0.0 ([#703]) as they caused bloat in generated binaries in some cases.

Example usage:

```
protoc --dart_out='generate_constructor_arguments,<other options>:.' ...
```

## 21.0.2

* Fix missing protobuf import in generated grpc files. ([#844])
Expand Down
3 changes: 3 additions & 0 deletions protoc_plugin/lib/src/base_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class BaseType {
String getRepeatedDartType(FileGenerator fileGen) =>
'$coreImportPrefix.List<${getDartType(fileGen)}>';

String getRepeatedDartTypeIterable(FileGenerator fileGen) =>
'$coreImportPrefix.Iterable<${getDartType(fileGen)}>';

factory BaseType(FieldDescriptorProto field, GenerationContext ctx) {
String constSuffix;

Expand Down
48 changes: 47 additions & 1 deletion protoc_plugin/lib/src/message_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,8 @@ class MessageGenerator extends ProtobufContainer {
NamedLocation(
name: classname, fieldPathSegment: fieldPath, start: 'class '.length)
], () {
out.println('factory $classname() => create();');
_generateFactory(out);

out.printlnAnnotated('$classname._() : super();', [
NamedLocation(name: classname, fieldPathSegment: fieldPath, start: 0)
]);
Expand Down Expand Up @@ -424,6 +425,51 @@ class MessageGenerator extends ProtobufContainer {
out.println();
}

void _generateFactory(IndentingWriter out) {
if (fileGen.options.generateConstructorArguments) {
out.print('factory $classname(');
if (_fieldList.isNotEmpty) {
out.println('{');
for (final field in _fieldList) {
_emitDeprecatedIf(field.isDeprecated, out);
if (field.isRepeated && !field.isMapField) {
out.println(
' ${field.baseType.getRepeatedDartTypeIterable(fileGen)}? ${field.memberNames!.fieldName},');
} else {
out.println(
' ${field.getDartType()}? ${field.memberNames!.fieldName},');
}
}
out.print('}');
}
if (_fieldList.isNotEmpty) {
out.println(') {');
out.println(' final _result = create();');
for (final field in _fieldList) {
out.println(' if (${field.memberNames!.fieldName} != null) {');
if (field.isDeprecated) {
out.println(
' // ignore: deprecated_member_use_from_same_package');
}
if (field.isRepeated || field.isMapField) {
out.println(
' _result.${field.memberNames!.fieldName}.addAll(${field.memberNames!.fieldName});');
} else {
out.println(
' _result.${field.memberNames!.fieldName} = ${field.memberNames!.fieldName};');
}
out.println(' }');
}
out.println(' return _result;');
out.println('}');
} else {
out.println(') => create();');
}
} else {
out.println('factory $classname() => create();');
}
}

// Returns true if the message type has any required fields. If it doesn't,
// we can optimize out calls to its isInitialized()/_findInvalidFields()
// methods.
Expand Down
32 changes: 29 additions & 3 deletions protoc_plugin/lib/src/options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,12 @@ bool genericOptionsParser(CodeGeneratorRequest request,
class GenerationOptions {
final bool useGrpc;
final bool generateMetadata;
final bool generateConstructorArguments;

GenerationOptions({this.useGrpc = false, this.generateMetadata = false});
GenerationOptions(
{this.useGrpc = false,
this.generateMetadata = false,
this.generateConstructorArguments = false});
}

/// A parser for a name-value pair option. Options parsed in
Expand Down Expand Up @@ -84,13 +88,27 @@ class GenerateMetadataParser implements SingleOptionParser {
@override
void parse(String name, String? value, OnError onError) {
if (value != null) {
onError('Invalid metadata option. No value expected.');
onError('Invalid generate_kythe_info option. No value expected.');
return;
}
generateKytheInfo = true;
}
}

class GenerateConstructorArgumentsParser implements SingleOptionParser {
bool generateConstructorArguments = false;

@override
void parse(String name, String? value, OnError onError) {
if (value != null) {
onError(
'Invalid generate_constructor_arguments option. No value expected.');
return;
}
generateConstructorArguments = true;
}
}

/// Parser used by the compiler, which supports the `rpc` option (see
/// [GrpcOptionParser]) and any additional option added in [parsers]. If
/// [parsers] has a key for `rpc`, it will be ignored.
Expand All @@ -102,13 +120,21 @@ GenerationOptions? parseGenerationOptions(

final grpcOptionParser = GrpcOptionParser();
newParsers['grpc'] = grpcOptionParser;

final generateMetadataParser = GenerateMetadataParser();
newParsers['generate_kythe_info'] = generateMetadataParser;

final generateConstructorArgumentsParser =
GenerateConstructorArgumentsParser();
newParsers['generate_constructor_arguments'] =
generateConstructorArgumentsParser;

if (genericOptionsParser(request, response, newParsers)) {
return GenerationOptions(
useGrpc: grpcOptionParser.grpcEnabled,
generateMetadata: generateMetadataParser.generateKytheInfo);
generateMetadata: generateMetadataParser.generateKytheInfo,
generateConstructorArguments:
generateConstructorArgumentsParser.generateConstructorArguments);
}
return null;
}
2 changes: 1 addition & 1 deletion protoc_plugin/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: protoc_plugin
version: 21.0.2
version: 21.0.3
description: A protobuf protoc compiler plugin used to generate Dart code.
repository: https://github.com/google/protobuf.dart/tree/master/protoc_plugin

Expand Down

0 comments on commit fc7b5a8

Please sign in to comment.