This repository has been archived by the owner on Jan 26, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial support for generating client and server stubs for Dart.
[email protected], [email protected] BUG= Review URL: https://chromiumcodereview.appspot.com//1196293003
- Loading branch information
Showing
12 changed files
with
405 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
part of protoc; | ||
|
||
class ClientApiGenerator extends ProtobufContainer { | ||
final String classname; | ||
final String fqname; | ||
|
||
final ProtobufContainer _parent; | ||
final GenerationContext _context; | ||
final ServiceDescriptorProto _descriptor; | ||
|
||
ClientApiGenerator(ServiceDescriptorProto descriptor, | ||
ProtobufContainer parent, this._context) | ||
: _descriptor = descriptor, | ||
_parent = parent, | ||
classname = descriptor.name, | ||
fqname = (parent == null || parent.fqname == null) | ||
? descriptor.name | ||
: (parent.fqname == '.' | ||
? '.${descriptor.name}' | ||
: '${parent.fqname}.${descriptor.name}') { | ||
_context.register(this); | ||
} | ||
|
||
String get package => _parent.package; | ||
|
||
String _shortType(String typename) { | ||
return typename.substring(typename.lastIndexOf('.')+1); | ||
} | ||
|
||
void generate(IndentingWriter out) { | ||
out.addBlock('class ${classname}Api {', '}', () { | ||
out.println('RpcClient _client;'); | ||
out.println('${classname}Api(this._client);'); | ||
out.println(); | ||
for (MethodDescriptorProto m in _descriptor.method) { | ||
// lowercase first letter in method name. | ||
var methodName = | ||
m.name.substring(0,1).toLowerCase() + m.name.substring(1); | ||
out.addBlock('Future<${_shortType(m.outputType)}> $methodName(' | ||
'ClientContext ctx, ${_shortType(m.inputType)} request) ' | ||
'async {', '}', () { | ||
out.println('var emptyResponse = new ${_shortType(m.outputType)}();'); | ||
out.println('var result = await _client.invoke(ctx, ' | ||
'\'${_descriptor.name}\', \'${m.name}\', ' | ||
'request, emptyResponse);'); | ||
out.println('return result;'); | ||
}); | ||
} | ||
}); | ||
out.println(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
part of protoc; | ||
|
||
class ServiceGenerator extends ProtobufContainer { | ||
final String classname; | ||
final String fqname; | ||
|
||
final ProtobufContainer _parent; | ||
final GenerationContext _context; | ||
final ServiceDescriptorProto _descriptor; | ||
final List<MethodDescriptorProto> _methodDescriptors; | ||
|
||
ServiceGenerator(ServiceDescriptorProto descriptor, ProtobufContainer parent, | ||
this._context) | ||
: _descriptor = descriptor, | ||
_parent = parent, | ||
classname = descriptor.name, | ||
fqname = _qualifiedName(descriptor, parent), | ||
_methodDescriptors = descriptor.method { | ||
_context.register(this); | ||
} | ||
|
||
static String _qualifiedName(ServiceDescriptorProto descriptor, | ||
ProtobufContainer parent) { | ||
if (parent == null || parent.fqname == null) { | ||
return descriptor.name; | ||
} else if (parent.fqname == '.') { | ||
return '.${descriptor.name}'; | ||
} else { | ||
return '${parent.fqname}.${descriptor.name}'; | ||
} | ||
} | ||
|
||
static String _serviceClassName(descriptor) { | ||
if (descriptor.name.endsWith("Service")) { | ||
return descriptor.name + "Base"; // avoid: ServiceServiceBase | ||
} else { | ||
return descriptor.name + "ServiceBase"; | ||
} | ||
} | ||
|
||
String get package => _parent.package; | ||
|
||
String _shortType(String typename) { | ||
return typename.substring(typename.lastIndexOf('.') + 1); | ||
} | ||
|
||
String _methodName(String name) => | ||
name.substring(0,1).toLowerCase() + name.substring(1); | ||
|
||
void generate(IndentingWriter out) { | ||
out.addBlock( | ||
'abstract class ${_serviceClassName(_descriptor)} extends ' | ||
'GeneratedService {', | ||
'}', () { | ||
for (MethodDescriptorProto m in _methodDescriptors) { | ||
var methodName = _methodName(m.name); | ||
out.println('Future<${_shortType(m.outputType)}> $methodName(' | ||
'ServerContext ctx, ${_shortType(m.inputType)} request);'); | ||
} | ||
out.println(); | ||
|
||
out.addBlock( | ||
'GeneratedMessage createRequest(String method) {', '}', () { | ||
out.addBlock("switch (method) {", "}", () { | ||
for (MethodDescriptorProto m in _methodDescriptors) { | ||
out.println( | ||
"case '${m.name}': return new ${_shortType(m.inputType)}();"); | ||
} | ||
out.println("default: " | ||
"throw new ArgumentError('Unknown method: \$method');"); | ||
}); | ||
}); | ||
out.println(); | ||
|
||
out.addBlock( | ||
'Future<GeneratedMessage> handleCall(ServerContext ctx, ' | ||
'String method, GeneratedMessage request) async {', '}', () { | ||
out.addBlock("switch (method) {", "}", () { | ||
for (MethodDescriptorProto m in _methodDescriptors) { | ||
var methodName = _methodName(m.name); | ||
out.println( | ||
"case '${m.name}': return await $methodName(ctx, request);"); | ||
} | ||
out.println("default: " | ||
"throw new ArgumentError('Unknown method: \$method');"); | ||
}); | ||
}); | ||
}); | ||
out.println(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
name: protoc_plugin | ||
version: 0.3.9 | ||
version: 0.3.10 | ||
author: Dart Team <[email protected]> | ||
description: Protoc compiler plugin to generate Dart code | ||
homepage: https://github.com/dart-lang/dart-protoc-plugin | ||
environment: | ||
sdk: '>=1.0.0 <2.0.0' | ||
dependencies: | ||
protobuf: '>=0.3.9 <0.4.0' | ||
protobuf: '>=0.3.10 <0.4.0' | ||
path: '>=1.0.0 <2.0.0' | ||
dev_dependencies: | ||
unittest: '>=0.9.0 <0.11.0' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
#!/usr/bin/env dart | ||
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
library client_generator_test; | ||
|
||
import 'package:protoc_plugin/src/descriptor.pb.dart'; | ||
import 'package:protoc_plugin/src/plugin.pb.dart'; | ||
import 'package:protoc_plugin/protoc.dart'; | ||
import 'package:unittest/unittest.dart'; | ||
|
||
ServiceDescriptorProto buildServiceDescriptor() { | ||
ServiceDescriptorProto sd = new ServiceDescriptorProto() | ||
..name = 'Test' | ||
..method.addAll([ | ||
new MethodDescriptorProto() | ||
..name = 'AMethod' | ||
..inputType = 'SomeRequest' | ||
..outputType = 'SomeReply', | ||
new MethodDescriptorProto() | ||
..name = 'AnotherMethod' | ||
..inputType = '.foo.bar.EmptyMessage' | ||
..outputType = '.foo.bar.AnotherReply', | ||
]); | ||
return sd; | ||
} | ||
|
||
void main() { | ||
test('testClientGenerator', () { | ||
// NOTE: Below > 80 cols because it is matching generated code > 80 cols. | ||
String expected = r''' | ||
class TestApi { | ||
RpcClient _client; | ||
TestApi(this._client); | ||
Future<SomeReply> aMethod(ClientContext ctx, SomeRequest request) async { | ||
var emptyResponse = new SomeReply(); | ||
var result = await _client.invoke(ctx, 'Test', 'AMethod', request, emptyResponse); | ||
return result; | ||
} | ||
Future<AnotherReply> anotherMethod(ClientContext ctx, EmptyMessage request) async { | ||
var emptyResponse = new AnotherReply(); | ||
var result = await _client.invoke(ctx, 'Test', 'AnotherMethod', request, emptyResponse); | ||
return result; | ||
} | ||
} | ||
'''; | ||
var options = parseGenerationOptions( | ||
new CodeGeneratorRequest(), new CodeGeneratorResponse()); | ||
var context = | ||
new GenerationContext(options, new DefaultOutputConfiguration()); | ||
var fd = new FileDescriptorProto(); | ||
var fg = new FileGenerator(fd, null, context); | ||
ServiceDescriptorProto sd = buildServiceDescriptor(); | ||
MemoryWriter buffer = new MemoryWriter(); | ||
IndentingWriter writer = new IndentingWriter(' ', buffer); | ||
ClientApiGenerator cag = new ClientApiGenerator(sd, fg, context); | ||
cag.generate(writer); | ||
expect(buffer.toString(), expected); | ||
}); | ||
} |
Oops, something went wrong.