| #!/usr/bin/env dart |
| // Copyright (c) 2013, 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 file_generator_test; |
| |
| import 'package:protoc_plugin/indenting_writer.dart'; |
| import 'package:protoc_plugin/src/descriptor.pb.dart'; |
| import 'package:protoc_plugin/src/plugin.pb.dart'; |
| import 'package:protoc_plugin/protoc.dart'; |
| import 'package:test/test.dart'; |
| |
| FileDescriptorProto buildFileDescriptor( |
| {phoneNumber: true, topLevelEnum: false}) { |
| FileDescriptorProto fd = new FileDescriptorProto()..name = 'test'; |
| |
| if (topLevelEnum) { |
| fd.enumType.add(new EnumDescriptorProto() |
| ..name = 'PhoneType' |
| ..value.addAll([ |
| new EnumValueDescriptorProto() |
| ..name = 'MOBILE' |
| ..number = 0, |
| new EnumValueDescriptorProto() |
| ..name = 'HOME' |
| ..number = 1, |
| new EnumValueDescriptorProto() |
| ..name = 'WORK' |
| ..number = 2, |
| new EnumValueDescriptorProto() |
| ..name = 'BUSINESS' |
| ..number = 2 |
| ])); |
| } |
| |
| if (phoneNumber) { |
| fd.messageType.add(new DescriptorProto() |
| ..name = 'PhoneNumber' |
| ..field.addAll([ |
| // required string number = 1; |
| new FieldDescriptorProto() |
| ..name = 'number' |
| ..number = 1 |
| ..label = FieldDescriptorProto_Label.LABEL_REQUIRED |
| ..type = FieldDescriptorProto_Type.TYPE_STRING, |
| // optional int32 type = 2; |
| // OR |
| // optional PhoneType type = 2; |
| new FieldDescriptorProto() |
| ..name = 'type' |
| ..number = 2 |
| ..label = FieldDescriptorProto_Label.LABEL_OPTIONAL |
| ..type = topLevelEnum |
| ? FieldDescriptorProto_Type.TYPE_ENUM |
| : FieldDescriptorProto_Type.TYPE_INT32 |
| ..typeName = topLevelEnum ? '.PhoneType' : '', |
| // optional string name = 3 [default = "$"]; |
| new FieldDescriptorProto() |
| ..name = 'name' |
| ..number = 3 |
| ..label = FieldDescriptorProto_Label.LABEL_OPTIONAL |
| ..type = FieldDescriptorProto_Type.TYPE_STRING |
| ..defaultValue = r'$' |
| ])); |
| } |
| |
| return fd; |
| } |
| |
| void main() { |
| test('FileGenerator outputs a .pb.dart file for a proto with one message', |
| () { |
| // NOTE: Below > 80 cols because it is matching generated code > 80 cols. |
| String expected = r''' |
| /// |
| // Generated code. Do not modify. |
| /// |
| // ignore_for_file: non_constant_identifier_names |
| // ignore_for_file: library_prefixes |
| library test; |
| |
| // ignore: UNUSED_SHOWN_NAME |
| import 'dart:core' show int, bool, double, String, List, override; |
| |
| import 'package:protobuf/protobuf.dart'; |
| |
| class PhoneNumber extends GeneratedMessage { |
| static final BuilderInfo _i = new BuilderInfo('PhoneNumber') |
| ..a/*<String>*/(1, 'number', PbFieldType.QS) |
| ..a/*<int>*/(2, 'type', PbFieldType.O3) |
| ..a/*<String>*/(3, 'name', PbFieldType.OS, '\$') |
| ; |
| |
| PhoneNumber() : super(); |
| PhoneNumber.fromBuffer(List<int> i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); |
| PhoneNumber.fromJson(String i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) : super.fromJson(i, r); |
| PhoneNumber clone() => new PhoneNumber()..mergeFromMessage(this); |
| BuilderInfo get info_ => _i; |
| static PhoneNumber create() => new PhoneNumber(); |
| static PbList<PhoneNumber> createRepeated() => new PbList<PhoneNumber>(); |
| static PhoneNumber getDefault() { |
| if (_defaultInstance == null) _defaultInstance = new _ReadonlyPhoneNumber(); |
| return _defaultInstance; |
| } |
| static PhoneNumber _defaultInstance; |
| static void $checkItem(PhoneNumber v) { |
| if (v is! PhoneNumber) checkItemFailed(v, 'PhoneNumber'); |
| } |
| |
| String get number => $_get(0, 1, ''); |
| set number(String v) { $_setString(0, 1, v); } |
| bool hasNumber() => $_has(0, 1); |
| void clearNumber() => clearField(1); |
| |
| int get type => $_get(1, 2, 0); |
| set type(int v) { $_setUnsignedInt32(1, 2, v); } |
| bool hasType() => $_has(1, 2); |
| void clearType() => clearField(2); |
| |
| String get name => $_get(2, 3, '\$'); |
| set name(String v) { $_setString(2, 3, v); } |
| bool hasName() => $_has(2, 3); |
| void clearName() => clearField(3); |
| } |
| |
| class _ReadonlyPhoneNumber extends PhoneNumber with ReadonlyMessageMixin {} |
| |
| '''; |
| FileDescriptorProto fd = buildFileDescriptor(); |
| var options = parseGenerationOptions( |
| new CodeGeneratorRequest(), new CodeGeneratorResponse()); |
| FileGenerator fg = new FileGenerator(fd, options); |
| link(options, [fg]); |
| expect(fg.generateMainFile(), expected); |
| }); |
| |
| test('FileGenerator outputs a pbjson.dart file for a proto with one message', |
| () { |
| var expected = r''' |
| /// |
| // Generated code. Do not modify. |
| /// |
| // ignore_for_file: non_constant_identifier_names |
| // ignore_for_file: library_prefixes |
| library test_pbjson; |
| |
| const PhoneNumber$json = const { |
| '1': 'PhoneNumber', |
| '2': const [ |
| const {'1': 'number', '3': 1, '4': 2, '5': 9}, |
| const {'1': 'type', '3': 2, '4': 1, '5': 5, '6': ''}, |
| const {'1': 'name', '3': 3, '4': 1, '5': 9, '7': r'$'}, |
| ], |
| }; |
| |
| '''; |
| FileDescriptorProto fd = buildFileDescriptor(); |
| var options = parseGenerationOptions( |
| new CodeGeneratorRequest(), new CodeGeneratorResponse()); |
| FileGenerator fg = new FileGenerator(fd, options); |
| link(options, [fg]); |
| expect(fg.generateJsonFile(), expected); |
| }); |
| |
| test('FileGenerator generates files for a top-level enum', () { |
| // NOTE: Below > 80 cols because it is matching generated code > 80 cols. |
| |
| String expected = r''' |
| /// |
| // Generated code. Do not modify. |
| /// |
| // ignore_for_file: non_constant_identifier_names |
| // ignore_for_file: library_prefixes |
| library test; |
| |
| // ignore: UNUSED_SHOWN_NAME |
| import 'dart:core' show int, bool, double, String, List, override; |
| |
| export 'test.pbenum.dart'; |
| |
| '''; |
| |
| String expectedEnum = r''' |
| /// |
| // Generated code. Do not modify. |
| /// |
| // ignore_for_file: non_constant_identifier_names |
| // ignore_for_file: library_prefixes |
| library test_pbenum; |
| |
| // ignore: UNUSED_SHOWN_NAME |
| import 'dart:core' show int, dynamic, String, List, Map; |
| import 'package:protobuf/protobuf.dart'; |
| |
| class PhoneType extends ProtobufEnum { |
| static const PhoneType MOBILE = const PhoneType._(0, 'MOBILE'); |
| static const PhoneType HOME = const PhoneType._(1, 'HOME'); |
| static const PhoneType WORK = const PhoneType._(2, 'WORK'); |
| |
| static const PhoneType BUSINESS = WORK; |
| |
| static const List<PhoneType> values = const <PhoneType> [ |
| MOBILE, |
| HOME, |
| WORK, |
| ]; |
| |
| static final Map<int, dynamic> _byValue = ProtobufEnum.initByValue(values); |
| static PhoneType valueOf(int value) => _byValue[value] as PhoneType; |
| static void $checkItem(PhoneType v) { |
| if (v is! PhoneType) checkItemFailed(v, 'PhoneType'); |
| } |
| |
| const PhoneType._(int v, String n) : super(v, n); |
| } |
| |
| '''; |
| |
| FileDescriptorProto fd = |
| buildFileDescriptor(phoneNumber: false, topLevelEnum: true); |
| var options = parseGenerationOptions( |
| new CodeGeneratorRequest(), new CodeGeneratorResponse()); |
| |
| FileGenerator fg = new FileGenerator(fd, options); |
| link(options, [fg]); |
| expect(fg.generateMainFile(), expected); |
| expect(fg.generateEnumFile(), expectedEnum); |
| }); |
| |
| test('FileGenerator generates a .pbjson.dart file for a top-level enum', () { |
| String expected = r''' |
| /// |
| // Generated code. Do not modify. |
| /// |
| // ignore_for_file: non_constant_identifier_names |
| // ignore_for_file: library_prefixes |
| library test_pbjson; |
| |
| const PhoneType$json = const { |
| '1': 'PhoneType', |
| '2': const [ |
| const {'1': 'MOBILE', '2': 0}, |
| const {'1': 'HOME', '2': 1}, |
| const {'1': 'WORK', '2': 2}, |
| const {'1': 'BUSINESS', '2': 2}, |
| ], |
| }; |
| |
| '''; |
| |
| FileDescriptorProto fd = |
| buildFileDescriptor(phoneNumber: false, topLevelEnum: true); |
| var options = parseGenerationOptions( |
| new CodeGeneratorRequest(), new CodeGeneratorResponse()); |
| |
| FileGenerator fg = new FileGenerator(fd, options); |
| link(options, [fg]); |
| expect(fg.generateJsonFile(), expected); |
| }); |
| |
| test('FileGenerator outputs library for a .proto in a package', () { |
| String expected = r''' |
| /// |
| // Generated code. Do not modify. |
| /// |
| // ignore_for_file: non_constant_identifier_names |
| // ignore_for_file: library_prefixes |
| library pb_library_test; |
| |
| // ignore: UNUSED_SHOWN_NAME |
| import 'dart:core' show int, bool, double, String, List, override; |
| |
| import 'package:protobuf/protobuf.dart'; |
| |
| '''; |
| FileDescriptorProto fd = buildFileDescriptor(); |
| fd.package = "pb_library"; |
| var options = parseGenerationOptions( |
| new CodeGeneratorRequest(), new CodeGeneratorResponse()); |
| |
| FileGenerator fg = new FileGenerator(fd, options); |
| link(options, [fg]); |
| |
| var writer = new IndentingWriter(); |
| fg.writeMainHeader(writer); |
| expect(writer.toString(), expected); |
| }); |
| |
| test('FileGenerator outputs a fixnum import when needed', () { |
| String expected = r''' |
| /// |
| // Generated code. Do not modify. |
| /// |
| // ignore_for_file: non_constant_identifier_names |
| // ignore_for_file: library_prefixes |
| library test; |
| |
| // ignore: UNUSED_SHOWN_NAME |
| import 'dart:core' show int, bool, double, String, List, override; |
| |
| import 'package:fixnum/fixnum.dart'; |
| import 'package:protobuf/protobuf.dart'; |
| |
| '''; |
| FileDescriptorProto fd = new FileDescriptorProto() |
| ..name = 'test' |
| ..messageType.add(new DescriptorProto() |
| ..name = 'Count' |
| ..field.addAll([ |
| new FieldDescriptorProto() |
| ..name = 'count' |
| ..number = 1 |
| ..type = FieldDescriptorProto_Type.TYPE_INT64 |
| ])); |
| |
| var options = parseGenerationOptions( |
| new CodeGeneratorRequest(), new CodeGeneratorResponse()); |
| |
| FileGenerator fg = new FileGenerator(fd, options); |
| link(options, [fg]); |
| |
| var writer = new IndentingWriter(); |
| fg.writeMainHeader(writer); |
| expect(writer.toString(), expected); |
| }); |
| |
| test('FileGenerator outputs files for a service', () { |
| String expectedClient = r''' |
| /// |
| // Generated code. Do not modify. |
| /// |
| // ignore_for_file: non_constant_identifier_names |
| // ignore_for_file: library_prefixes |
| library test; |
| |
| import 'dart:async'; |
| // ignore: UNUSED_SHOWN_NAME |
| import 'dart:core' show int, bool, double, String, List, override; |
| |
| import 'package:protobuf/protobuf.dart'; |
| |
| class Empty extends GeneratedMessage { |
| static final BuilderInfo _i = new BuilderInfo('Empty') |
| ..hasRequiredFields = false |
| ; |
| |
| Empty() : super(); |
| Empty.fromBuffer(List<int> i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); |
| Empty.fromJson(String i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) : super.fromJson(i, r); |
| Empty clone() => new Empty()..mergeFromMessage(this); |
| BuilderInfo get info_ => _i; |
| static Empty create() => new Empty(); |
| static PbList<Empty> createRepeated() => new PbList<Empty>(); |
| static Empty getDefault() { |
| if (_defaultInstance == null) _defaultInstance = new _ReadonlyEmpty(); |
| return _defaultInstance; |
| } |
| static Empty _defaultInstance; |
| static void $checkItem(Empty v) { |
| if (v is! Empty) checkItemFailed(v, 'Empty'); |
| } |
| } |
| |
| class _ReadonlyEmpty extends Empty with ReadonlyMessageMixin {} |
| |
| class TestApi { |
| RpcClient _client; |
| TestApi(this._client); |
| |
| Future<Empty> ping(ClientContext ctx, Empty request) { |
| var emptyResponse = new Empty(); |
| return _client.invoke(ctx, 'Test', 'Ping', request, emptyResponse); |
| } |
| } |
| |
| '''; |
| |
| String expectedServer = r''' |
| /// |
| // Generated code. Do not modify. |
| /// |
| // ignore_for_file: non_constant_identifier_names |
| // ignore_for_file: library_prefixes |
| library test_pbserver; |
| |
| import 'dart:async'; |
| |
| import 'package:protobuf/protobuf.dart'; |
| |
| import 'test.pb.dart'; |
| import 'test.pbjson.dart'; |
| |
| export 'test.pb.dart'; |
| |
| abstract class TestServiceBase extends GeneratedService { |
| Future<Empty> ping(ServerContext ctx, Empty request); |
| |
| GeneratedMessage createRequest(String method) { |
| switch (method) { |
| case 'Ping': return new Empty(); |
| default: throw new ArgumentError('Unknown method: $method'); |
| } |
| } |
| |
| Future<GeneratedMessage> handleCall(ServerContext ctx, String method, GeneratedMessage request) { |
| switch (method) { |
| case 'Ping': return this.ping(ctx, request); |
| default: throw new ArgumentError('Unknown method: $method'); |
| } |
| } |
| |
| Map<String, dynamic> get $json => Test$json; |
| Map<String, Map<String, dynamic>> get $messageJson => Test$messageJson; |
| } |
| |
| '''; |
| |
| DescriptorProto empty = new DescriptorProto()..name = "Empty"; |
| |
| ServiceDescriptorProto sd = new ServiceDescriptorProto() |
| ..name = 'Test' |
| ..method.add(new MethodDescriptorProto() |
| ..name = 'Ping' |
| ..inputType = '.Empty' |
| ..outputType = '.Empty'); |
| |
| FileDescriptorProto fd = new FileDescriptorProto() |
| ..name = 'test' |
| ..messageType.add(empty) |
| ..service.add(sd); |
| |
| var options = parseGenerationOptions( |
| new CodeGeneratorRequest(), new CodeGeneratorResponse()); |
| |
| FileGenerator fg = new FileGenerator(fd, options); |
| link(options, [fg]); |
| |
| var writer = new IndentingWriter(); |
| fg.writeMainHeader(writer); |
| expect(fg.generateMainFile(), expectedClient); |
| expect(fg.generateServerFile(), expectedServer); |
| }); |
| |
| test('FileGenerator does not output legacy service stubs if gRPC is selected', |
| () { |
| String expectedClient = r''' |
| /// |
| // Generated code. Do not modify. |
| /// |
| // ignore_for_file: non_constant_identifier_names |
| // ignore_for_file: library_prefixes |
| library test; |
| |
| // ignore: UNUSED_SHOWN_NAME |
| import 'dart:core' show int, bool, double, String, List, override; |
| |
| import 'package:protobuf/protobuf.dart'; |
| |
| class Empty extends GeneratedMessage { |
| static final BuilderInfo _i = new BuilderInfo('Empty') |
| ..hasRequiredFields = false |
| ; |
| |
| Empty() : super(); |
| Empty.fromBuffer(List<int> i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); |
| Empty.fromJson(String i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) : super.fromJson(i, r); |
| Empty clone() => new Empty()..mergeFromMessage(this); |
| BuilderInfo get info_ => _i; |
| static Empty create() => new Empty(); |
| static PbList<Empty> createRepeated() => new PbList<Empty>(); |
| static Empty getDefault() { |
| if (_defaultInstance == null) _defaultInstance = new _ReadonlyEmpty(); |
| return _defaultInstance; |
| } |
| static Empty _defaultInstance; |
| static void $checkItem(Empty v) { |
| if (v is! Empty) checkItemFailed(v, 'Empty'); |
| } |
| } |
| |
| class _ReadonlyEmpty extends Empty with ReadonlyMessageMixin {} |
| |
| '''; |
| |
| DescriptorProto empty = new DescriptorProto()..name = "Empty"; |
| |
| ServiceDescriptorProto sd = new ServiceDescriptorProto() |
| ..name = 'Test' |
| ..method.add(new MethodDescriptorProto() |
| ..name = 'Ping' |
| ..inputType = '.Empty' |
| ..outputType = '.Empty'); |
| |
| FileDescriptorProto fd = new FileDescriptorProto() |
| ..name = 'test' |
| ..messageType.add(empty) |
| ..service.add(sd); |
| |
| var options = new GenerationOptions(useGrpc: true); |
| |
| FileGenerator fg = new FileGenerator(fd, options); |
| link(options, [fg]); |
| |
| var writer = new IndentingWriter(); |
| fg.writeMainHeader(writer); |
| expect(fg.generateMainFile(), expectedClient); |
| }); |
| |
| test('FileGenerator outputs gRPC stubs if gRPC is selected', () { |
| final expectedGrpc = r''' |
| /// |
| // Generated code. Do not modify. |
| /// |
| // ignore_for_file: non_constant_identifier_names |
| // ignore_for_file: library_prefixes |
| library test_pbgrpc; |
| |
| import 'dart:async'; |
| |
| import 'package:grpc/grpc.dart'; |
| |
| import 'test.pb.dart'; |
| export 'test.pb.dart'; |
| |
| class TestClient { |
| final ClientChannel _channel; |
| |
| static final _$unary = new ClientMethod<Input, Output>( |
| '/Test/Unary', |
| (Input value) => value.writeToBuffer(), |
| (List<int> value) => new Output.fromBuffer(value)); |
| static final _$clientStreaming = new ClientMethod<Input, Output>( |
| '/Test/ClientStreaming', |
| (Input value) => value.writeToBuffer(), |
| (List<int> value) => new Output.fromBuffer(value)); |
| static final _$serverStreaming = new ClientMethod<Input, Output>( |
| '/Test/ServerStreaming', |
| (Input value) => value.writeToBuffer(), |
| (List<int> value) => new Output.fromBuffer(value)); |
| static final _$bidirectional = new ClientMethod<Input, Output>( |
| '/Test/Bidirectional', |
| (Input value) => value.writeToBuffer(), |
| (List<int> value) => new Output.fromBuffer(value)); |
| |
| TestClient(this._channel); |
| |
| ResponseFuture<Output> unary(Input request) { |
| final call = new ClientCall(_channel, _$unary); |
| call.request |
| ..add(request) |
| ..close(); |
| return new ResponseFuture(call); |
| } |
| |
| ResponseFuture<Output> clientStreaming(Stream<Input> request) { |
| final call = new ClientCall(_channel, _$clientStreaming); |
| request.pipe(call.request); |
| return new ResponseFuture(call); |
| } |
| |
| ResponseStream<Output> serverStreaming(Input request) { |
| final call = new ClientCall(_channel, _$serverStreaming); |
| call.request |
| ..add(request) |
| ..close(); |
| return new ResponseStream(call); |
| } |
| |
| ResponseStream<Output> bidirectional(Stream<Input> request) { |
| final call = new ClientCall(_channel, _$bidirectional); |
| request.pipe(call.request); |
| return new ResponseStream(call); |
| } |
| } |
| |
| abstract class TestServiceBase extends Service { |
| String get $name => 'Test'; |
| |
| TestServiceBase() { |
| $addMethod(new ServiceMethod( |
| 'Unary', |
| unary_Pre, |
| false, |
| false, |
| (List<int> value) => new Input.fromBuffer(value), |
| (Output value) => value.writeToBuffer())); |
| $addMethod(new ServiceMethod( |
| 'ClientStreaming', |
| clientStreaming, |
| true, |
| false, |
| (List<int> value) => new Input.fromBuffer(value), |
| (Output value) => value.writeToBuffer())); |
| $addMethod(new ServiceMethod( |
| 'ServerStreaming', |
| serverStreaming_Pre, |
| false, |
| true, |
| (List<int> value) => new Input.fromBuffer(value), |
| (Output value) => value.writeToBuffer())); |
| $addMethod(new ServiceMethod( |
| 'Bidirectional', |
| bidirectional, |
| true, |
| true, |
| (List<int> value) => new Input.fromBuffer(value), |
| (Output value) => value.writeToBuffer())); |
| } |
| |
| Future<Output> unary_Pre(ServiceCall call, Future<Input> request) async { |
| return unary(call, await request); |
| } |
| |
| Stream<Output> serverStreaming_Pre( |
| ServiceCall call, Future<Input> request) async* { |
| yield* serverStreaming(call, await request); |
| } |
| |
| Future<Output> unary(ServiceCall call, Input request); |
| Future<Output> clientStreaming(ServiceCall call, Stream<Input> request); |
| Stream<Output> serverStreaming(ServiceCall call, Input request); |
| Stream<Output> bidirectional(ServiceCall call, Stream<Input> request); |
| } |
| '''; |
| |
| final input = new DescriptorProto()..name = "Input"; |
| final output = new DescriptorProto()..name = "Output"; |
| |
| final unary = new MethodDescriptorProto() |
| ..name = 'Unary' |
| ..inputType = '.Input' |
| ..outputType = '.Output' |
| ..clientStreaming = false |
| ..serverStreaming = false; |
| final clientStreaming = new MethodDescriptorProto() |
| ..name = 'ClientStreaming' |
| ..inputType = '.Input' |
| ..outputType = '.Output' |
| ..clientStreaming = true |
| ..serverStreaming = false; |
| final serverStreaming = new MethodDescriptorProto() |
| ..name = 'ServerStreaming' |
| ..inputType = '.Input' |
| ..outputType = '.Output' |
| ..clientStreaming = false |
| ..serverStreaming = true; |
| final bidirectional = new MethodDescriptorProto() |
| ..name = 'Bidirectional' |
| ..inputType = '.Input' |
| ..outputType = '.Output' |
| ..clientStreaming = true |
| ..serverStreaming = true; |
| |
| ServiceDescriptorProto sd = new ServiceDescriptorProto() |
| ..name = 'Test' |
| ..method.addAll([unary, clientStreaming, serverStreaming, bidirectional]); |
| |
| FileDescriptorProto fd = new FileDescriptorProto() |
| ..name = 'test' |
| ..messageType.addAll([input, output]) |
| ..service.add(sd); |
| |
| var options = new GenerationOptions(useGrpc: true); |
| |
| FileGenerator fg = new FileGenerator(fd, options); |
| link(options, [fg]); |
| |
| var writer = new IndentingWriter(); |
| fg.writeMainHeader(writer); |
| expect(fg.generateGrpcFile(), expectedGrpc); |
| }); |
| |
| test('FileGenerator generates imports for .pb.dart files', () { |
| // NOTE: Below > 80 cols because it is matching generated code > 80 cols. |
| String expected = r''' |
| /// |
| // Generated code. Do not modify. |
| /// |
| // ignore_for_file: non_constant_identifier_names |
| // ignore_for_file: library_prefixes |
| library test; |
| |
| // ignore: UNUSED_SHOWN_NAME |
| import 'dart:core' show int, bool, double, String, List, override; |
| |
| import 'package:protobuf/protobuf.dart'; |
| |
| import 'package1.pb.dart' as p1; |
| import 'package2.pb.dart' as p2; |
| |
| class M extends GeneratedMessage { |
| static final BuilderInfo _i = new BuilderInfo('M') |
| ..a/*<M>*/(1, 'm', PbFieldType.OM, M.getDefault, M.create) |
| ..a/*<p1.M>*/(2, 'm1', PbFieldType.OM, p1.M.getDefault, p1.M.create) |
| ..a/*<p2.M>*/(3, 'm2', PbFieldType.OM, p2.M.getDefault, p2.M.create) |
| ..hasRequiredFields = false |
| ; |
| |
| M() : super(); |
| M.fromBuffer(List<int> i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); |
| M.fromJson(String i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) : super.fromJson(i, r); |
| M clone() => new M()..mergeFromMessage(this); |
| BuilderInfo get info_ => _i; |
| static M create() => new M(); |
| static PbList<M> createRepeated() => new PbList<M>(); |
| static M getDefault() { |
| if (_defaultInstance == null) _defaultInstance = new _ReadonlyM(); |
| return _defaultInstance; |
| } |
| static M _defaultInstance; |
| static void $checkItem(M v) { |
| if (v is! M) checkItemFailed(v, 'M'); |
| } |
| |
| M get m => $_get(0, 1, null); |
| set m(M v) { setField(1, v); } |
| bool hasM() => $_has(0, 1); |
| void clearM() => clearField(1); |
| |
| p1.M get m1 => $_get(1, 2, null); |
| set m1(p1.M v) { setField(2, v); } |
| bool hasM1() => $_has(1, 2); |
| void clearM1() => clearField(2); |
| |
| p2.M get m2 => $_get(2, 3, null); |
| set m2(p2.M v) { setField(3, v); } |
| bool hasM2() => $_has(2, 3); |
| void clearM2() => clearField(3); |
| } |
| |
| class _ReadonlyM extends M with ReadonlyMessageMixin {} |
| |
| '''; |
| |
| var expectedJson = r''' |
| /// |
| // Generated code. Do not modify. |
| /// |
| // ignore_for_file: non_constant_identifier_names |
| // ignore_for_file: library_prefixes |
| library test_pbjson; |
| |
| const M$json = const { |
| '1': 'M', |
| '2': const [ |
| const {'1': 'm', '3': 1, '4': 1, '5': 11, '6': '.M'}, |
| const {'1': 'm1', '3': 2, '4': 1, '5': 11, '6': '.p1.M'}, |
| const {'1': 'm2', '3': 3, '4': 1, '5': 11, '6': '.p2.M'}, |
| ], |
| }; |
| |
| '''; |
| |
| // This defines three .proto files package1.proto, package2.proto and |
| // test.proto with the following content: |
| // |
| // package1.proto: |
| // --------------- |
| // package p1; |
| // message M { |
| // optional M m = 2; |
| // } |
| // |
| // package2.proto: |
| // --------------- |
| // package p2; |
| // message M { |
| // optional M m = 2; |
| // } |
| // |
| // test.proto: |
| // --------------- |
| // package test; |
| // import "package1.proto"; |
| // import "package2.proto"; |
| // message M { |
| // optional M m = 1; |
| // optional p1.M m1 = 2; |
| // optional p2.M m2 = 3; |
| // } |
| |
| // Description of package1.proto. |
| DescriptorProto md1 = new DescriptorProto() |
| ..name = 'M' |
| ..field.addAll([ |
| // optional M m = 1; |
| new FieldDescriptorProto() |
| ..name = 'm' |
| ..number = 1 |
| ..label = FieldDescriptorProto_Label.LABEL_OPTIONAL |
| ..type = FieldDescriptorProto_Type.TYPE_MESSAGE |
| ..typeName = ".p1.M", |
| ]); |
| FileDescriptorProto fd1 = new FileDescriptorProto() |
| ..package = 'p1' |
| ..name = 'package1.proto' |
| ..messageType.add(md1); |
| |
| // Description of package1.proto. |
| DescriptorProto md2 = new DescriptorProto() |
| ..name = 'M' |
| ..field.addAll([ |
| // optional M m = 1; |
| new FieldDescriptorProto() |
| ..name = 'x' |
| ..number = 1 |
| ..label = FieldDescriptorProto_Label.LABEL_OPTIONAL |
| ..type = FieldDescriptorProto_Type.TYPE_MESSAGE |
| ..typeName = ".p2.M", |
| ]); |
| FileDescriptorProto fd2 = new FileDescriptorProto() |
| ..package = 'p2' |
| ..name = 'package2.proto' |
| ..messageType.add(md2); |
| |
| // Description of test.proto. |
| DescriptorProto md = new DescriptorProto() |
| ..name = 'M' |
| ..field.addAll([ |
| // optional M m = 1; |
| new FieldDescriptorProto() |
| ..name = 'm' |
| ..number = 1 |
| ..label = FieldDescriptorProto_Label.LABEL_OPTIONAL |
| ..type = FieldDescriptorProto_Type.TYPE_MESSAGE |
| ..typeName = ".M", |
| // optional p1.M m1 = 2; |
| new FieldDescriptorProto() |
| ..name = 'm1' |
| ..number = 2 |
| ..label = FieldDescriptorProto_Label.LABEL_OPTIONAL |
| ..type = FieldDescriptorProto_Type.TYPE_MESSAGE |
| ..typeName = ".p1.M", |
| // optional p2.M m2 = 3; |
| new FieldDescriptorProto() |
| ..name = 'm2' |
| ..number = 3 |
| ..label = FieldDescriptorProto_Label.LABEL_OPTIONAL |
| ..type = FieldDescriptorProto_Type.TYPE_MESSAGE |
| ..typeName = ".p2.M", |
| ]); |
| FileDescriptorProto fd = new FileDescriptorProto() |
| ..name = 'test.proto' |
| ..messageType.add(md); |
| fd.dependency.addAll(['package1.proto', 'package2.proto']); |
| var request = new CodeGeneratorRequest(); |
| var response = new CodeGeneratorResponse(); |
| var options = parseGenerationOptions(request, response); |
| |
| FileGenerator fg = new FileGenerator(fd, options); |
| link(options, |
| [fg, new FileGenerator(fd1, options), new FileGenerator(fd2, options)]); |
| expect(fg.generateMainFile(), expected); |
| expect(fg.generateJsonFile(), expectedJson); |
| }); |
| } |