From 00b159fe453cfbc351a6d15f1d3ca9b7990898d6 Mon Sep 17 00:00:00 2001 From: Ernest Micklei Date: Fri, 10 Mar 2017 23:11:06 +0100 Subject: [PATCH] Squashed commit of the following: commit d0d9c087c298553c3ab22c9eb20e74ed55543b15 Author: Ernest Micklei Date: Fri Mar 10 23:02:39 2017 +0100 fixed issue #3, fix formatting extended message commit 79f3388b6984d39ace1ecc4a6fe5a59de0fa9f2d Author: Ernest Micklei Date: Fri Mar 10 07:22:57 2017 +0100 fix conflict commit c80e09245d14b69b1b37478435951d28faa3f7b2 Merge: d3d4cec f6ba43d Author: Ernest Micklei Date: Fri Mar 10 07:19:02 2017 +0100 Merge branch 'issue3' of https://github.com/emicklei/proto into issue3 commit d3d4cec4f26686191a74fcf498a6ee80c8eeeb92 Author: Ernest Micklei Date: Thu Mar 9 22:01:01 2017 +0100 Revert "add example to unformatted, begin change parse rpc" This reverts commit 94eb5561ab0bf068e77ebc482b4fecc808110b4d. commit d3e1bd51a376fe248a07195a453a44c0ea75c3e6 Author: Ernest Micklei Date: Thu Mar 9 21:59:28 2017 +0100 work on issue #3 commit f6ba43d792c27f895e72d43e9f5a90449dad6b18 Author: Ernest Micklei Date: Thu Mar 9 22:01:01 2017 +0100 Revert "add example to unformatted, begin change parse rpc" This reverts commit 94eb5561ab0bf068e77ebc482b4fecc808110b4d. commit a1563274bd1ed150e999077dfe7dbcb1b1484d17 Author: Ernest Micklei Date: Thu Mar 9 21:59:28 2017 +0100 work on issue #3 --- cmd/protofmt/format.sh | 4 + cmd/protofmt/unformatted.proto | 65 -- cmd/protofmt/unittest_proto2_formatted.proto | 841 ++++++++++++++++++ .../unittest_proto3_arena_formatted.proto | 193 ++++ cmd/protofmt/unittest_proto3_formatted.proto | 363 ++++++++ field_test.go | 8 +- formatter.go | 7 +- formatter_test.go | 58 +- message_test.go | 8 +- option.go | 52 +- option_test.go | 32 +- parser.go | 10 +- proto_test.go | 12 +- scanner.go | 14 + service_test.go | 44 +- token.go | 9 +- 16 files changed, 1604 insertions(+), 116 deletions(-) create mode 100755 cmd/protofmt/format.sh delete mode 100644 cmd/protofmt/unformatted.proto create mode 100644 cmd/protofmt/unittest_proto2_formatted.proto create mode 100644 cmd/protofmt/unittest_proto3_arena_formatted.proto create mode 100644 cmd/protofmt/unittest_proto3_formatted.proto diff --git a/cmd/protofmt/format.sh b/cmd/protofmt/format.sh new file mode 100755 index 0000000..367623c --- /dev/null +++ b/cmd/protofmt/format.sh @@ -0,0 +1,4 @@ +go install +protofmt unittest_proto2.proto > unittest_proto2_formatted.proto +protofmt unittest_proto3.proto > unittest_proto3_formatted.proto +protofmt unittest_proto3_arena.proto > unittest_proto3_arena_formatted.proto \ No newline at end of file diff --git a/cmd/protofmt/unformatted.proto b/cmd/protofmt/unformatted.proto deleted file mode 100644 index 92fcf3c..0000000 --- a/cmd/protofmt/unformatted.proto +++ /dev/null @@ -1,65 +0,0 @@ -// example0 -syntax = "proto3"; - - // using Any -import "google/protobuf/any.proto"; - -import public "testdata/test.proto"; // not weak - -/* This pkg - */ -package here.proto_proto ; // pkg - -// from a bottle -message Message -{ - string name =1; -// this is a thing - google.protobuf.Any anything = 2 [packed=true, danger=false]; // anything - - repeated - Message - children - = 3; - - enum Humour { - // something we dont know - UNKNOWN = 0; - PUNS = 1; - SLAPSTICK = 2; - /* who is this? */ - BILL_BAILEY = 3; - } - -reserved 2, 15, 9 to 11; -reserved "foo", "bar"; // foo bar - -extensions 100 to 199; // no 200 - - map terrain = 4; // terrain - - enum EnumAllowingAlias { - option allow_alias = true; // allow_alias - UNKNOWN = 0; // UNKNOWN - STARTED = 1; - RUN = 2 [(custom_option) = "hello world"]; -} -} // end message - -service SearchService { // comment - rpc Search ( SearchRequest ) returns ( SearchResponse ); // Search - rpc Find ( Finder ) returns ( stream Result ) {}; // Find - } - -// emptiness -enum Enum {} -service Service {} -message Message {} - -// context aware -enum enum { - enum = 0; // enum -} -message message { - sometype message = 1; // message -} \ No newline at end of file diff --git a/cmd/protofmt/unittest_proto2_formatted.proto b/cmd/protofmt/unittest_proto2_formatted.proto new file mode 100644 index 0000000..9f552c1 --- /dev/null +++ b/cmd/protofmt/unittest_proto2_formatted.proto @@ -0,0 +1,841 @@ + +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file we will use for unit testing. +syntax = "proto2"; + +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option cc_generic_services = true; // auto-added +option java_generic_services = true; // auto-added +option py_generic_services = true; // auto-added +option cc_enable_arenas = true; + +import "google/protobuf/unittest_import.proto"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +// In test_util.h we do "using namespace unittest = protobuf_unittest". +package protobuf_unittest; + +// Protos optimized for SPEED use a strict superset of the generated code +// of equivalent ones optimized for CODE_SIZE, so we should optimize all our +// tests for speed unless explicitly testing code size optimization. +option optimize_for = SPEED; +option java_outer_classname = "UnittestProto"; + +// This proto includes every type of field in both singular and repeated +// forms. +message TestAllTypes { + message NestedMessage { + + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + optional int32 bb = 1; + } + enum NestedEnum { + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + optional int32 optional_int32 = 1; + optional int64 optional_int64 = 2; + optional uint32 optional_uint32 = 3; + optional uint64 optional_uint64 = 4; + optional sint32 optional_sint32 = 5; + optional sint64 optional_sint64 = 6; + optional fixed32 optional_fixed32 = 7; + optional fixed64 optional_fixed64 = 8; + optional sfixed32 optional_sfixed32 = 9; + optional sfixed64 optional_sfixed64 = 10; + optional float optional_float = 11; + optional double optional_double = 12; + optional bool optional_bool = 13; + optional string optional_string = 14; + optional bytes optional_bytes = 15; + optional group OptionalGroup = 16 { + optional int32 a = 17; + } + optional NestedMessage optional_nested_message = 18; + optional ForeignMessage optional_foreign_message = 19; + optional protobuf_unittest_import.ImportMessage optional_import_message = 20; + optional NestedEnum optional_nested_enum = 21; + optional ForeignEnum optional_foreign_enum = 22; + optional protobuf_unittest_import.ImportEnum optional_import_enum = 23; + optional string optional_string_piece = 24 [ctype = STRING_PIECE]; + optional string optional_cord = 25 [ctype = CORD ]; + + // Defined in unittest_import_public.proto + optional protobuf_unittest_import.PublicImportMessage optional_public_import_message = 26; + optional NestedMessage optional_lazy_message = 27 [lazy = true]; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + group RepeatedGroup = 46 { + optional int32 a = 47; + } + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50; + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53; + repeated string repeated_string_piece = 54 [ctype = STRING_PIECE]; + repeated string repeated_cord = 55 [ctype = CORD ]; + repeated NestedMessage repeated_lazy_message = 57 [lazy = true ]; + + // Singular with defaults + optional int32 default_int32 = 61 [default = 41 ] ; + optional int64 default_int64 = 62 [default = 42 ] ; + optional uint32 default_uint32 = 63 [default = 43 ] ; + optional uint64 default_uint64 = 64 [default = 44 ] ; + optional sint32 default_sint32 = 65 [default = -45 ] ; + optional sint64 default_sint64 = 66 [default = 46 ] ; + optional fixed32 default_fixed32 = 67 [default = 47 ] ; + optional fixed64 default_fixed64 = 68 [default = 48 ] ; + optional sfixed32 default_sfixed32 = 69 [default = 49 ] ; + optional sfixed64 default_sfixed64 = 70 [default = -50 ] ; + optional float default_float = 71 [default = 51.5 ] ; + optional double default_double = 72 [default = 52e3 ] ; + optional bool default_bool = 73 [default = true ] ; + optional string default_string = 74 [default = "hello" ] ; + optional bytes default_bytes = 75 [default = "world" ] ; + optional NestedEnum default_nested_enum = 81 [default = BAR ] ; + optional ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR ] ; + optional protobuf_unittest_import.ImportEnum default_import_enum = 83 [default = IMPORT_BAR ] ; + optional string default_string_piece = 84 [ctype = STRING_PIECE, default = "abc"]; + optional string default_cord = 85 [ctype = CORD , default = "123"]; + + // For oneof test + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } +} + +// This proto includes a recusively nested message. +message NestedTestAllTypes { + optional NestedTestAllTypes child = 1; + optional TestAllTypes payload = 2; + repeated NestedTestAllTypes repeated_child = 3; +} +message TestDeprecatedFields { + optional int32 deprecated_int32 = 1 [deprecated = true]; +} + +// Define these after TestAllTypes to make sure the compiler can handle +// that. +message ForeignMessage { + optional int32 c = 1; + optional int32 d = 2; +} + +enum ForeignEnum { + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; +} + +message TestReservedFields { + reserved 2, 15, 9 to 11; + reserved "bar", "baz"; +} +message TestAllExtensions { + extensions 1 to max; +} +extend TestAllExtensions { + + // Singular + optional int32 optional_int32_extension = 1; + optional int64 optional_int64_extension = 2; + optional uint32 optional_uint32_extension = 3; + optional uint64 optional_uint64_extension = 4; + optional sint32 optional_sint32_extension = 5; + optional sint64 optional_sint64_extension = 6; + optional fixed32 optional_fixed32_extension = 7; + optional fixed64 optional_fixed64_extension = 8; + optional sfixed32 optional_sfixed32_extension = 9; + optional sfixed64 optional_sfixed64_extension = 10; + optional float optional_float_extension = 11; + optional double optional_double_extension = 12; + optional bool optional_bool_extension = 13; + optional string optional_string_extension = 14; + optional bytes optional_bytes_extension = 15; + optional group OptionalGroup_extension = 16 { + optional int32 a = 17; + } + optional TestAllTypes.NestedMessage optional_nested_message_extension = 18; + optional ForeignMessage optional_foreign_message_extension = 19; + optional protobuf_unittest_import.ImportMessage optional_import_message_extension = 20; + optional TestAllTypes.NestedEnum optional_nested_enum_extension = 21; + optional ForeignEnum optional_foreign_enum_extension = 22; + optional protobuf_unittest_import.ImportEnum optional_import_enum_extension = 23; + optional string optional_string_piece_extension = 24 [ctype = STRING_PIECE]; + optional string optional_cord_extension = 25 [ctype = CORD ]; + optional protobuf_unittest_import.PublicImportMessage optional_public_import_message_extension = 26; + optional TestAllTypes.NestedMessage optional_lazy_message_extension = 27 [lazy = true ]; + + // Repeated + repeated int32 repeated_int32_extension = 31; + repeated int64 repeated_int64_extension = 32; + repeated uint32 repeated_uint32_extension = 33; + repeated uint64 repeated_uint64_extension = 34; + repeated sint32 repeated_sint32_extension = 35; + repeated sint64 repeated_sint64_extension = 36; + repeated fixed32 repeated_fixed32_extension = 37; + repeated fixed64 repeated_fixed64_extension = 38; + repeated sfixed32 repeated_sfixed32_extension = 39; + repeated sfixed64 repeated_sfixed64_extension = 40; + repeated float repeated_float_extension = 41; + repeated double repeated_double_extension = 42; + repeated bool repeated_bool_extension = 43; + repeated string repeated_string_extension = 44; + repeated bytes repeated_bytes_extension = 45; + group RepeatedGroup_extension = 46 { + optional int32 a = 47; + } + repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 48; + repeated ForeignMessage repeated_foreign_message_extension = 49; + repeated protobuf_unittest_import.ImportMessage repeated_import_message_extension = 50; + repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51; + repeated ForeignEnum repeated_foreign_enum_extension = 52; + repeated protobuf_unittest_import.ImportEnum repeated_import_enum_extension = 53; + repeated string repeated_string_piece_extension = 54 [ctype = STRING_PIECE]; + repeated string repeated_cord_extension = 55 [ctype = CORD ]; + repeated TestAllTypes.NestedMessage repeated_lazy_message_extension = 57 [lazy = true ]; + + // Singular with defaults + optional int32 default_int32_extension = 61 [default = 41 ] ; + optional int64 default_int64_extension = 62 [default = 42 ] ; + optional uint32 default_uint32_extension = 63 [default = 43 ] ; + optional uint64 default_uint64_extension = 64 [default = 44 ] ; + optional sint32 default_sint32_extension = 65 [default = -45 ] ; + optional sint64 default_sint64_extension = 66 [default = 46 ] ; + optional fixed32 default_fixed32_extension = 67 [default = 47 ] ; + optional fixed64 default_fixed64_extension = 68 [default = 48 ] ; + optional sfixed32 default_sfixed32_extension = 69 [default = 49 ] ; + optional sfixed64 default_sfixed64_extension = 70 [default = -50 ] ; + optional float default_float_extension = 71 [default = 51.5 ] ; + optional double default_double_extension = 72 [default = 52e3 ] ; + optional bool default_bool_extension = 73 [default = true ] ; + optional string default_string_extension = 74 [default = "hello" ] ; + optional bytes default_bytes_extension = 75 [default = "world" ] ; + optional TestAllTypes.NestedEnum default_nested_enum_extension = 81 [default = BAR ] ; + optional ForeignEnum default_foreign_enum_extension = 82 [default = FOREIGN_BAR ] ; + optional protobuf_unittest_import.ImportEnum default_import_enum_extension = 83 [default = IMPORT_BAR ] ; + optional string default_string_piece_extension = 84 [ctype = STRING_PIECE, default = "abc"]; + optional string default_cord_extension = 85 [ctype = CORD , default = "123"]; + + // For oneof test + optional uint32 oneof_uint32_extension = 111; + optional TestAllTypes.NestedMessage oneof_nested_message_extension = 112; + optional string oneof_string_extension = 113; + optional bytes oneof_bytes_extension = 114; +} +message TestNestedExtension { + extend TestAllExtensions { + + // Check for bug where string extensions declared in tested scope did not + // compile. + optional string test = 1002 [default = "test"]; + + // Used to test if generated extension name is correct when there are + // underscores. + optional string nested_string_extension = 1003; + } +} + +// We have separate messages for testing required fields because it's +// annoying to have to fill in required fields in TestProto in order to +// do anything with it. Note that we don't need to test every type of +// required filed because the code output is basically identical to +// optional fields for all types. +message TestRequired { + int32 a = 1; + optional int32 dummy2 = 2; + int32 b = 3; + extend TestAllExtensions { + optional TestRequired single = 1000; + repeated TestRequired multi = 1001; + } + + // Pad the field count to 32 so that we can test that IsInitialized() + // properly checks multiple elements of has_bits_. + optional int32 dummy4 = 4; + optional int32 dummy5 = 5; + optional int32 dummy6 = 6; + optional int32 dummy7 = 7; + optional int32 dummy8 = 8; + optional int32 dummy9 = 9; + optional int32 dummy10 = 10; + optional int32 dummy11 = 11; + optional int32 dummy12 = 12; + optional int32 dummy13 = 13; + optional int32 dummy14 = 14; + optional int32 dummy15 = 15; + optional int32 dummy16 = 16; + optional int32 dummy17 = 17; + optional int32 dummy18 = 18; + optional int32 dummy19 = 19; + optional int32 dummy20 = 20; + optional int32 dummy21 = 21; + optional int32 dummy22 = 22; + optional int32 dummy23 = 23; + optional int32 dummy24 = 24; + optional int32 dummy25 = 25; + optional int32 dummy26 = 26; + optional int32 dummy27 = 27; + optional int32 dummy28 = 28; + optional int32 dummy29 = 29; + optional int32 dummy30 = 30; + optional int32 dummy31 = 31; + optional int32 dummy32 = 32; + int32 c = 33; +} +message TestRequiredForeign { + optional TestRequired optional_message = 1; + repeated TestRequired repeated_message = 2; + optional int32 dummy = 3; +} + +// Test that we can use NestedMessage from outside TestAllTypes. +message TestForeignNested { + optional TestAllTypes.NestedMessage foreign_nested = 1; +} + +// TestEmptyMessage is used to test unknown field support. +message TestEmptyMessage {} + +// Like above, but declare all field numbers as potential extensions. No +// actual extensions should ever be defined for this type. +message TestEmptyMessageWithExtensions { + extensions 1 to max; +} +message TestMultipleExtensionRanges { + extensions 42; + extensions 4143 to 4243; + extensions 65536 to max; +} + +// Test that really large tag numbers don't break anything. +message TestReallyLargeTagNumber { + + // The largest possible tag number is 2^28 - 1, since the wire format uses + // three bits to communicate wire type. + optional int32 a = 1; + optional int32 bb = 268435455; +} +message TestRecursiveMessage { + optional TestRecursiveMessage a = 1; + optional int32 i = 2; +} + +// Test that mutual recursion works. +message TestMutualRecursionA { + optional TestMutualRecursionB bb = 1; +} +message TestMutualRecursionB { + optional TestMutualRecursionA a = 1; + optional int32 optional_int32 = 2; +} + +// Test that groups have disjoint field numbers from their siblings and +// parents. This is NOT possible in proto1; only google.protobuf. When attempting +// to compile with proto1, this will emit an error; so we only include it +// in protobuf_unittest_proto. +message TestDupFieldNumber { + + // NO_PROTO1 + optional int32 a = 1; // NO_PROTO1 + optional group Foo = 2 { + optional int32 a = 1; + } + + // NO_PROTO1 + optional group Bar = 3 { + optional int32 a = 1; + } + + // NO_PROTO1 +} + +// NO_PROTO1 +// Additional messages for testing lazy fields. +message TestEagerMessage { + optional TestAllTypes sub_message = 1 [lazy = false]; +} +message TestLazyMessage { + optional TestAllTypes sub_message = 1 [lazy = true]; +} + +// Needed for a Python test. +message TestNestedMessageHasBits { + message NestedMessage { + repeated int32 nestedmessage_repeated_int32 = 1; + repeated ForeignMessage nestedmessage_repeated_foreignmessage = 2; + } + optional NestedMessage optional_nested_message = 1; +} + +// Test an enum that has multiple values with the same number. +enum TestEnumWithDupValue { + option allow_alias = true; + FOO1 = 1; + BAR1 = 2; + BAZ = 3; + FOO2 = 1; + BAR2 = 2; +} + +// Test an enum with large, unordered values. +enum TestSparseEnum { + SPARSE_A = 123; + SPARSE_B = 62374; + SPARSE_C = 12589234; + SPARSE_D = -15; + SPARSE_E = -53452; + SPARSE_F = 0; + SPARSE_G = 2; +} + +// Test message with CamelCase field names. This violates Protocol Buffer +// standard style. +message TestCamelCaseFieldNames { + optional int32 PrimitiveField = 1; + optional string StringField = 2; + optional ForeignEnum EnumField = 3; + optional ForeignMessage MessageField = 4; + optional string StringPieceField = 5 [ctype = STRING_PIECE]; + optional string CordField = 6 [ctype = CORD ]; + repeated int32 RepeatedPrimitiveField = 7; + repeated string RepeatedStringField = 8; + repeated ForeignEnum RepeatedEnumField = 9; + repeated ForeignMessage RepeatedMessageField = 10; + repeated string RepeatedStringPieceField = 11 [ctype = STRING_PIECE]; + repeated string RepeatedCordField = 12 [ctype = CORD ]; +} + +// We list fields out of order, to ensure that we're using field number and not +// field index to determine serialization order. +message TestFieldOrderings { + optional string my_string = 11; + extensions 2 to 10; + optional int64 my_int = 1; + extensions 12 to 100; + optional float my_float = 101; + message NestedMessage { + optional int64 oo = 2; + + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + optional int32 bb = 1; + } + optional NestedMessage optional_nested_message = 200; +} +extend TestFieldOrderings { + optional string my_extension_string = 50; + optional int32 my_extension_int = 5; +} +message TestExtremeDefaultValues { + optional bytes escaped_bytes = 1 [default = "\0\001\a\b\f\n\r\t\v\\\'\"\xfe"]; + optional uint32 large_uint32 = 2 [default = 0xFFFFFFFF ]; + optional uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF ]; + optional int32 small_int32 = 4 [default = -0x7FFFFFFF ]; + optional int64 small_int64 = 5 [default = -0x7FFFFFFFFFFFFFFF ]; + optional int32 really_small_int32 = 21 [default = -0x80000000 ]; + optional int64 really_small_int64 = 22 [default = -0x8000000000000000 ]; + + // The default value here is UTF-8 for "\u1234". (We could also just type + // the UTF-8 text directly into this text file rather than escape it, but + // lots of people use editors that would be confused by this.) + optional string utf8_string = 6 [default = "\341\210\264"]; + + // Tests for single-precision floating-point values. + optional float zero_float = 7 [default = 0 ]; + optional float one_float = 8 [default = 1 ]; + optional float small_float = 9 [default = 1.5 ]; + optional float negative_one_float = 10 [default = -1 ]; + optional float negative_float = 11 [default = -1.5]; + + // Using exponents + optional float large_float = 12 [default = 2E8 ]; + optional float small_negative_float = 13 [default = -8e-28]; + + // Text for nonfinite floating-point values. + optional double inf_double = 14 [default = inf ]; + optional double neg_inf_double = 15 [default = -inf]; + optional double nan_double = 16 [default = nan ]; + optional float inf_float = 17 [default = inf ]; + optional float neg_inf_float = 18 [default = -inf]; + optional float nan_float = 19 [default = nan ]; + + // Tests for C++ trigraphs. + // Trigraphs should be escaped in C++ generated files, but they should not be + // escaped for other languages. + // Note that in .proto file, "\?" is a valid way to escape ? in string + // literals. + optional string cpp_trigraph = 20 [default = "? \? ?? \?? \??? ??/ ?\?-"]; + + // String defaults containing the character '\000' + optional string string_with_zero = 23 [default = "hel\000lo" ] ; + optional bytes bytes_with_zero = 24 [default = "wor\000ld" ] ; + optional string string_piece_with_zero = 25 [ctype = STRING_PIECE, default = "ab\000c"]; + optional string cord_with_zero = 26 [ctype = CORD , default = "12\0003"]; + optional string replacement_string = 27 [default = "${unknown}"] ; +} +message SparseEnumMessage { + optional TestSparseEnum sparse_enum = 1; +} + +// Test String and Bytes: string is for valid UTF-8 strings +message OneString { + optional string data = 1; +} +message MoreString { + repeated string data = 1; +} +message OneBytes { + optional bytes data = 1; +} +message MoreBytes { + repeated bytes data = 1; +} + +// Test int32, uint32, int64, uint64, and bool are all compatible +message Int32Message { + optional int32 data = 1; +} +message Uint32Message { + optional uint32 data = 1; +} +message Int64Message { + optional int64 data = 1; +} +message Uint64Message { + optional uint64 data = 1; +} +message BoolMessage { + optional bool data = 1; +} + +// Test oneofs. +message TestOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + TestAllTypes foo_message = 3; + group FooGroup = 4 { + optional int32 a = 5; + optional string b = 6; + } + } +} +message TestOneofBackwardsCompatible { + optional int32 foo_int = 1; + optional string foo_string = 2; + optional TestAllTypes foo_message = 3; + optional group FooGroup = 4 { + optional int32 a = 5; + optional string b = 6; + } +} +message TestOneof2 { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + string foo_cord = 3 [ctype = CORD ]; + string foo_string_piece = 4 [ctype = STRING_PIECE]; + bytes foo_bytes = 5; + NestedEnum foo_enum = 6; + NestedMessage foo_message = 7; + group FooGroup = 8 { + optional int32 a = 9; + optional string b = 10; + } + NestedMessage foo_lazy_message = 11 [lazy = true]; + } + oneof bar { + int32 bar_int = 12 [default = 5 ] ; + string bar_string = 13 [default = "STRING" ] ; + string bar_cord = 14 [ctype = CORD , default = "CORD" ]; + string bar_string_piece = 15 [ctype = STRING_PIECE, default = "SPIECE"]; + bytes bar_bytes = 16 [default = "BYTES" ] ; + NestedEnum bar_enum = 17 [default = BAR ] ; + } + optional int32 baz_int = 18; + optional string baz_string = 19 [default = "BAZ"]; + message NestedMessage { + optional int64 qux_int = 1; + repeated int32 corge_int = 2; + } + enum NestedEnum { + FOO = 1; + BAR = 2; + BAZ = 3; + } +} +message TestRequiredOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + NestedMessage foo_message = 3; + } + message NestedMessage { + double required_double = 1; + } +} + +// Test messages for packed fields +message TestPackedTypes { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnum packed_enum = 103 [packed = true]; +} + +// A message with the same fields as TestPackedTypes, but without packing. Used +// to test packed <-> unpacked wire compatibility. +message TestUnpackedTypes { + repeated int32 unpacked_int32 = 90 [packed = false]; + repeated int64 unpacked_int64 = 91 [packed = false]; + repeated uint32 unpacked_uint32 = 92 [packed = false]; + repeated uint64 unpacked_uint64 = 93 [packed = false]; + repeated sint32 unpacked_sint32 = 94 [packed = false]; + repeated sint64 unpacked_sint64 = 95 [packed = false]; + repeated fixed32 unpacked_fixed32 = 96 [packed = false]; + repeated fixed64 unpacked_fixed64 = 97 [packed = false]; + repeated sfixed32 unpacked_sfixed32 = 98 [packed = false]; + repeated sfixed64 unpacked_sfixed64 = 99 [packed = false]; + repeated float unpacked_float = 100 [packed = false]; + repeated double unpacked_double = 101 [packed = false]; + repeated bool unpacked_bool = 102 [packed = false]; + repeated ForeignEnum unpacked_enum = 103 [packed = false]; +} +message TestPackedExtensions { + extensions 1 to max; +} +extend TestPackedExtensions { + repeated int32 packed_int32_extension = 90 [packed = true]; + repeated int64 packed_int64_extension = 91 [packed = true]; + repeated uint32 packed_uint32_extension = 92 [packed = true]; + repeated uint64 packed_uint64_extension = 93 [packed = true]; + repeated sint32 packed_sint32_extension = 94 [packed = true]; + repeated sint64 packed_sint64_extension = 95 [packed = true]; + repeated fixed32 packed_fixed32_extension = 96 [packed = true]; + repeated fixed64 packed_fixed64_extension = 97 [packed = true]; + repeated sfixed32 packed_sfixed32_extension = 98 [packed = true]; + repeated sfixed64 packed_sfixed64_extension = 99 [packed = true]; + repeated float packed_float_extension = 100 [packed = true]; + repeated double packed_double_extension = 101 [packed = true]; + repeated bool packed_bool_extension = 102 [packed = true]; + repeated ForeignEnum packed_enum_extension = 103 [packed = true]; +} +message TestUnpackedExtensions { + extensions 1 to max; +} +extend TestUnpackedExtensions { + repeated int32 unpacked_int32_extension = 90 [packed = false]; + repeated int64 unpacked_int64_extension = 91 [packed = false]; + repeated uint32 unpacked_uint32_extension = 92 [packed = false]; + repeated uint64 unpacked_uint64_extension = 93 [packed = false]; + repeated sint32 unpacked_sint32_extension = 94 [packed = false]; + repeated sint64 unpacked_sint64_extension = 95 [packed = false]; + repeated fixed32 unpacked_fixed32_extension = 96 [packed = false]; + repeated fixed64 unpacked_fixed64_extension = 97 [packed = false]; + repeated sfixed32 unpacked_sfixed32_extension = 98 [packed = false]; + repeated sfixed64 unpacked_sfixed64_extension = 99 [packed = false]; + repeated float unpacked_float_extension = 100 [packed = false]; + repeated double unpacked_double_extension = 101 [packed = false]; + repeated bool unpacked_bool_extension = 102 [packed = false]; + repeated ForeignEnum unpacked_enum_extension = 103 [packed = false]; +} + +// Used by ExtensionSetTest/DynamicExtensions. The test actually builds +// a set of extensions to TestAllExtensions dynamically, based on the fields +// of this message type. +message TestDynamicExtensions { + enum DynamicEnumType { + DYNAMIC_FOO = 2200; + DYNAMIC_BAR = 2201; + DYNAMIC_BAZ = 2202; + } + message DynamicMessageType { + optional int32 dynamic_field = 2100; + } + optional fixed32 scalar_extension = 2000; + optional ForeignEnum enum_extension = 2001; + optional DynamicEnumType dynamic_enum_extension = 2002; + optional ForeignMessage message_extension = 2003; + optional DynamicMessageType dynamic_message_extension = 2004; + repeated string repeated_extension = 2005; + repeated sint32 packed_extension = 2006 [packed = true]; +} +message TestRepeatedScalarDifferentTagSizes { + + // Parsing repeated fixed size values used to fail. This message needs to be + // used in order to get a tag of the right size; all of the repeated fields + // in TestAllTypes didn't trigger the check. + repeated fixed32 repeated_fixed32 = 12; + + // Check for a varint type, just for good measure. + repeated int32 repeated_int32 = 13; + + // These have two-byte tags. + repeated fixed64 repeated_fixed64 = 2046; + repeated int64 repeated_int64 = 2047; + + // Three byte tags. + repeated float repeated_float = 262142; + repeated uint64 repeated_uint64 = 262143; +} + +// Test that if an optional or required message/group field appears multiple +// times in the input, they need to be merged. +message TestParsingMerge { + + // RepeatedFieldsGenerator defines matching field types as TestParsingMerge, + // except that all fields are repeated. In the tests, we will serialize the + // RepeatedFieldsGenerator to bytes, and parse the bytes to TestParsingMerge. + // Repeated fields in RepeatedFieldsGenerator are expected to be merged into + // the corresponding required/optional fields in TestParsingMerge. + message RepeatedFieldsGenerator { + repeated TestAllTypes field1 = 1; + repeated TestAllTypes field2 = 2; + repeated TestAllTypes field3 = 3; + group Group1 = 10 { + optional TestAllTypes field1 = 11; + } + group Group2 = 20 { + optional TestAllTypes field1 = 21; + } + repeated TestAllTypes ext1 = 1000; + repeated TestAllTypes ext2 = 1001; + } + TestAllTypes required_all_types = 1; + optional TestAllTypes optional_all_types = 2; + repeated TestAllTypes repeated_all_types = 3; + optional group OptionalGroup = 10 { + optional TestAllTypes optional_group_all_types = 11; + } + group RepeatedGroup = 20 { + optional TestAllTypes repeated_group_all_types = 21; + } + extensions 1000 to max; + extend TestParsingMerge { + optional TestAllTypes optional_ext = 1000; + repeated TestAllTypes repeated_ext = 1001; + } +} +message TestCommentInjectionMessage { + + // */ <- This should not close the generated doc comment + optional string a = 1 [default = "*/ <- Neither should this."]; +} + +// Test that RPC services work. +message FooRequest {} +message FooResponse {} +message FooClientMessage {} +message FooServerMessage {} + +service TestService { + rpc Foo (FooRequest) returns (FooResponse); + rpc Bar (BarRequest) returns (BarResponse); +} + +message BarRequest {} +message BarResponse {} +message TestJsonName { + optional int32 field_name1 = 1; + optional int32 fieldName2 = 2; + optional int32 FieldName3 = 3; + optional int32 _field_name4 = 4; + optional int32 FIELD_NAME5 = 5; + optional int32 field_name6 = 6 [json_name = "@type"]; +} +message TestHugeFieldNumbers { + optional int32 optional_int32 = 536870000; + optional int32 fixed_32 = 536870001; + repeated int32 repeated_int32 = 536870002 [packed = false]; + repeated int32 packed_int32 = 536870003 [packed = true ]; + optional ForeignEnum optional_enum = 536870004; + optional string optional_string = 536870005; + optional bytes optional_bytes = 536870006; + optional ForeignMessage optional_message = 536870007; + optional group OptionalGroup = 536870008 { + optional int32 group_a = 536870009; + } + map string_string_map = 536870010; + oneof oneof_field { + uint32 oneof_uint32 = 536870011; + TestAllTypes oneof_test_all_types = 536870012; + string oneof_string = 536870013; + bytes oneof_bytes = 536870014; + } + extensions 536860000 to 536869999; +} +extend TestHugeFieldNumbers { + optional TestAllTypes test_all_types = 536860000; +} diff --git a/cmd/protofmt/unittest_proto3_arena_formatted.proto b/cmd/protofmt/unittest_proto3_arena_formatted.proto new file mode 100644 index 0000000..161f578 --- /dev/null +++ b/cmd/protofmt/unittest_proto3_arena_formatted.proto @@ -0,0 +1,193 @@ + +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto"; + +option cc_enable_arenas = true; + +import "google/protobuf/unittest_import.proto"; + +package proto_arena_unittest; + +// This proto includes every type of field in both singular and repeated +// forms. +message TestAllTypes { + message NestedMessage { + + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + enum NestedEnum { + ZERO = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + + // Groups are not allowed in proto. + // optional group OptionalGroup = 16 { + // optional int32 a = 17; + // } + NestedMessage optional_nested_message = 18; + ForeignMessage optional_foreign_message = 19; + protobuf_unittest_import.ImportMessage optional_import_message = 20; + NestedEnum optional_nested_enum = 21; + ForeignEnum optional_foreign_enum = 22; + + // Omitted (compared to unittest.proto) because proto2 enums are not allowed + // inside proto2 messages. + // + // optional protobuf_unittest_import.ImportEnum optional_import_enum = 23; + string optional_string_piece = 24 [ctype = STRING_PIECE]; + string optional_cord = 25 [ctype = CORD ]; + + // Defined in unittest_import_public.proto + protobuf_unittest_import.PublicImportMessage optional_public_import_message = 26; + NestedMessage optional_lazy_message = 27 [lazy = true]; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + // Groups are not allowed in proto. + // repeated group RepeatedGroup = 46 { + // optional int32 a = 47; + // } + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50; + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + + // Omitted (compared to unittest.proto) because proto2 enums are not allowed + // inside proto2 messages. + // + // repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53; + repeated string repeated_string_piece = 54 [ctype = STRING_PIECE]; + repeated string repeated_cord = 55 [ctype = CORD ]; + repeated NestedMessage repeated_lazy_message = 57 [lazy = true ]; + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } +} + +// Test messages for packed fields +message TestPackedTypes { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnum packed_enum = 103 [packed = true]; +} + +// Explicitly set packed to false +message TestUnpackedTypes { + repeated int32 repeated_int32 = 1 [packed = false]; + repeated int64 repeated_int64 = 2 [packed = false]; + repeated uint32 repeated_uint32 = 3 [packed = false]; + repeated uint64 repeated_uint64 = 4 [packed = false]; + repeated sint32 repeated_sint32 = 5 [packed = false]; + repeated sint64 repeated_sint64 = 6 [packed = false]; + repeated fixed32 repeated_fixed32 = 7 [packed = false]; + repeated fixed64 repeated_fixed64 = 8 [packed = false]; + repeated sfixed32 repeated_sfixed32 = 9 [packed = false]; + repeated sfixed64 repeated_sfixed64 = 10 [packed = false]; + repeated float repeated_float = 11 [packed = false]; + repeated double repeated_double = 12 [packed = false]; + repeated bool repeated_bool = 13 [packed = false]; + repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 [packed = false]; +} + +// This proto includes a recusively nested message. +message NestedTestAllTypes { + NestedTestAllTypes child = 1; + TestAllTypes payload = 2; +} + +// Define these after TestAllTypes to make sure the compiler can handle +// that. +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_ZERO = 0; + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; +} + +// TestEmptyMessage is used to test behavior of unknown fields. +message TestEmptyMessage {} diff --git a/cmd/protofmt/unittest_proto3_formatted.proto b/cmd/protofmt/unittest_proto3_formatted.proto new file mode 100644 index 0000000..a21aa83 --- /dev/null +++ b/cmd/protofmt/unittest_proto3_formatted.proto @@ -0,0 +1,363 @@ + +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file we will use for unit testing. +syntax = "proto"; + +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option cc_generic_services = true; // auto-added +option java_generic_services = true; // auto-added +option py_generic_services = true; // auto-added +option cc_enable_arenas = true; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +import "google/protobuf/unittest_import_proto.proto"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +// In test_util.h we do "using namespace unittest = protobuf_unittest". +package protobuf_unittest; + +// Protos optimized for SPEED use a strict superset of the generated code +// of equivalent ones optimized for CODE_SIZE, so we should optimize all our +// tests for speed unless explicitly testing code size optimization. +option optimize_for = SPEED; +option java_outer_classname = "UnittestProto"; + +// This proto includes every type of field in both singular and repeated +// forms. +message TestAllTypes { + message NestedMessage { + + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + enum NestedEnum { + NESTED_ENUM_UNSPECIFIED = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 single_int32 = 1; + int64 single_int64 = 2; + uint32 single_uint32 = 3; + uint64 single_uint64 = 4; + sint32 single_sint32 = 5; + sint64 single_sint64 = 6; + fixed32 single_fixed32 = 7; + fixed64 single_fixed64 = 8; + sfixed32 single_sfixed32 = 9; + sfixed64 single_sfixed64 = 10; + float single_float = 11; + double single_double = 12; + bool single_bool = 13; + string single_string = 14; + bytes single_bytes = 15; + NestedMessage single_nested_message = 18; + ForeignMessage single_foreign_message = 19; + protobuf_unittest_import.ImportMessage single_import_message = 20; + NestedEnum single_nested_enum = 21; + ForeignEnum single_foreign_enum = 22; + protobuf_unittest_import.ImportEnum single_import_enum = 23; + + // Defined in unittest_import_public.proto + protobuf_unittest_import.PublicImportMessage single_public_import_message = 26; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50; + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53; + + // Defined in unittest_import_public.proto + repeated protobuf_unittest_import.PublicImportMessage repeated_public_import_message = 54; + + // For oneof test + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } +} + +// This proto includes a recusively nested message. +message NestedTestAllTypes { + NestedTestAllTypes child = 1; + TestAllTypes payload = 2; + repeated NestedTestAllTypes repeated_child = 3; +} +message TestDeprecatedFields { + int32 deprecated_int32 = 1 [deprecated = true]; +} + +// Define these after TestAllTypes to make sure the compiler can handle +// that. +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_UNSPECIFIED = 0; + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; +} + +message TestReservedFields { + reserved 2, 15, 9 to 11; + reserved "bar", "baz"; +} + +// Test that we can use NestedMessage from outside TestAllTypes. +message TestForeignNested { + TestAllTypes.NestedMessage foreign_nested = 1; +} + +// Test that really large tag numbers don't break anything. +message TestReallyLargeTagNumber { + + // The largest possible tag number is 2^28 - 1, since the wire format uses + // three bits to communicate wire type. + int32 a = 1; + int32 bb = 268435455; +} +message TestRecursiveMessage { + TestRecursiveMessage a = 1; + int32 i = 2; +} + +// Test that mutual recursion works. +message TestMutualRecursionA { + TestMutualRecursionB bb = 1; +} +message TestMutualRecursionB { + TestMutualRecursionA a = 1; + int32 optional_int32 = 2; +} + +// Test an enum that has multiple values with the same number. +enum TestEnumWithDupValue { + TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED = 0; + option allow_alias = true; + FOO1 = 1; + BAR1 = 2; + BAZ = 3; + FOO2 = 1; + BAR2 = 2; +} + +// Test an enum with large, unordered values. +enum TestSparseEnum { + TEST_SPARSE_ENUM_UNSPECIFIED = 0; + SPARSE_A = 123; + SPARSE_B = 62374; + SPARSE_C = 12589234; + SPARSE_D = -15; + SPARSE_E = -53452; + + // In proto, value 0 must be the first one specified + // SPARSE_F = 0; + SPARSE_G = 2; +} + +// Test message with CamelCase field names. This violates Protocol Buffer +// standard style. +message TestCamelCaseFieldNames { + int32 PrimitiveField = 1; + string StringField = 2; + ForeignEnum EnumField = 3; + ForeignMessage MessageField = 4; + repeated int32 RepeatedPrimitiveField = 7; + repeated string RepeatedStringField = 8; + repeated ForeignEnum RepeatedEnumField = 9; + repeated ForeignMessage RepeatedMessageField = 10; +} + +// We list fields out of order, to ensure that we're using field number and not +// field index to determine serialization order. +message TestFieldOrderings { + string my_string = 11; + int64 my_int = 1; + float my_float = 101; + message NestedMessage { + int64 oo = 2; + + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + NestedMessage single_nested_message = 200; +} +message SparseEnumMessage { + TestSparseEnum sparse_enum = 1; +} + +// Test String and Bytes: string is for valid UTF-8 strings +message OneString { + string data = 1; +} +message MoreString { + repeated string data = 1; +} +message OneBytes { + bytes data = 1; +} +message MoreBytes { + bytes data = 1; +} + +// Test int32, uint32, int64, uint64, and bool are all compatible +message Int32Message { + int32 data = 1; +} +message Uint32Message { + uint32 data = 1; +} +message Int64Message { + int64 data = 1; +} +message Uint64Message { + uint64 data = 1; +} +message BoolMessage { + bool data = 1; +} + +// Test oneofs. +message TestOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + TestAllTypes foo_message = 3; + } +} + +// Test messages for packed fields +message TestPackedTypes { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnum packed_enum = 103 [packed = true]; +} + +// A message with the same fields as TestPackedTypes, but without packing. Used +// to test packed <-> unpacked wire compatibility. +message TestUnpackedTypes { + repeated int32 unpacked_int32 = 90 [packed = false]; + repeated int64 unpacked_int64 = 91 [packed = false]; + repeated uint32 unpacked_uint32 = 92 [packed = false]; + repeated uint64 unpacked_uint64 = 93 [packed = false]; + repeated sint32 unpacked_sint32 = 94 [packed = false]; + repeated sint64 unpacked_sint64 = 95 [packed = false]; + repeated fixed32 unpacked_fixed32 = 96 [packed = false]; + repeated fixed64 unpacked_fixed64 = 97 [packed = false]; + repeated sfixed32 unpacked_sfixed32 = 98 [packed = false]; + repeated sfixed64 unpacked_sfixed64 = 99 [packed = false]; + repeated float unpacked_float = 100 [packed = false]; + repeated double unpacked_double = 101 [packed = false]; + repeated bool unpacked_bool = 102 [packed = false]; + repeated ForeignEnum unpacked_enum = 103 [packed = false]; +} +message TestRepeatedScalarDifferentTagSizes { + + // Parsing repeated fixed size values used to fail. This message needs to be + // used in order to get a tag of the right size; all of the repeated fields + // in TestAllTypes didn't trigger the check. + repeated fixed32 repeated_fixed32 = 12; + + // Check for a varint type, just for good measure. + repeated int32 repeated_int32 = 13; + + // These have two-byte tags. + repeated fixed64 repeated_fixed64 = 2046; + repeated int64 repeated_int64 = 2047; + + // Three byte tags. + repeated float repeated_float = 262142; + repeated uint64 repeated_uint64 = 262143; +} +message TestCommentInjectionMessage { + + // */ <- This should not close the generated doc comment + string a = 1; +} + +// Test that RPC services work. +message FooRequest {} +message FooResponse {} +message FooClientMessage {} +message FooServerMessage {} + +service TestService { + rpc Foo (FooRequest) returns (FooResponse); + rpc Bar (BarRequest) returns (BarResponse); +} + +message BarRequest {} +message BarResponse {} diff --git a/field_test.go b/field_test.go index 091ffdb..fa20622 100644 --- a/field_test.go +++ b/field_test.go @@ -1,7 +1,7 @@ // Copyright (c) 2017 Ernest Micklei -// +// // MIT License -// +// // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including @@ -9,10 +9,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND diff --git a/formatter.go b/formatter.go index 1e293ea..43a2e87 100644 --- a/formatter.go +++ b/formatter.go @@ -94,7 +94,12 @@ func (f *Formatter) VisitImport(i *Import) {} // VisitMessage formats a Message. func (f *Formatter) VisitMessage(m *Message) { f.begin("message") - fmt.Fprintf(f.w, "message %s {", m.Name) + if m.IsExtend { + fmt.Fprintf(f.w, "extend ") + } else { + fmt.Fprintf(f.w, "message ") + } + fmt.Fprintf(f.w, "%s {", m.Name) if len(m.Elements) > 0 { f.nl() f.indentLevel++ diff --git a/formatter_test.go b/formatter_test.go index 0353b84..3913a90 100644 --- a/formatter_test.go +++ b/formatter_test.go @@ -1,7 +1,7 @@ // Copyright (c) 2017 Ernest Micklei -// +// // MIT License -// +// // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including @@ -9,10 +9,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -25,6 +25,7 @@ package proto import ( "bytes" + "fmt" "strings" "testing" ) @@ -93,9 +94,52 @@ message ConnectRequest { } } -func logformatted(t *testing.T, v Visitee) { +func logformatted(t *testing.T, v Visitee) string { b := new(bytes.Buffer) - f := NewFormatter(b, " ") + f := NewFormatter(b, " ") // 2 spaces v.Accept(f) - t.Log(b.String()) + return b.String() +} + +func TestExtendMessage(t *testing.T) { + proto := `extend google.protobuf.MessageOptions { optional string my_option = 51234; }` + p := newParserOn(proto) + p.scanIgnoreWhitespace() // consume first token + m := new(Message) + m.IsExtend = true + err := m.parse(p) + if err != nil { + t.Fatal(err) + } + if got, want := logformatted(t, m), ` +extend google.protobuf.MessageOptions { + optional string my_option = 51234; +} +`; got != want { + fmt.Println(diff(t, got, want)) + t.Fail() + } +} + +func diff(t *testing.T, left, right string) string { + b := new(bytes.Buffer) + w := func(char rune) { + if '\n' == char { + b.WriteString("(n)") + } else if '\t' == char { + b.WriteString("(t)") + } else if ' ' == char { + b.WriteString("( )") + } else { + b.WriteRune(char) + } + } + for _, char := range left { + w(char) + } + b.WriteString("\n") + for _, char := range right { + w(char) + } + return b.String() } diff --git a/message_test.go b/message_test.go index 783078f..abb7e40 100644 --- a/message_test.go +++ b/message_test.go @@ -1,7 +1,7 @@ // Copyright (c) 2017 Ernest Micklei -// +// // MIT License -// +// // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including @@ -9,10 +9,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND diff --git a/option.go b/option.go index 9d67321..4999047 100644 --- a/option.go +++ b/option.go @@ -1,7 +1,7 @@ // Copyright (c) 2017 Ernest Micklei -// +// // MIT License -// +// // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including @@ -9,10 +9,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -27,10 +27,11 @@ import "fmt" // Option is a protoc compiler option type Option struct { - Name string - Constant Literal - IsEmbedded bool - Comment *Comment + Name string + Constant Literal + IsEmbedded bool + Comment *Comment + AggregatedConstants map[string]*Literal } // inlineComment is part of commentInliner. @@ -111,6 +112,12 @@ func (o *Option) parse(p *Parser) error { if tEQUALS != tok { return p.unexpected(lit, "option constant =", o) } + p.s.skipWhitespace() + if p.s.peek('{') { + p.s.read() + return o.parseAggregate(p) + } + // non aggregate l := new(Literal) if err := l.parse(p); err != nil { return err @@ -138,3 +145,32 @@ func (l *Literal) parse(p *Parser) error { l.Source, l.IsString = p.s.scanLiteral() return nil } + +// parseAggregate reads options written using aggregate syntax +func (o *Option) parseAggregate(p *Parser) error { + o.AggregatedConstants = map[string]*Literal{} + for { + tok, lit := p.scanIgnoreWhitespace() + if tRIGHTCURLY == tok { + break + } + if tIDENT != tok { + return p.unexpected(lit, "option aggregate key", o) + } + key := lit + tok, lit = p.scanIgnoreWhitespace() + if tCOLON != tok { + return p.unexpected(lit, "option aggregate key colon :", o) + } + l := new(Literal) + if err := l.parse(p); err != nil { + return err + } + o.AggregatedConstants[key] = l + } + tok, lit := p.scanIgnoreWhitespace() + if tSEMICOLON != tok { + return p.unexpected(lit, "option aggregate end ;", o) + } + return nil +} diff --git a/option_test.go b/option_test.go index af490f9..7cc3395 100644 --- a/option_test.go +++ b/option_test.go @@ -1,7 +1,7 @@ // Copyright (c) 2017 Ernest Micklei -// +// // MIT License -// +// // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including @@ -9,10 +9,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -25,7 +25,7 @@ package proto import "testing" -func TestOption(t *testing.T) { +func TestOptionCases(t *testing.T) { for i, each := range []struct { proto string name string @@ -46,11 +46,16 @@ func TestOption(t *testing.T) { "Float", "", "-3.14E1", + }, { + `option (foo_options) = { opt1: 123 opt2: "baz" };`, + "(foo_options)", + "", + "", }} { p := newParserOn(each.proto) pr, err := p.Parse() if err != nil { - t.Fatal(err) + t.Fatal("testcase failed:", i, err) } if got, want := len(pr.Elements), 1; got != want { t.Fatalf("[%d] got [%v] want [%v]", i, got, want) @@ -74,3 +79,18 @@ func TestOption(t *testing.T) { } } } + +func TestLiteralString(t *testing.T) { + proto := `"string"` + p := newParserOn(proto) + l := new(Literal) + if err := l.parse(p); err != nil { + t.Fatal(err) + } + if got, want := l.IsString, true; got != want { + t.Errorf("got [%v] want [%v]", got, want) + } + if got, want := l.Source, "string"; got != want { + t.Errorf("got [%v] want [%v]", got, want) + } +} diff --git a/parser.go b/parser.go index ea3de87..1deb3ea 100644 --- a/parser.go +++ b/parser.go @@ -1,7 +1,7 @@ // Copyright (c) 2017 Ernest Micklei -// +// // MIT License -// +// // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including @@ -9,10 +9,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -92,5 +92,5 @@ func (p *Parser) unexpected(found, expected string, obj interface{}) error { _, file, line, _ := runtime.Caller(1) debug = fmt.Sprintf(" at %s:%d (with %#v)", file, line, obj) } - return fmt.Errorf("found %q on line %d, expected %s%s", found, p.s.line, expected, debug) + return fmt.Errorf("found %q on line %d, expected [%s]%s", found, p.s.line, expected, debug) } diff --git a/proto_test.go b/proto_test.go index 2e9a7bd..86b0164 100644 --- a/proto_test.go +++ b/proto_test.go @@ -1,7 +1,7 @@ // Copyright (c) 2017 Ernest Micklei -// +// // MIT License -// +// // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including @@ -9,10 +9,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -42,10 +42,6 @@ func TestParseFormattedProto3ArenaUnitTest(t *testing.T) { parseFormattedParsed(t, filepath.Join("cmd", "protofmt", "unittest_proto3_arena.proto")) } -func TestParseFormattedUnformatted(t *testing.T) { - parseFormattedParsed(t, filepath.Join("cmd", "protofmt", "unformatted.proto")) -} - func parseFormattedParsed(t *testing.T, filename string) { // open it f, err := os.Open(filename) diff --git a/scanner.go b/scanner.go index 9cf2c20..1d24704 100644 --- a/scanner.go +++ b/scanner.go @@ -66,6 +66,8 @@ func (s *scanner) scan() (tok token, lit string) { return tEOF, "" case ';': return tSEMICOLON, string(ch) + case ':': + return tCOLON, string(ch) case '=': return tEQUALS, string(ch) case '"': @@ -98,6 +100,18 @@ func (s *scanner) scan() (tok token, lit string) { return tILLEGAL, string(ch) } +// skipWhitespace consumes all whitespace until eof or a non-whitespace rune. +func (s *scanner) skipWhitespace() { + for { + if ch := s.read(); ch == eof { + break + } else if !isWhitespace(ch) { + s.unread(ch) + break + } + } +} + // scanWhitespace consumes the current rune and all contiguous whitespace. func (s *scanner) scanWhitespace() (tok token, lit string) { // Create a buffer and read the current character into it. diff --git a/service_test.go b/service_test.go index 75e4074..6dd4b27 100644 --- a/service_test.go +++ b/service_test.go @@ -1,7 +1,7 @@ // Copyright (c) 2017 Ernest Micklei -// +// // MIT License -// +// // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including @@ -9,10 +9,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -48,3 +48,39 @@ func TestService(t *testing.T) { t.Errorf("got [%v] want [%v]", got, want) } } + +func TestRPCWithOptionAggregateSyntax(t *testing.T) { + proto := `service AccountService { + rpc CreateAccount (CreateAccount) returns (ServiceFault){ + option (test_ident) = { + test: "test" + test2:"test2" + }; + } + }` + pr, err := newParserOn(proto).Parse() + if err != nil { + t.Fatal(err) + } + srv := collect(pr).Services()[0] + if got, want := len(srv.Elements), 1; got != want { + t.Errorf("got [%v] want [%v]", got, want) + } + rpc1 := srv.Elements[0].(*RPC) + if got, want := len(rpc1.Options), 1; got != want { + t.Errorf("got [%v] want [%v]", got, want) + } + opt := rpc1.Options[0] + if got, want := opt.Name, "(test_ident)"; got != want { + t.Errorf("got [%v] want [%v]", got, want) + } + if got, want := len(opt.AggregatedConstants), 2; got != want { + t.Fatalf("got [%v] want [%v]", got, want) + } + if got, want := opt.AggregatedConstants["test"].Source, "test"; got != want { + t.Errorf("got [%v] want [%v]", got, want) + } + if got, want := opt.AggregatedConstants["test2"].Source, "test2"; got != want { + t.Errorf("got [%v] want [%v]", got, want) + } +} diff --git a/token.go b/token.go index 200afef..0f6d198 100644 --- a/token.go +++ b/token.go @@ -1,7 +1,7 @@ // Copyright (c) 2017 Ernest Micklei -// +// // MIT License -// +// // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including @@ -9,10 +9,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -37,6 +37,7 @@ const ( // Misc characters tSEMICOLON // ; + tCOLON // : tEQUALS // = tQUOTE // " tSINGLEQUOTE // '