diff --git a/internal/bundles/assets/import_proto_cli.arraiz b/internal/bundles/assets/import_proto_cli.arraiz index db053f4a..e375ab4a 100644 Binary files a/internal/bundles/assets/import_proto_cli.arraiz and b/internal/bundles/assets/import_proto_cli.arraiz differ diff --git a/pkg/importer/importer_test.go b/pkg/importer/importer_test.go index a62092d5..e311dfef 100644 --- a/pkg/importer/importer_test.go +++ b/pkg/importer/importer_test.go @@ -219,6 +219,23 @@ func TestLoadProtobufFromTestFiles(t *testing.T) { }) } +func TestLoadProtobufTestErrors(t *testing.T) { + t.Parallel() + + runImportErrorTest(t, errTestConfig{ + testConfig: testConfig{ + name: "TestLoadProtobufTestErrors", + testDir: "proto/tests/errors", + testExtension: ".proto", + format: Protobuf.Name, + }, + + cases: map[string]string{ + "dulicate_enum": "enum with multiple names for value 0 found", + }, + }) +} + func TestLoadProtobufDirFromTestDir(t *testing.T) { runImportDirEqualityTests(t, testConfig{ name: "TestLoadProtobufDirFromTestDir", diff --git a/pkg/importer/proto/proto_to_sysl.arrai b/pkg/importer/proto/proto_to_sysl.arrai index b526ad82..40c04a2c 100644 --- a/pkg/importer/proto/proto_to_sysl.arrai +++ b/pkg/importer/proto/proto_to_sysl.arrai @@ -241,10 +241,21 @@ let type = \message \file \appName \imports \prefix # `enum` the enum being converted. # `file` the file the enum is located in. let enum = \enum \file + let fields = enum.@value.fields?:{} => (@: .@, @value: evalNumber(.@value.value), deprecated: .@value.options?('deprecated')?.b?:false); + let nested = fields nest|@,deprecated|e; ( name: syslSafeName(enum.@), attrs: baseAttrs(enum, file), - enum: (items: enum.@value.fields?:{} => (@: .@, @value: evalNumber(.@value.value))) + enum: (items: (fields where \f + (let n = ((nested where .@value = f.@value) single).e; + cond { + n count = 1: true, # only entry for value + (n where !.deprecated) count > 1: //error($`enum with multiple names for value ${f.@value} found: ${(n where !.deprecated) => .@}`), + !f.deprecated: true, # this is the only non-deprecated + (n where !.deprecated) count = 1: false, # this is deprecated and there is a non-deprecated value + (n => .@ orderby .)(0) = f.@: true, # use the first (alphabetically) deprecated value + _: false, # skip it + })) => (@: .@, @value: .@value)) ); # `endpoint` creates an endpoint out of a rpc. diff --git a/pkg/importer/proto/proto_to_sysl_test.arrai b/pkg/importer/proto/proto_to_sysl_test.arrai index b8610a07..0afd54fd 100644 --- a/pkg/importer/proto/proto_to_sysl_test.arrai +++ b/pkg/importer/proto/proto_to_sysl_test.arrai @@ -1,4 +1,4 @@ -let (:import, ...) = //{./proto_parser}; +let (:import, :parseFile, ...) = //{./proto_parser}; let (:module, ...) = //{./proto_to_sysl}; ( @@ -21,5 +21,30 @@ let (:module, ...) = //{./proto_to_sysl}; let actual = sysl.apps('SearchService').attrs('proto_options').a.elt(0).s; # Strings are not escaped in memory, only on serialization. //test.assert.equal(`php_namespace = Foo\Bar`, actual), + ), + + enum: ( + dupicates_filter: + let model = {'f.proto': parseFile(` + syntax = "proto3"; + package enums; + enum e { + E0 = 0; + E1 = 1; + E1_DEP = 1 [deprecated = true]; + E2 = 2; + E2_DEP1 = 2 [deprecated = true]; + E2_DEP2 = 2 [deprecated = true]; + E3_DEP = 3 [deprecated = true]; + E4_DEP1 = 4 [deprecated = true]; + E4_DEP2 = 4 [deprecated = true]; + E5_DEP2 = 5 [deprecated = true]; + E5_DEP1 = 5 [deprecated = true]; + }` + )}; + let sysl = module((), model); + let expected = {'E0': 0, 'E1': 1, 'E2': 2, 'E3_DEP': 3, 'E4_DEP1': 4, 'E5_DEP1': 5}; + let actual = sysl.apps('enums').types('e').enum.items; + //test.assert.equal(expected, actual), ) ) diff --git a/pkg/importer/proto/tests/enum.proto b/pkg/importer/proto/tests/enum.proto new file mode 100644 index 00000000..2b5ee52b --- /dev/null +++ b/pkg/importer/proto/tests/enum.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; +package enums; +enum e { + E0 = 0; + E1 = 1; + E1_DEP = 1 [deprecated = true]; + E2 = 2; + E2_DEP1 = 2 [deprecated = true]; + E2_DEP2 = 2 [deprecated = true]; + E3_DEP = 3 [deprecated = true]; + E4_DEP1 = 4 [deprecated = true]; + E4_DEP2 = 4 [deprecated = true]; + E5_DEP2 = 5 [deprecated = true]; + E5_DEP1 = 5 [deprecated = true]; +} diff --git a/pkg/importer/proto/tests/enum.sysl b/pkg/importer/proto/tests/enum.sysl new file mode 100644 index 00000000..5392104c --- /dev/null +++ b/pkg/importer/proto/tests/enum.sysl @@ -0,0 +1,12 @@ +# Code generated by Sysl. DO NOT EDIT. + +enums: + @package = "enums" + + !enum e [source_path="proto/tests/enum.proto"]: + E0 : 0 + E1 : 1 + E2 : 2 + E3_DEP : 3 + E4_DEP1 : 4 + E5_DEP1 : 5 diff --git a/pkg/importer/proto/tests/errors/dulicate_enum.proto b/pkg/importer/proto/tests/errors/dulicate_enum.proto new file mode 100644 index 00000000..81b9ed89 --- /dev/null +++ b/pkg/importer/proto/tests/errors/dulicate_enum.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; +package enums; +enum e { + E0 = 0; + E1 = 0; +}