diff options
author | Anass Al <dev@anassinator.com> | 2020-04-06 09:27:13 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-06 09:27:13 -0700 |
commit | fb96fadc20a78da264b1878ff95f12838c3b22c8 (patch) | |
tree | a38786659ba6eab03c07c521bcb63f878d8fead0 | |
parent | 408f11fbdd42bedc86e6a69aecdc77c98b39167a (diff) | |
download | flatbuffers-fb96fadc20a78da264b1878ff95f12838c3b22c8.tar.gz flatbuffers-fb96fadc20a78da264b1878ff95f12838c3b22c8.tar.bz2 flatbuffers-fb96fadc20a78da264b1878ff95f12838c3b22c8.zip |
[C#] Fix nested structs and arrays in Object API (#5765)
* [C#] Fix nested structs and arrays in Object API
The adds support for nested structs and fixed size arrays in the C#
Object API codegen which previously generated invalid code that wouldn't
compile.
- Nested structs would originally generate syntax errors due to adding an
additional `.` to separate fields.
- Fixed size arrays of nested structs would originally generate code for
the first field in the top most struct, and would lead to a compiler
error due to referencing undefined variables.
* [C#] fix nested structs and arrays of structs.
* fix nested structs + arrays
* add table support
* Cleanup code
Co-authored-by: mugisoba <mugisoba+github@icloud.com>
-rw-r--r-- | src/idl_gen_csharp.cpp | 168 | ||||
-rw-r--r-- | tests/MyGame/Example/Vec3.cs | 6 |
2 files changed, 96 insertions, 78 deletions
diff --git a/src/idl_gen_csharp.cpp b/src/idl_gen_csharp.cpp index 0bcd132c..96a5da80 100644 --- a/src/idl_gen_csharp.cpp +++ b/src/idl_gen_csharp.cpp @@ -38,6 +38,11 @@ static CommentConfig comment_config = { namespace csharp { class CSharpGenerator : public BaseGenerator { + struct FieldArrayLength { + std::string name; + int length; + }; + public: CSharpGenerator(const Parser &parser, const std::string &path, const std::string &file_name) @@ -1540,6 +1545,15 @@ class CSharpGenerator : public BaseGenerator { GenOffsetType(*field.value.type.struct_def) + ") : " + GenTypeGet(field.value.type) + ".Pack(builder, _o." + camel_name + ");\n"; + } else if (struct_def.fixed && struct_has_create) { + std::vector<FieldArrayLength> array_lengths; + FieldArrayLength tmp_array_length = { + field.name, + field.value.type.fixed_length, + }; + array_lengths.push_back(tmp_array_length); + GenStructPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr, + array_lengths); } break; } @@ -1620,12 +1634,14 @@ class CSharpGenerator : public BaseGenerator { } case BASE_TYPE_ARRAY: { if (field.value.type.struct_def != nullptr) { - std::vector<std::string> name_vec; - name_vec.push_back(field.name); - std::vector<int> array_length_vec; - array_length_vec.push_back(field.value.type.fixed_length); - GenArrayPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr, - name_vec, array_length_vec); + std::vector<FieldArrayLength> array_lengths; + FieldArrayLength tmp_array_length = { + field.name, + field.value.type.fixed_length, + }; + array_lengths.push_back(tmp_array_length); + GenStructPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr, + array_lengths); } else { code += " var _" + field.name + " = _o." + camel_name + ";\n"; } @@ -1656,8 +1672,9 @@ class CSharpGenerator : public BaseGenerator { switch (field.value.type.base_type) { case BASE_TYPE_STRUCT: { if (struct_def.fixed) { - GenStructArgs_ObjectAPI(*field.value.type.struct_def, code_ptr, - " _o." + camel_name + "."); + GenStructPackCall_ObjectAPI(*field.value.type.struct_def, + code_ptr, + " _" + field.name + "_"); } else { code += ",\n"; if (field.value.type.struct_def->fixed) { @@ -1674,8 +1691,9 @@ class CSharpGenerator : public BaseGenerator { } case BASE_TYPE_ARRAY: { if (field.value.type.struct_def != nullptr) { - GenArrayPackCall_ObjectAPI(*field.value.type.struct_def, code_ptr, - " _" + field.name + "_"); + GenStructPackCall_ObjectAPI(*field.value.type.struct_def, + code_ptr, + " _" + field.name + "_"); } else { code += ",\n"; code += " _" + field.name; @@ -1745,28 +1763,9 @@ class CSharpGenerator : public BaseGenerator { code += " }\n"; } - void GenStructArgs_ObjectAPI(const StructDef &struct_def, - std::string *code_ptr, - std::string prefix) const { - auto &code = *code_ptr; - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { - auto &field = **it; - const auto &field_type = field.value.type; - if (IsStruct(field_type)) { - GenStructArgs_ObjectAPI(*field_type.struct_def, code_ptr, - prefix + "." + MakeCamel(field.name) + "."); - } else { - code += ",\n"; - code += prefix + MakeCamel(field.name); - } - } - } - - void GenArrayPackDecl_ObjectAPI(const StructDef &struct_def, - std::string *code_ptr, - std::vector<std::string> name_vec, - std::vector<int> array_length_vec) const { + void GenStructPackDecl_ObjectAPI( + const StructDef &struct_def, std::string *code_ptr, + std::vector<FieldArrayLength> &array_lengths) const { auto &code = *code_ptr; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { @@ -1774,64 +1773,81 @@ class CSharpGenerator : public BaseGenerator { auto is_array = IsArray(field.value.type); const auto &field_type = is_array ? field.value.type.VectorType() : field.value.type; - if (!IsStruct(field_type)) { - auto tmp_name_vec = name_vec; - tmp_name_vec.push_back(field.name); - auto tmp_array_length_vec = array_length_vec; - if (is_array) { - tmp_array_length_vec.push_back(field_type.fixed_length); + FieldArrayLength tmp_array_length = { + field.name, + field_type.fixed_length, + }; + array_lengths.push_back(tmp_array_length); + if (field_type.struct_def != nullptr) { + GenStructPackDecl_ObjectAPI(*field_type.struct_def, code_ptr, + array_lengths); + } else { + std::vector<FieldArrayLength> array_only_lengths; + for (size_t i = 0; i < array_lengths.size(); ++i) { + if (array_lengths[i].length > 0) { + array_only_lengths.push_back(array_lengths[i]); + } } std::string name; - for (size_t tmp_name_index = 0; tmp_name_index < tmp_name_vec.size(); - ++tmp_name_index) { - name += "_" + tmp_name_vec[tmp_name_index]; - } - code += " var " + name + " = new " + GenTypeBasic(field_type) + "["; - code += NumToString(tmp_array_length_vec[0]); - for (size_t i = 1; i < tmp_array_length_vec.size(); ++i) { - auto array_length = tmp_array_length_vec[i]; - code += "," + NumToString(array_length); - } - code += "];\n"; - code += " "; - // initialize array - for (size_t i = 0; i < tmp_array_length_vec.size(); ++i) { - auto array_length = tmp_array_length_vec[i]; - auto idx = "idx" + NumToString(i); - code += "for (var " + idx + " = 0; " + idx + " < " + - NumToString(array_length) + "; ++" + idx + ") {"; - } - code += name + "[idx0"; - for (size_t i = 1; i < tmp_array_length_vec.size(); ++i) { - auto idx = "idx" + NumToString(i); - code += "," + idx; + for (size_t i = 0; i < array_lengths.size(); ++i) { + name += "_" + array_lengths[i].name; } - code += "] = _o"; - for (size_t i = 0; i < tmp_array_length_vec.size(); ++i) { - auto idx = "idx" + NumToString(i); - code += "." + MakeCamel(tmp_name_vec[i]) + "[" + idx + "]"; - } - if (!is_array) { code += "." + MakeCamel(field.name); } - code += ";"; - for (size_t i = 0; i < tmp_array_length_vec.size(); ++i) { - code += "}"; + code += " var " + name + " = "; + if (array_only_lengths.size() > 0) { + code += "new " + GenTypeBasic(field_type) + "["; + for (size_t i = 0; i < array_only_lengths.size(); ++i) { + if (i != 0) { code += ","; } + code += NumToString(array_only_lengths[i].length); + } + code += "];\n"; + code += " "; + // initialize array + for (size_t i = 0; i < array_only_lengths.size(); ++i) { + auto idx = "idx" + NumToString(i); + code += "for (var " + idx + " = 0; " + idx + " < " + + NumToString(array_only_lengths[i].length) + "; ++" + idx + + ") {"; + } + for (size_t i = 0; i < array_only_lengths.size(); ++i) { + auto idx = "idx" + NumToString(i); + if (i == 0) { + code += name + "[" + idx; + } else { + code += "," + idx; + } + } + code += "] = _o"; + for (size_t i = 0, j = 0; i < array_lengths.size(); ++i) { + code += "." + MakeCamel(array_lengths[i].name); + if (array_lengths[i].length <= 0) continue; + code += "[idx" + NumToString(j++) + "]"; + } + code += ";"; + for (size_t i = 0; i < array_only_lengths.size(); ++i) { code += "}"; } + } else { + code += "_o"; + for (size_t i = 0; i < array_lengths.size(); ++i) { + code += "." + MakeCamel(array_lengths[i].name); + } + code += ";"; } code += "\n"; } + array_lengths.pop_back(); } } - void GenArrayPackCall_ObjectAPI(const StructDef &struct_def, - std::string *code_ptr, - std::string prefix) const { + void GenStructPackCall_ObjectAPI(const StructDef &struct_def, + std::string *code_ptr, + std::string prefix) const { auto &code = *code_ptr; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { auto &field = **it; const auto &field_type = field.value.type; - if (IsStruct(field_type)) { - GenArrayPackCall_ObjectAPI(*field_type.struct_def, code_ptr, - prefix + field.name + "_"); + if (field_type.struct_def != nullptr) { + GenStructPackCall_ObjectAPI(*field_type.struct_def, code_ptr, + prefix + field.name + "_"); } else { code += ",\n"; code += prefix + field.name; diff --git a/tests/MyGame/Example/Vec3.cs b/tests/MyGame/Example/Vec3.cs index 4a9bf0d1..54fc8f99 100644 --- a/tests/MyGame/Example/Vec3.cs +++ b/tests/MyGame/Example/Vec3.cs @@ -59,6 +59,8 @@ public struct Vec3 : IFlatbufferObject } public static Offset<MyGame.Example.Vec3> Pack(FlatBufferBuilder builder, Vec3T _o) { if (_o == null) return default(Offset<MyGame.Example.Vec3>); + var _test3_a = _o.Test3.A; + var _test3_b = _o.Test3.B; return CreateVec3( builder, _o.X, @@ -66,8 +68,8 @@ public struct Vec3 : IFlatbufferObject _o.Z, _o.Test1, _o.Test2, - _o.Test3.A, - _o.Test3.B); + _test3_a, + _test3_b); } }; |