Skip to content

Commit f2a9c14

Browse files
gRPC stub generation. (#79)
Added support for generating gRPC stubs. gRPC mode is selected by adding the option 'grpc' to the `--dart_out` argument, as in `--dart_out=grpc:<path>`. When gRPC mode is selected, the legacy ("generic") RPC stubs will not be emitted.
1 parent 2467861 commit f2a9c14

12 files changed

+611
-34
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## Unreleased
2+
3+
### gRPC support
4+
5+
* Added gRPC stub generation.
6+
* Updated descriptor.proto from google/protobuf v3.3.0.
7+
18
## 0.7.2 - 2017-06-12
29

310
* Added CHANGELOG.md

lib/code_generator.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class CodeGenerator extends ProtobufContainer {
5555
// (We may import it even if we don't generate the .pb.dart file.)
5656
List<FileGenerator> generators = <FileGenerator>[];
5757
for (FileDescriptorProto file in request.protoFile) {
58-
generators.add(new FileGenerator(file));
58+
generators.add(new FileGenerator(file, options));
5959
}
6060

6161
// Collect field types and importable files.

lib/file_generator.dart

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
part of protoc;
66

77
final _dartIdentifier = new RegExp(r'^\w+$');
8+
final _formatter = new DartFormatter();
89

910
/// Generates the Dart output files for one .proto input file.
1011
///
@@ -90,22 +91,23 @@ class FileGenerator extends ProtobufContainer {
9091
}
9192

9293
final FileDescriptorProto descriptor;
94+
final GenerationOptions options;
9395

9496
// The relative path used to import the .proto file, as a URI.
9597
final Uri protoFileUri;
9698

97-
final List<EnumGenerator> enumGenerators = <EnumGenerator>[];
98-
final List<MessageGenerator> messageGenerators = <MessageGenerator>[];
99-
final List<ExtensionGenerator> extensionGenerators = <ExtensionGenerator>[];
100-
final List<ClientApiGenerator> clientApiGenerators = <ClientApiGenerator>[];
101-
final List<ServiceGenerator> serviceGenerators = <ServiceGenerator>[];
99+
final enumGenerators = <EnumGenerator>[];
100+
final messageGenerators = <MessageGenerator>[];
101+
final extensionGenerators = <ExtensionGenerator>[];
102+
final clientApiGenerators = <ClientApiGenerator>[];
103+
final serviceGenerators = <ServiceGenerator>[];
104+
final grpcGenerators = <GrpcServiceGenerator>[];
102105

103106
/// True if cross-references have been resolved.
104107
bool _linked = false;
105108

106-
FileGenerator(FileDescriptorProto descriptor)
107-
: descriptor = descriptor,
108-
protoFileUri = new Uri.file(descriptor.name) {
109+
FileGenerator(this.descriptor, this.options)
110+
: protoFileUri = new Uri.file(descriptor.name) {
109111
if (protoFileUri.isAbsolute) {
110112
// protoc should never generate an import with an absolute path.
111113
throw "FAILURE: Import with absolute path is not supported";
@@ -133,9 +135,13 @@ class FileGenerator extends ProtobufContainer {
133135
extensionGenerators.add(new ExtensionGenerator(extension, this));
134136
}
135137
for (ServiceDescriptorProto service in descriptor.service) {
136-
var serviceGen = new ServiceGenerator(service, this);
137-
serviceGenerators.add(serviceGen);
138-
clientApiGenerators.add(new ClientApiGenerator(serviceGen));
138+
if (options.useGrpc) {
139+
grpcGenerators.add(new GrpcServiceGenerator(service, this));
140+
} else {
141+
var serviceGen = new ServiceGenerator(service, this);
142+
serviceGenerators.add(serviceGen);
143+
clientApiGenerators.add(new ClientApiGenerator(serviceGen));
144+
}
139145
}
140146
}
141147

@@ -178,12 +184,19 @@ class FileGenerator extends ProtobufContainer {
178184
..content = content;
179185
}
180186

181-
return [
187+
final files = [
182188
makeFile(".pb.dart", generateMainFile(config)),
183189
makeFile(".pbenum.dart", generateEnumFile(config)),
184-
makeFile(".pbserver.dart", generateServerFile(config)),
185190
makeFile(".pbjson.dart", generateJsonFile(config)),
186191
];
192+
if (options.useGrpc) {
193+
if (grpcGenerators.isNotEmpty) {
194+
files.add(makeFile(".pbgrpc.dart", generateGrpcFile(config)));
195+
}
196+
} else {
197+
files.add(makeFile(".pbserver.dart", generateServerFile(config)));
198+
}
199+
return files;
187200
}
188201

189202
/// Returns the contents of the .pb.dart file for this .proto file.
@@ -417,6 +430,40 @@ import 'package:protobuf/protobuf.dart';
417430
return out.toString();
418431
}
419432

433+
/// Returns the contents of the .pbgrpc.dart file for this .proto file.
434+
String generateGrpcFile(
435+
[OutputConfiguration config = const DefaultOutputConfiguration()]) {
436+
if (!_linked) throw new StateError("not linked");
437+
var out = new IndentingWriter();
438+
_writeLibraryHeading(out, "pbgrpc");
439+
440+
out.println('''
441+
import 'dart:async';
442+
443+
import 'package:grpc/grpc.dart';
444+
''');
445+
446+
// Import .pb.dart files needed for requests and responses.
447+
var imports = new Set<FileGenerator>();
448+
for (var generator in grpcGenerators) {
449+
generator.addImportsTo(imports);
450+
}
451+
for (var target in imports) {
452+
_writeImport(out, config, target, ".pb.dart");
453+
}
454+
455+
var resolvedImport =
456+
config.resolveImport(protoFileUri, protoFileUri, ".pb.dart");
457+
out.println("export '$resolvedImport';");
458+
out.println();
459+
460+
for (var generator in grpcGenerators) {
461+
generator.generate(out);
462+
}
463+
464+
return _formatter.format(out.toString());
465+
}
466+
420467
/// Returns the contents of the .pbjson.dart file for this .proto file.
421468
String generateJsonFile(
422469
[OutputConfiguration config = const DefaultOutputConfiguration()]) {

0 commit comments

Comments
 (0)