From 2239b332f4348154695fa89894097b881abc7c98 Mon Sep 17 00:00:00 2001 From: Arieh Schneier <15041913+AriehSchneier@users.noreply.github.com> Date: Thu, 20 Jun 2024 09:26:44 +1000 Subject: [PATCH] proto->sysl: filter out duplicate enum values (#925) --- .../bundles/assets/import_proto_cli.arraiz | Bin 38613 -> 38862 bytes pkg/importer/importer_test.go | 17 +++++++++++ pkg/importer/proto/proto_to_sysl.arrai | 13 ++++++++- pkg/importer/proto/proto_to_sysl_test.arrai | 27 +++++++++++++++++- pkg/importer/proto/tests/enum.proto | 15 ++++++++++ pkg/importer/proto/tests/enum.sysl | 12 ++++++++ .../proto/tests/errors/dulicate_enum.proto | 6 ++++ 7 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 pkg/importer/proto/tests/enum.proto create mode 100644 pkg/importer/proto/tests/enum.sysl create mode 100644 pkg/importer/proto/tests/errors/dulicate_enum.proto diff --git a/internal/bundles/assets/import_proto_cli.arraiz b/internal/bundles/assets/import_proto_cli.arraiz index db053f4af508a829f6926b52e6d42166463013df..e375ab4abf521e14c39759118127f5cb1a43e3c7 100644 GIT binary patch delta 4998 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 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; +}