google / protobuf.dart

Runtime library for Dart protobufs
https://pub.dev/packages/protobuf
BSD 3-Clause "New" or "Revised" License
533 stars 184 forks source link

Unable to use GRPC service RPC call "New" #485

Closed daniel-sullivan closed 2 years ago

daniel-sullivan commented 3 years ago

When attempting to compile Dart libraries for our existing platform, we came across a strange issue with one of the repositories where we have a definition similar to:

service Account {
  rpc Get(api.base.GetRequest) returns (api.account.Model);
  rpc Search(api.base.SearchRequest) returns (stream api.account.SearchResponse);
  rpc New(api.account.Model) returns (api.account.Model);
  rpc Update(api.account.Model) returns (api.account.Model);
  rpc Destroy(api.base.DestroyRequest) returns (google.protobuf.Empty);
}

We received an output similar to the below examples with the main error seeming to be "Constructors can't have type parameters.". Unfortunately Google didn't provide any suggestions.

Doing a bit of digging through commenting out lines, we discovered that the issue was being caused by this line:

  rpc New(api.account.Model) returns (api.account.Model);

Further reading into Dart suggests that with "new" being a reserved term in Dart, us using it as the rpc function name is causing a conflict.

This was verified by creating two files:

test_create.proto

syntax = "proto3";

message SimpleReq {
  string test = 1;
}

message SimpleResponse {
  string test = 1;
}

service TestService {
  rpc Create(SimpleReq) returns (SimpleResponse);
}
❯ protoc --dart_out=grpc:. test_create.proto
< successful return > 

test_new.proto

syntax = "proto3";

message SimpleReq {
  string test = 1;
}

message SimpleResponse {
  string test = 1;
}

service TestService {
  rpc New(SimpleReq) returns (SimpleResponse);
}
❯ protoc --dart_out=grpc:. test_new.proto
Unhandled exception:
Could not format because the source could not be parsed:

line 50, column 36: A function body must be provided.
   ╷
50 │   $async.Future<$0.SimpleResponse> new($grpc.ServiceCall call, $0.SimpleReq request);
   │                                    ^^^
   ╵
line 28, column 24: Expected to find '>'.
   ╷
28 │   $grpc.ResponseFuture<$0.SimpleResponse> new($0.SimpleReq request, {$grpc.CallOptions options}) {
   │                        ^^
   ╵
line 28, column 23: Constructors can't have type parameters.
   ╷
28 │   $grpc.ResponseFuture<$0.SimpleResponse> new($0.SimpleReq request, {$grpc.CallOptions options}) {
   │                       ^^^^^^^^^^^^^^^^^^^
   ╵
line 50, column 17: Expected to find '>'.
   ╷
50 │   $async.Future<$0.SimpleResponse> new($grpc.ServiceCall call, $0.SimpleReq request);
   │                 ^^
   ╵
line 28, column 3: Methods must have an explicit list of parameters.
   ╷
28 │   $grpc.ResponseFuture<$0.SimpleResponse> new($0.SimpleReq request, {$grpc.CallOptions options}) {
   │   ^^^^^
   ╵
line 50, column 16: Constructors can't have type parameters.
   ╷
50 │   $async.Future<$0.SimpleResponse> new($grpc.ServiceCall call, $0.SimpleReq request);
   │                ^^^^^^^^^^^^^^^^^^^
   ╵
line 28, column 3: The name of a constructor must match the name of the enclosing class.
   ╷
28 │   $grpc.ResponseFuture<$0.SimpleResponse> new($0.SimpleReq request, {$grpc.CallOptions options}) {
   │   ^^^^^
   ╵
line 28, column 43: A function body must be provided.
   ╷
28 │   $grpc.ResponseFuture<$0.SimpleResponse> new($0.SimpleReq request, {$grpc.CallOptions options}) {
   │                                           ^^^
   ╵
line 50, column 36: Expected a class member.
   ╷
50 │   $async.Future<$0.SimpleResponse> new($grpc.ServiceCall call, $0.SimpleReq request);
   │                                    ^^^
   ╵
line 50, column 3: The name of a constructor must match the name of the enclosing class.
   ╷
50 │   $async.Future<$0.SimpleResponse> new($grpc.ServiceCall call, $0.SimpleReq request);
   │   ^^^^^^
   ╵
(5 more errors...)
#0      DartFormatter.formatSource (package:dart_style/src/dart_formatter.dart:141:7)
#1      DartFormatter.format (package:dart_style/src/dart_formatter.dart:75:12)
#2      FileGenerator.generateGrpcFile (package:protoc_plugin/file_generator.dart:518:23)
#3      FileGenerator.generateFiles (package:protoc_plugin/file_generator.dart:252:44)
#4      CodeGenerator.generate.<anonymous closure> (package:protoc_plugin/code_generator.dart:114:36)
#5      _RootZone.runUnary (dart:async/zone.dart:1450:54)
#6      _FutureListener.handleValue (dart:async/future_impl.dart:143:18)
#7      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:696:45)
#8      Future._propagateToListeners (dart:async/future_impl.dart:725:32)
#9      Future._complete (dart:async/future_impl.dart:519:7)
#10     Stream.fold.<anonymous closure> (dart:async/stream.dart:847:14)
#11     _RootZone.runGuarded (dart:async/zone.dart:1372:10)
#12     _BufferingStreamSubscription._sendDone.sendDone (dart:async/stream_impl.dart:410:13)
#13     _BufferingStreamSubscription._sendDone (dart:async/stream_impl.dart:420:15)
#14     _BufferingStreamSubscription._close (dart:async/stream_impl.dart:305:7)
#15     _SyncStreamControllerDispatch._sendDone (dart:async/stream_controller.dart:816:19)
#16     _StreamController._closeUnchecked (dart:async/stream_controller.dart:671:7)
#17     _StreamController.close (dart:async/stream_controller.dart:664:5)
#18     _Socket._onData (dart:io-patch/socket_patch.dart:2051:21)
#19     _RootZone.runUnaryGuarded (dart:async/zone.dart:1384:10)
#20     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:357:11)
#21     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:285:7)
#22     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:808:19)
#23     _StreamController._add (dart:async/stream_controller.dart:682:7)
#24     _StreamController.add (dart:async/stream_controller.dart:624:5)
#25     new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1587:35)
#26     _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1069:18)
#27     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
#28     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
#29     _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:118:13)
#30     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:169:5)
--dart_out: protoc-gen-dart: Plugin failed with status code 255.

Would anyone have any suggestions which don't involve renaming the functions in this module? (which are currently being used by several other systems). Unfortunately, we're just starting to get into Dart coding so don't have the skills required to investigate solutions in a time efficient manner.

sigurdm commented 3 years ago

Seems we don't do any disambiguation of method names when generating the service descriptors...

osa1 commented 2 years ago

487 fixes this but it was closed without an explanation. I added a comment in the PR to reopen it and merge it.

osa1 commented 2 years ago

Duplicate of #159, except the conflicting identifier is New instead of Request.