Import grpc with prefix in generated pbgrpc.dart files (#191)

diff --git a/protoc_plugin/CHANGELOG.md b/protoc_plugin/CHANGELOG.md
index 74ed7e3..3b6ef96 100644
--- a/protoc_plugin/CHANGELOG.md
+++ b/protoc_plugin/CHANGELOG.md
@@ -1,4 +1,8 @@
-+## 15.0.1
+## 15.0.2
+
+* The generated `pbgrpc.dart` files now import `package:grpc/grpc.dart` with a prefix.
+
+## 15.0.1
 
 * Add test for frozen messages with extension fields and update protobuf dependency to 0.13.0.
 
diff --git a/protoc_plugin/lib/client_generator.dart b/protoc_plugin/lib/client_generator.dart
index 309b121..f27f9c5 100644
--- a/protoc_plugin/lib/client_generator.dart
+++ b/protoc_plugin/lib/client_generator.dart
@@ -42,7 +42,7 @@
     var inputType = service._getDartClassName(m.inputType);
     var outputType = service._getDartClassName(m.outputType);
     out.addBlock(
-        '\$async.Future<$outputType> $methodName('
+        '$_asyncImportPrefix.Future<$outputType> $methodName('
         '$_protobufImportPrefix.ClientContext ctx, $inputType request) {',
         '}', () {
       out.println('var emptyResponse = new $outputType();');
diff --git a/protoc_plugin/lib/file_generator.dart b/protoc_plugin/lib/file_generator.dart
index c9940c6..845966b 100644
--- a/protoc_plugin/lib/file_generator.dart
+++ b/protoc_plugin/lib/file_generator.dart
@@ -7,6 +7,13 @@
 final _dartIdentifier = new RegExp(r'^\w+$');
 final _formatter = new DartFormatter();
 final String _protobufImportPrefix = r'$pb';
+final String _asyncImportPrefix = r'$async';
+final String _grpcImportPrefix = r'$grpc';
+final String _protobufImport =
+    "import 'package:protobuf/protobuf.dart' as $_protobufImportPrefix;";
+final String _asyncImport = "import 'dart:async' as $_asyncImportPrefix;";
+final String _grpcImport =
+    "import 'package:grpc/grpc.dart' as $_grpcImportPrefix;";
 
 /// Generates the Dart output files for one .proto input file.
 ///
@@ -255,7 +262,7 @@
     // We only add the dart:async import if there are generic client API
     // generators for services in the FileDescriptorProto.
     if (clientApiGenerators.isNotEmpty) {
-      out.println(r"import 'dart:async' as $async;");
+      out.println(_asyncImport);
     }
 
     // Make sure any other symbols in dart:core don't cause name conflicts with
@@ -268,8 +275,7 @@
     }
 
     if (_needsProtobufImport) {
-      out.println(
-          "import 'package:protobuf/protobuf.dart' as $_protobufImportPrefix;");
+      out.println(_protobufImport);
       out.println();
     }
 
@@ -376,8 +382,7 @@
       // with enums that have the same name.
       out.println("// ignore_for_file: UNDEFINED_SHOWN_NAME,UNUSED_SHOWN_NAME\n"
           "import 'dart:core' show int, dynamic, String, List, Map;");
-      out.println(
-          "import 'package:protobuf/protobuf.dart' as $_protobufImportPrefix;");
+      out.println(_protobufImport);
       out.println();
     }
 
@@ -409,11 +414,9 @@
     _writeHeading(out);
 
     if (serviceGenerators.isNotEmpty) {
-      out.println(r'''
-import 'dart:async' as $async;
-
-import 'package:protobuf/protobuf.dart';
-''');
+      out.println(_asyncImport);
+      out.println();
+      out.println(_protobufImport);
     }
 
     // Import .pb.dart files needed for requests and responses.
@@ -450,11 +453,9 @@
     var out = new IndentingWriter();
     _writeHeading(out);
 
-    out.println(r'''
-import 'dart:async' as $async;
-
-import 'package:grpc/grpc.dart';
-''');
+    out.println(_asyncImport);
+    out.println();
+    out.println(_grpcImport);
 
     // Import .pb.dart files needed for requests and responses.
     var imports = new Set<FileGenerator>();
diff --git a/protoc_plugin/lib/grpc_generator.dart b/protoc_plugin/lib/grpc_generator.dart
index 79f3d78..6e5579c 100644
--- a/protoc_plugin/lib/grpc_generator.dart
+++ b/protoc_plugin/lib/grpc_generator.dart
@@ -110,13 +110,13 @@
   }
 
   void _generateClient(IndentingWriter out) {
-    out.addBlock('class $_clientClassname extends Client {', '}', () {
+    out.addBlock('class $_clientClassname extends $_client {', '}', () {
       for (final method in _methods) {
         method.generateClientMethodDescriptor(out);
       }
       out.println();
       out.println(
-          '$_clientClassname(ClientChannel channel, {CallOptions options})');
+          '$_clientClassname($_clientChannel channel, {$_callOptions options})');
       out.println('    : super(channel, options: options);');
       for (final method in _methods) {
         method.generateClientStub(out);
@@ -125,7 +125,7 @@
   }
 
   void _generateService(IndentingWriter out) {
-    out.addBlock('abstract class $_serviceClassname extends Service {', '}',
+    out.addBlock('abstract class $_serviceClassname extends $_service {', '}',
         () {
       out.println('String get \$name => \'$_fullServiceName\';');
       out.println();
@@ -143,6 +143,11 @@
       }
     });
   }
+
+  static final String _callOptions = '$_grpcImportPrefix.CallOptions';
+  static final String _client = '$_grpcImportPrefix.Client';
+  static final String _clientChannel = '$_grpcImportPrefix.ClientChannel';
+  static final String _service = '$_grpcImportPrefix.Service';
 }
 
 class _GrpcMethod {
@@ -188,13 +193,12 @@
     final responseType = service._getDartClassName(method.outputType);
 
     final argumentType =
-        clientStreaming ? '\$async.Stream<$requestType>' : requestType;
+        clientStreaming ? '$_stream<$requestType>' : requestType;
     final clientReturnType = serverStreaming
-        ? 'ResponseStream<$responseType>'
-        : 'ResponseFuture<$responseType>';
-    final serverReturnType = serverStreaming
-        ? '\$async.Stream<$responseType>'
-        : '\$async.Future<$responseType>';
+        ? '$_responseStream<$responseType>'
+        : '$_responseFuture<$responseType>';
+    final serverReturnType =
+        serverStreaming ? '$_stream<$responseType>' : '$_future<$responseType>';
 
     return new _GrpcMethod._(
         grpcName,
@@ -211,7 +215,7 @@
 
   void generateClientMethodDescriptor(IndentingWriter out) {
     out.println(
-        'static final _\$$_dartName = new ClientMethod<$_requestType, $_responseType>(');
+        'static final _\$$_dartName = new $_clientMethod<$_requestType, $_responseType>(');
     out.println('    \'/$_serviceName/$_grpcName\',');
     out.println('    ($_requestType value) => value.writeToBuffer(),');
     out.println(
@@ -221,24 +225,23 @@
   void generateClientStub(IndentingWriter out) {
     out.println();
     out.addBlock(
-        '$_clientReturnType $_dartName($_argumentType request, {CallOptions options}) {',
+        '$_clientReturnType $_dartName($_argumentType request, {${GrpcServiceGenerator._callOptions} options}) {',
         '}', () {
-      final requestStream = _clientStreaming
-          ? 'request'
-          : r'new $async.Stream.fromIterable([request])';
+      final requestStream =
+          _clientStreaming ? 'request' : 'new $_stream.fromIterable([request])';
       out.println(
           'final call = \$createCall(_\$$_dartName, $requestStream, options: options);');
       if (_serverStreaming) {
-        out.println('return new ResponseStream(call);');
+        out.println('return new $_responseStream(call);');
       } else {
-        out.println('return new ResponseFuture(call);');
+        out.println('return new $_responseFuture(call);');
       }
     });
   }
 
   void generateServiceMethodRegistration(IndentingWriter out) {
     out.println(
-        '\$addMethod(new ServiceMethod<$_requestType, $_responseType>(');
+        '\$addMethod(new $_serviceMethod<$_requestType, $_responseType>(');
     out.println('    \'$_grpcName\',');
     out.println('    $_dartName${_clientStreaming ? '' : '_Pre'},');
     out.println('    $_clientStreaming,');
@@ -252,7 +255,7 @@
     if (_clientStreaming) return;
 
     out.addBlock(
-        '$_serverReturnType ${_dartName}_Pre(ServiceCall call, \$async.Future request) async${_serverStreaming ? '*' : ''} {',
+        '$_serverReturnType ${_dartName}_Pre($_serviceCall call, $_future request) async${_serverStreaming ? '*' : ''} {',
         '}', () {
       if (_serverStreaming) {
         out.println(
@@ -266,6 +269,14 @@
 
   void generateServiceMethodStub(IndentingWriter out) {
     out.println(
-        '$_serverReturnType $_dartName(ServiceCall call, $_argumentType request);');
+        '$_serverReturnType $_dartName($_serviceCall call, $_argumentType request);');
   }
+
+  static final String _serviceCall = '$_grpcImportPrefix.ServiceCall';
+  static final String _serviceMethod = '$_grpcImportPrefix.ServiceMethod';
+  static final String _clientMethod = '$_grpcImportPrefix.ClientMethod';
+  static final String _future = '$_asyncImportPrefix.Future';
+  static final String _stream = '$_asyncImportPrefix.Stream';
+  static final String _responseFuture = '$_grpcImportPrefix.ResponseFuture';
+  static final String _responseStream = '$_grpcImportPrefix.ResponseStream';
 }
diff --git a/protoc_plugin/lib/service_generator.dart b/protoc_plugin/lib/service_generator.dart
index e06d5fc..427df93 100644
--- a/protoc_plugin/lib/service_generator.dart
+++ b/protoc_plugin/lib/service_generator.dart
@@ -131,15 +131,15 @@
   String _methodName(String name) =>
       name.substring(0, 1).toLowerCase() + name.substring(1);
 
-  String get _parentClass => 'GeneratedService';
+  String get _parentClass => _generatedService;
 
   void _generateStub(IndentingWriter out, MethodDescriptorProto m) {
     var methodName = _methodName(m.name);
     var inputClass = _getDartClassName(m.inputType);
     var outputClass = _getDartClassName(m.outputType);
 
-    out.println('\$async.Future<$outputClass> $methodName('
-        'ServerContext ctx, $inputClass request);');
+    out.println('$_future<$outputClass> $methodName('
+        '$_serverContext ctx, $inputClass request);');
   }
 
   void _generateStubs(IndentingWriter out) {
@@ -150,7 +150,7 @@
   }
 
   void _generateRequestMethod(IndentingWriter out) {
-    out.addBlock('GeneratedMessage createRequest(String method) {', '}', () {
+    out.addBlock('$_generatedMessage createRequest(String method) {', '}', () {
       out.addBlock("switch (method) {", "}", () {
         for (MethodDescriptorProto m in _methodDescriptors) {
           var inputClass = _getDartClassName(m.inputType);
@@ -165,8 +165,8 @@
 
   void _generateDispatchMethod(out) {
     out.addBlock(
-        r'$async.Future<GeneratedMessage> handleCall(ServerContext ctx, '
-        'String method, GeneratedMessage request) {',
+        '$_future<$_generatedMessage> handleCall($_serverContext ctx, '
+        'String method, $_generatedMessage request) {',
         '}', () {
       out.addBlock("switch (method) {", "}", () {
         for (MethodDescriptorProto m in _methodDescriptors) {
@@ -233,4 +233,11 @@
       out.println();
     }
   }
+
+  static final String _future = '$_asyncImportPrefix.Future';
+  static final String _generatedMessage =
+      '$_protobufImportPrefix.GeneratedMessage';
+  static final String _serverContext = '$_protobufImportPrefix.ServerContext';
+  static final String _generatedService =
+      '$_protobufImportPrefix.GeneratedService';
 }
diff --git a/protoc_plugin/pubspec.yaml b/protoc_plugin/pubspec.yaml
index 4a80d17..9caee2c 100644
--- a/protoc_plugin/pubspec.yaml
+++ b/protoc_plugin/pubspec.yaml
@@ -1,5 +1,5 @@
 name: protoc_plugin
-version: 15.0.1
+version: 15.0.2
 author: Dart Team <misc@dartlang.org>
 description: Protoc compiler plugin to generate Dart code
 homepage: https://github.com/dart-lang/protobuf
diff --git a/protoc_plugin/test/goldens/grpc_service.pbgrpc b/protoc_plugin/test/goldens/grpc_service.pbgrpc
index b167366..55d9462 100644
--- a/protoc_plugin/test/goldens/grpc_service.pbgrpc
+++ b/protoc_plugin/test/goldens/grpc_service.pbgrpc
@@ -6,84 +6,85 @@
 
 import 'dart:async' as $async;
 
-import 'package:grpc/grpc.dart';
-
+import 'package:grpc/grpc.dart' as $grpc;
 import 'test.pb.dart';
 export 'test.pb.dart';
 
-class TestClient extends Client {
-  static final _$unary = new ClientMethod<Input, Output>(
+class TestClient extends $grpc.Client {
+  static final _$unary = new $grpc.ClientMethod<Input, Output>(
       '/Test/Unary',
       (Input value) => value.writeToBuffer(),
       (List<int> value) => new Output.fromBuffer(value));
-  static final _$clientStreaming = new ClientMethod<Input, Output>(
+  static final _$clientStreaming = new $grpc.ClientMethod<Input, Output>(
       '/Test/ClientStreaming',
       (Input value) => value.writeToBuffer(),
       (List<int> value) => new Output.fromBuffer(value));
-  static final _$serverStreaming = new ClientMethod<Input, Output>(
+  static final _$serverStreaming = new $grpc.ClientMethod<Input, Output>(
       '/Test/ServerStreaming',
       (Input value) => value.writeToBuffer(),
       (List<int> value) => new Output.fromBuffer(value));
-  static final _$bidirectional = new ClientMethod<Input, Output>(
+  static final _$bidirectional = new $grpc.ClientMethod<Input, Output>(
       '/Test/Bidirectional',
       (Input value) => value.writeToBuffer(),
       (List<int> value) => new Output.fromBuffer(value));
 
-  TestClient(ClientChannel channel, {CallOptions options})
+  TestClient($grpc.ClientChannel channel, {$grpc.CallOptions options})
       : super(channel, options: options);
 
-  ResponseFuture<Output> unary(Input request, {CallOptions options}) {
+  $grpc.ResponseFuture<Output> unary(Input request,
+      {$grpc.CallOptions options}) {
     final call = $createCall(_$unary, new $async.Stream.fromIterable([request]),
         options: options);
-    return new ResponseFuture(call);
+    return new $grpc.ResponseFuture(call);
   }
 
-  ResponseFuture<Output> clientStreaming($async.Stream<Input> request,
-      {CallOptions options}) {
+  $grpc.ResponseFuture<Output> clientStreaming($async.Stream<Input> request,
+      {$grpc.CallOptions options}) {
     final call = $createCall(_$clientStreaming, request, options: options);
-    return new ResponseFuture(call);
+    return new $grpc.ResponseFuture(call);
   }
 
-  ResponseStream<Output> serverStreaming(Input request, {CallOptions options}) {
+  $grpc.ResponseStream<Output> serverStreaming(Input request,
+      {$grpc.CallOptions options}) {
     final call = $createCall(
         _$serverStreaming, new $async.Stream.fromIterable([request]),
         options: options);
-    return new ResponseStream(call);
+    return new $grpc.ResponseStream(call);
   }
 
-  ResponseStream<Output> bidirectional($async.Stream<Input> request,
-      {CallOptions options}) {
+  $grpc.ResponseStream<Output> bidirectional($async.Stream<Input> request,
+      {$grpc.CallOptions options}) {
     final call = $createCall(_$bidirectional, request, options: options);
-    return new ResponseStream(call);
+    return new $grpc.ResponseStream(call);
   }
 }
 
-abstract class TestServiceBase extends Service {
+abstract class TestServiceBase extends $grpc.Service {
   String get $name => 'Test';
 
   TestServiceBase() {
-    $addMethod(new ServiceMethod<Input, Output>(
+    $addMethod(new $grpc.ServiceMethod<Input, Output>(
         'Unary',
         unary_Pre,
         false,
         false,
         (List<int> value) => new Input.fromBuffer(value),
         (Output value) => value.writeToBuffer()));
-    $addMethod(new ServiceMethod<Input, Output>(
+    $addMethod(new $grpc.ServiceMethod<Input, Output>(
         'ClientStreaming',
         clientStreaming,
         true,
         false,
         (List<int> value) => new Input.fromBuffer(value),
         (Output value) => value.writeToBuffer()));
-    $addMethod(new ServiceMethod<Input, Output>(
+    $addMethod(new $grpc.ServiceMethod<Input, Output>(
         'ServerStreaming',
         serverStreaming_Pre,
         false,
         true,
         (List<int> value) => new Input.fromBuffer(value),
         (Output value) => value.writeToBuffer()));
-    $addMethod(new ServiceMethod<Input, Output>(
+    $addMethod(new $grpc.ServiceMethod<Input, Output>(
         'Bidirectional',
         bidirectional,
         true,
@@ -93,19 +94,19 @@
   }
 
   $async.Future<Output> unary_Pre(
-      ServiceCall call, $async.Future request) async {
+      $grpc.ServiceCall call, $async.Future request) async {
     return unary(call, await request);
   }
 
   $async.Stream<Output> serverStreaming_Pre(
-      ServiceCall call, $async.Future request) async* {
+      $grpc.ServiceCall call, $async.Future request) async* {
     yield* serverStreaming(call, (await request) as Input);
   }
 
-  $async.Future<Output> unary(ServiceCall call, Input request);
+  $async.Future<Output> unary($grpc.ServiceCall call, Input request);
   $async.Future<Output> clientStreaming(
-      ServiceCall call, $async.Stream<Input> request);
-  $async.Stream<Output> serverStreaming(ServiceCall call, Input request);
+      $grpc.ServiceCall call, $async.Stream<Input> request);
+  $async.Stream<Output> serverStreaming($grpc.ServiceCall call, Input request);
   $async.Stream<Output> bidirectional(
-      ServiceCall call, $async.Stream<Input> request);
+      $grpc.ServiceCall call, $async.Stream<Input> request);
 }
diff --git a/protoc_plugin/test/goldens/service.pbserver b/protoc_plugin/test/goldens/service.pbserver
index cf1be0c..a80c7b0 100644
--- a/protoc_plugin/test/goldens/service.pbserver
+++ b/protoc_plugin/test/goldens/service.pbserver
@@ -6,24 +6,23 @@
 
 import 'dart:async' as $async;
 
-import 'package:protobuf/protobuf.dart';
-
+import 'package:protobuf/protobuf.dart' as $pb;
 import 'test.pb.dart';
 import 'test.pbjson.dart';
 
 export 'test.pb.dart';
 
-abstract class TestServiceBase extends GeneratedService {
-  $async.Future<Empty> ping(ServerContext ctx, Empty request);
+abstract class TestServiceBase extends $pb.GeneratedService {
+  $async.Future<Empty> ping($pb.ServerContext ctx, Empty request);
 
-  GeneratedMessage createRequest(String method) {
+  $pb.GeneratedMessage createRequest(String method) {
     switch (method) {
       case 'Ping': return new Empty();
       default: throw new ArgumentError('Unknown method: $method');
     }
   }
 
-  $async.Future<GeneratedMessage> handleCall(ServerContext ctx, String method, GeneratedMessage request) {
+  $async.Future<$pb.GeneratedMessage> handleCall($pb.ServerContext ctx, String method, $pb.GeneratedMessage request) {
     switch (method) {
       case 'Ping': return this.ping(ctx, request);
       default: throw new ArgumentError('Unknown method: $method');
diff --git a/protoc_plugin/test/goldens/serviceGenerator b/protoc_plugin/test/goldens/serviceGenerator
index f5eb2e9..f1c7397 100644
--- a/protoc_plugin/test/goldens/serviceGenerator
+++ b/protoc_plugin/test/goldens/serviceGenerator
@@ -1,8 +1,8 @@
-abstract class TestServiceBase extends GeneratedService {
-  $async.Future<SomeReply> aMethod(ServerContext ctx, SomeRequest request);
-  $async.Future<$0.AnotherReply> anotherMethod(ServerContext ctx, $0.EmptyMessage request);
+abstract class TestServiceBase extends $pb.GeneratedService {
+  $async.Future<SomeReply> aMethod($pb.ServerContext ctx, SomeRequest request);
+  $async.Future<$0.AnotherReply> anotherMethod($pb.ServerContext ctx, $0.EmptyMessage request);
 
-  GeneratedMessage createRequest(String method) {
+  $pb.GeneratedMessage createRequest(String method) {
     switch (method) {
       case 'AMethod': return new SomeRequest();
       case 'AnotherMethod': return new $0.EmptyMessage();
@@ -10,7 +10,7 @@
     }
   }
 
-  $async.Future<GeneratedMessage> handleCall(ServerContext ctx, String method, GeneratedMessage request) {
+  $async.Future<$pb.GeneratedMessage> handleCall($pb.ServerContext ctx, String method, $pb.GeneratedMessage request) {
     switch (method) {
       case 'AMethod': return this.aMethod(ctx, request);
       case 'AnotherMethod': return this.anotherMethod(ctx, request);