From 6c5603fd98aac5e7aeb31a96a9b75dc0986ca75a Mon Sep 17 00:00:00 2001 From: tira-misu Date: Wed, 30 Mar 2022 21:51:58 +0200 Subject: [PATCH] [C#] Fix collision of field name and type name (#7149) * Fix C/C++ CreateDirect with sorted vectors If a struct has a key the vector has to be sorted. To sort the vector you can't use "const". * Changes due to code review * Improve code readability * Add generate of JSON schema to string to lib * option indent_step is supported * Remove unused variables * Fix break in test * Fix style to be consistent with rest of the code * [TS] Fix reserved words as arguments (#6955) * [TS] Fix generation of reserved words in object api (#7106) * [TS] Fix generation of object api * [TS] Fix MakeCamel -> ConvertCase * [C#] Fix collision of field name and type name * [TS] Add test for struct of struct of struct * Update generated files * Add missing files * [TS] Fix query of null/undefined fields in object api * Add example for type field name collision --- scripts/generate_code.py | 5 ++ src/idl_gen_csharp.cpp | 30 +++++++---- tests/type_field_collsion.fbs | 8 +++ tests/type_field_collsion/Collision.cs | 73 ++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 9 deletions(-) create mode 100644 tests/type_field_collsion.fbs create mode 100644 tests/type_field_collsion/Collision.cs diff --git a/scripts/generate_code.py b/scripts/generate_code.py index 2cc7715a9..c5da9bda4 100755 --- a/scripts/generate_code.py +++ b/scripts/generate_code.py @@ -345,6 +345,11 @@ flatc(RUST_OPTS, prefix="optional_scalars", schema=optional_scalars_schema) flatc(NO_INCL_OPTS + CPP_OPTS, schema=optional_scalars_schema) +# Type / field collsion +type_field_collsion_schema = "type_field_collsion.fbs" + +flatc(["--csharp", "--gen-object-api"], schema=type_field_collsion_schema) + # Generate string/vector default code for tests flatc(RUST_OPTS, prefix="more_defaults", schema="more_defaults.fbs") diff --git a/src/idl_gen_csharp.cpp b/src/idl_gen_csharp.cpp index cb605defd..bbb3ec3a9 100644 --- a/src/idl_gen_csharp.cpp +++ b/src/idl_gen_csharp.cpp @@ -914,7 +914,9 @@ class CSharpGenerator : public BaseGenerator { code += member_suffix; code += "}\n"; if (IsVector(field.value.type)) { - code += " public int " + Name(field); + auto camel_name = Name(field); + if (camel_name == struct_def.name) { camel_name += "_"; } + code += " public int " + camel_name; code += "Length"; code += " { get"; code += offset_prefix; @@ -1566,6 +1568,7 @@ class CSharpGenerator : public BaseGenerator { void GenUnionUnPack_ObjectAPI(const EnumDef &enum_def, std::string *code_ptr, const std::string &camel_name, + const std::string &camel_name_short, bool is_vector) const { auto &code = *code_ptr; std::string varialbe_name = "_o." + camel_name; @@ -1584,10 +1587,11 @@ class CSharpGenerator : public BaseGenerator { code += indent + varialbe_name + " = new "; } code += NamespacedName(enum_def) + "Union();\n"; - code += indent + varialbe_name + ".Type = this." + camel_name + "Type" + + code += indent + varialbe_name + ".Type = this." + camel_name_short + + "Type" + type_suffix + ";\n"; - code += - indent + "switch (this." + camel_name + "Type" + type_suffix + ") {\n"; + code += indent + "switch (this." + camel_name_short + "Type" + type_suffix + + ") {\n"; for (auto eit = enum_def.Vals().begin(); eit != enum_def.Vals().end(); ++eit) { auto &ev = **eit; @@ -1633,6 +1637,8 @@ class CSharpGenerator : public BaseGenerator { auto &field = **it; if (field.deprecated) continue; auto camel_name = Name(field); + if (camel_name == struct_def.name) { camel_name += "_"; } + auto camel_name_short = Name(field); auto start = " _o." + camel_name + " = "; switch (field.value.type.base_type) { case BASE_TYPE_STRUCT: { @@ -1666,7 +1672,7 @@ class CSharpGenerator : public BaseGenerator { code += " for (var _j = 0; _j < this." + camel_name + "Length; ++_j) {\n"; GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr, - camel_name, true); + camel_name, camel_name_short, true); code += " }\n"; } else if (field.value.type.element != BASE_TYPE_UTYPE) { auto fixed = field.value.type.struct_def == nullptr; @@ -1687,7 +1693,7 @@ class CSharpGenerator : public BaseGenerator { case BASE_TYPE_UTYPE: break; case BASE_TYPE_UNION: { GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr, - camel_name, false); + camel_name, camel_name_short, false); break; } default: { @@ -1707,6 +1713,8 @@ class CSharpGenerator : public BaseGenerator { auto &field = **it; if (field.deprecated) continue; auto camel_name = Name(field); + if (camel_name == struct_def.name) { camel_name += "_"; } + auto camel_name_short = Name(field); // pre switch (field.value.type.base_type) { case BASE_TYPE_STRUCT: { @@ -1782,7 +1790,7 @@ class CSharpGenerator : public BaseGenerator { code += " var " + array_name + " = _o." + property_name + ".ToArray();\n"; } - code += " _" + field.name + " = Create" + camel_name + + code += " _" + field.name + " = Create" + camel_name_short + "Vector(builder, " + array_name + ");\n"; code += " }\n"; } else { @@ -1794,7 +1802,7 @@ class CSharpGenerator : public BaseGenerator { camel_name + "[_j]);"; code += " var _" + field.name + " = default(VectorOffset);\n"; code += " if (_o." + camel_name + " != null) {\n"; - code += " Start" + camel_name + "Vector(builder, _o." + + code += " Start" + camel_name_short + "Vector(builder, _o." + camel_name + ".Count);\n"; code += " for (var _j = _o." + camel_name + ".Count - 1; _j >= 0; --_j) { " + pack_method + " }\n"; @@ -1840,6 +1848,7 @@ class CSharpGenerator : public BaseGenerator { auto &field = **it; if (field.deprecated) continue; auto camel_name = Name(field); + if (camel_name == struct_def.name) { camel_name += "_"; } switch (field.value.type.base_type) { case BASE_TYPE_STRUCT: { if (struct_def.fixed) { @@ -2094,6 +2103,7 @@ class CSharpGenerator : public BaseGenerator { auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts); if (field.IsScalarOptional()) type_name += "?"; auto camel_name = Name(field); + if (camel_name == struct_def.name) { camel_name += "_"; } if (opts.cs_gen_json_serializer) { if (IsUnion(field.value.type)) { auto utype_name = NamespacedName(*field.value.type.enum_def); @@ -2159,7 +2169,9 @@ class CSharpGenerator : public BaseGenerator { if (field.deprecated) continue; if (field.value.type.base_type == BASE_TYPE_UTYPE) continue; if (field.value.type.element == BASE_TYPE_UTYPE) continue; - code += " this." + Name(field) + " = "; + auto camel_name = Name(field); + if (camel_name == struct_def.name) { camel_name += "_"; } + code += " this." + camel_name + " = "; auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts); if (IsScalar(field.value.type.base_type)) { code += GenDefaultValue(field) + ";\n"; diff --git a/tests/type_field_collsion.fbs b/tests/type_field_collsion.fbs new file mode 100644 index 000000000..ec7354428 --- /dev/null +++ b/tests/type_field_collsion.fbs @@ -0,0 +1,8 @@ +namespace type_field_collsion; + +// This table tests collsions of identifiers. +table Collision { + collision : int; +} + +root_type Collision; diff --git a/tests/type_field_collsion/Collision.cs b/tests/type_field_collsion/Collision.cs new file mode 100644 index 000000000..04a0be808 --- /dev/null +++ b/tests/type_field_collsion/Collision.cs @@ -0,0 +1,73 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace type_field_collsion +{ + +using global::System; +using global::System.Collections.Generic; +using global::FlatBuffers; + +public struct Collision : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_2_0_0(); } + public static Collision GetRootAsCollision(ByteBuffer _bb) { return GetRootAsCollision(_bb, new Collision()); } + public static Collision GetRootAsCollision(ByteBuffer _bb, Collision obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Collision __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int Collision_ { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateCollision(FlatBufferBuilder builder, + int collision = 0) { + builder.StartTable(1); + Collision.AddCollision(builder, collision); + return Collision.EndCollision(builder); + } + + public static void StartCollision(FlatBufferBuilder builder) { builder.StartTable(1); } + public static void AddCollision(FlatBufferBuilder builder, int collision) { builder.AddInt(0, collision, 0); } + public static Offset EndCollision(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishCollisionBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value); } + public static void FinishSizePrefixedCollisionBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value); } + public CollisionT UnPack() { + var _o = new CollisionT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(CollisionT _o) { + _o.Collision_ = this.Collision_; + } + public static Offset Pack(FlatBufferBuilder builder, CollisionT _o) { + if (_o == null) return default(Offset); + return CreateCollision( + builder, + _o.Collision_); + } +} + +public class CollisionT +{ + public int Collision_ { get; set; } + + public CollisionT() { + this.Collision_ = 0; + } + public static CollisionT DeserializeFromBinary(byte[] fbBuffer) { + return Collision.GetRootAsCollision(new ByteBuffer(fbBuffer)).UnPack(); + } + public byte[] SerializeToBinary() { + var fbb = new FlatBufferBuilder(0x10000); + Collision.FinishCollisionBuffer(fbb, Collision.Pack(fbb, this)); + return fbb.DataBuffer.ToSizedArray(); + } +} + + +}