From 47d35f10533547e5c8d06f7e5c05dbc02178a002 Mon Sep 17 00:00:00 2001 From: Artavazd Balaian Date: Sat, 11 Sep 2021 00:55:46 +0800 Subject: [PATCH] BugFix: Optional enum when it is null (#6835) * Test to make sure optional enum is written properly * Handle optional enum codegen: when cast optional enum add `?` * Run `tests/generate_code.sh` to generate code from schema * Fix type casting in case of CreateXXXTypeVector * Reason why vector's type is not optional --- src/idl_gen_csharp.cpp | 14 ++++++++------ tests/FlatBuffers.Test/FlatBuffersExampleTests.cs | 13 +++++++++++++ tests/optional_scalars/ScalarStuff.cs | 2 +- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/idl_gen_csharp.cpp b/src/idl_gen_csharp.cpp index 05fe04ad7c7..f23d9f07fb6 100644 --- a/src/idl_gen_csharp.cpp +++ b/src/idl_gen_csharp.cpp @@ -309,17 +309,17 @@ class CSharpGenerator : public BaseGenerator { // would be cast down to int before being put onto the buffer. In C#, one cast // directly cast an Enum to its underlying type, which is essential before // putting it onto the buffer. - std::string SourceCast(const Type &type) const { + std::string SourceCast(const Type &type, const bool isOptional=false) const { if (IsSeries(type)) { return SourceCast(type.VectorType()); } else { - if (IsEnum(type)) return "(" + GenTypeBasic(type, false) + ")"; + if (IsEnum(type)) return "(" + GenTypeBasic(type, false) + (isOptional ? "?": "") + ")"; } return ""; } - std::string SourceCastBasic(const Type &type) const { - return IsScalar(type.base_type) ? SourceCast(type) : ""; + std::string SourceCastBasic(const Type &type, const bool isOptional) const { + return IsScalar(type.base_type) ? SourceCast(type, isOptional) : ""; } std::string GenEnumDefaultValue(const FieldDef &field) const { @@ -1191,7 +1191,7 @@ class CSharpGenerator : public BaseGenerator { code += " " + EscapeKeyword(argname) + ") { builder.Add"; code += GenMethod(field.value.type) + "("; code += NumToString(it - struct_def.fields.vec.begin()) + ", "; - code += SourceCastBasic(field.value.type); + code += SourceCastBasic(field.value.type, field.IsScalarOptional()); code += EscapeKeyword(argname); if (!IsScalar(field.value.type.base_type) && field.value.type.base_type != BASE_TYPE_UNION) { @@ -1225,7 +1225,9 @@ class CSharpGenerator : public BaseGenerator { code += "Add"; code += GenMethod(vector_type); code += "("; - code += SourceCastBasic(vector_type); + // At the moment there is no support of the type Vector with optional enum, + // e.g. if we have enum type SomeEnum there is no way to define `SomeEmum?[] enums` in FlatBuffer schema, so isOptional = false + code += SourceCastBasic(vector_type, false); code += "data[i]"; if (vector_type.base_type == BASE_TYPE_STRUCT || IsString(vector_type)) diff --git a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs index 83cb35c2e13..79a213c3880 100644 --- a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs +++ b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs @@ -1139,5 +1139,18 @@ public void TestKeywordEscaping() { Assert.AreEqual(keywordsInTable.Is, KeywordTest.ABC.@stackalloc); Assert.AreEqual(keywordsInTable.Private, KeywordTest.@public.NONE); } + + + [FlatBuffersTestMethod] + public void AddOptionalEnum_WhenPassNull_ShouldWorkProperly() { + var fbb = new FlatBufferBuilder(1); + ScalarStuff.StartScalarStuff(fbb); + ScalarStuff.AddMaybeEnum(fbb, null); + var offset = ScalarStuff.EndScalarStuff(fbb); + ScalarStuff.FinishScalarStuffBuffer(fbb, offset); + + ScalarStuff scalarStuff = ScalarStuff.GetRootAsScalarStuff(fbb.DataBuffer); + Assert.AreEqual(null, scalarStuff.MaybeEnum); + } } } diff --git a/tests/optional_scalars/ScalarStuff.cs b/tests/optional_scalars/ScalarStuff.cs index f7ad73a8004..e5498383082 100644 --- a/tests/optional_scalars/ScalarStuff.cs +++ b/tests/optional_scalars/ScalarStuff.cs @@ -169,7 +169,7 @@ public struct ScalarStuff : IFlatbufferObject public static void AddMaybeBool(FlatBufferBuilder builder, bool? maybeBool) { builder.AddBool(31, maybeBool); } public static void AddDefaultBool(FlatBufferBuilder builder, bool defaultBool) { builder.AddBool(32, defaultBool, true); } public static void AddJustEnum(FlatBufferBuilder builder, optional_scalars.OptionalByte justEnum) { builder.AddSbyte(33, (sbyte)justEnum, 0); } - public static void AddMaybeEnum(FlatBufferBuilder builder, optional_scalars.OptionalByte? maybeEnum) { builder.AddSbyte(34, (sbyte)maybeEnum); } + public static void AddMaybeEnum(FlatBufferBuilder builder, optional_scalars.OptionalByte? maybeEnum) { builder.AddSbyte(34, (sbyte?)maybeEnum); } public static void AddDefaultEnum(FlatBufferBuilder builder, optional_scalars.OptionalByte defaultEnum) { builder.AddSbyte(35, (sbyte)defaultEnum, 1); } public static Offset EndScalarStuff(FlatBufferBuilder builder) { int o = builder.EndTable();