-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
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.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
part of protoc; | ||
|
||
final _dartIdentifier = new RegExp(r'^\w+$'); | ||
final _formatter = new DartFormatter(); | ||
|
||
/// Generates the Dart output files for one .proto input file. | ||
/// | ||
|
@@ -90,22 +91,23 @@ class FileGenerator extends ProtobufContainer { | |
} | ||
|
||
final FileDescriptorProto descriptor; | ||
final GenerationOptions options; | ||
|
||
// The relative path used to import the .proto file, as a URI. | ||
final Uri protoFileUri; | ||
|
||
final List<EnumGenerator> enumGenerators = <EnumGenerator>[]; | ||
final List<MessageGenerator> messageGenerators = <MessageGenerator>[]; | ||
final List<ExtensionGenerator> extensionGenerators = <ExtensionGenerator>[]; | ||
final List<ClientApiGenerator> clientApiGenerators = <ClientApiGenerator>[]; | ||
final List<ServiceGenerator> serviceGenerators = <ServiceGenerator>[]; | ||
final enumGenerators = <EnumGenerator>[]; | ||
final messageGenerators = <MessageGenerator>[]; | ||
final extensionGenerators = <ExtensionGenerator>[]; | ||
final clientApiGenerators = <ClientApiGenerator>[]; | ||
final serviceGenerators = <ServiceGenerator>[]; | ||
final grpcGenerators = <GrpcServiceGenerator>[]; | ||
|
||
/// True if cross-references have been resolved. | ||
bool _linked = false; | ||
|
||
FileGenerator(FileDescriptorProto descriptor) | ||
: descriptor = descriptor, | ||
protoFileUri = new Uri.file(descriptor.name) { | ||
FileGenerator(this.descriptor, this.options) | ||
: protoFileUri = new Uri.file(descriptor.name) { | ||
if (protoFileUri.isAbsolute) { | ||
// protoc should never generate an import with an absolute path. | ||
throw "FAILURE: Import with absolute path is not supported"; | ||
|
@@ -133,9 +135,13 @@ class FileGenerator extends ProtobufContainer { | |
extensionGenerators.add(new ExtensionGenerator(extension, this)); | ||
} | ||
for (ServiceDescriptorProto service in descriptor.service) { | ||
var serviceGen = new ServiceGenerator(service, this); | ||
serviceGenerators.add(serviceGen); | ||
clientApiGenerators.add(new ClientApiGenerator(serviceGen)); | ||
if (options.useGrpc) { | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
jakobr-google
Author
Contributor
|
||
grpcGenerators.add(new GrpcServiceGenerator(service, this)); | ||
} else { | ||
var serviceGen = new ServiceGenerator(service, this); | ||
serviceGenerators.add(serviceGen); | ||
clientApiGenerators.add(new ClientApiGenerator(serviceGen)); | ||
} | ||
} | ||
} | ||
|
||
|
@@ -178,12 +184,19 @@ class FileGenerator extends ProtobufContainer { | |
..content = content; | ||
} | ||
|
||
return [ | ||
final files = [ | ||
makeFile(".pb.dart", generateMainFile(config)), | ||
makeFile(".pbenum.dart", generateEnumFile(config)), | ||
makeFile(".pbserver.dart", generateServerFile(config)), | ||
makeFile(".pbjson.dart", generateJsonFile(config)), | ||
]; | ||
if (options.useGrpc) { | ||
if (grpcGenerators.isNotEmpty) { | ||
files.add(makeFile(".pbgrpc.dart", generateGrpcFile(config))); | ||
} | ||
} else { | ||
files.add(makeFile(".pbserver.dart", generateServerFile(config))); | ||
} | ||
return files; | ||
} | ||
|
||
/// Returns the contents of the .pb.dart file for this .proto file. | ||
|
@@ -417,6 +430,40 @@ import 'package:protobuf/protobuf.dart'; | |
return out.toString(); | ||
} | ||
|
||
/// Returns the contents of the .pbgrpc.dart file for this .proto file. | ||
String generateGrpcFile( | ||
[OutputConfiguration config = const DefaultOutputConfiguration()]) { | ||
if (!_linked) throw new StateError("not linked"); | ||
var out = new IndentingWriter(); | ||
_writeLibraryHeading(out, "pbgrpc"); | ||
|
||
out.println(''' | ||
import 'dart:async'; | ||
import 'package:grpc/grpc.dart'; | ||
'''); | ||
|
||
// Import .pb.dart files needed for requests and responses. | ||
var imports = new Set<FileGenerator>(); | ||
for (var generator in grpcGenerators) { | ||
generator.addImportsTo(imports); | ||
} | ||
for (var target in imports) { | ||
_writeImport(out, config, target, ".pb.dart"); | ||
} | ||
|
||
var resolvedImport = | ||
config.resolveImport(protoFileUri, protoFileUri, ".pb.dart"); | ||
out.println("export '$resolvedImport';"); | ||
out.println(); | ||
|
||
for (var generator in grpcGenerators) { | ||
generator.generate(out); | ||
} | ||
|
||
return _formatter.format(out.toString()); | ||
} | ||
|
||
/// Returns the contents of the .pbjson.dart file for this .proto file. | ||
String generateJsonFile( | ||
[OutputConfiguration config = const DefaultOutputConfiguration()]) { | ||
|
@jakobr-google: It seems unfortunate that it only generates one or the other, because it will make using gRPC with Bazel harder. When the Bazel build rules run protoc using Bazel and aspects, the aspect doesn't know what the downstream dependencies will need, and they could have conflicting requirements, so using a flag seems like a problem?
A more Bazel-friendly alternative would be to generate both files all the time.