diff --git a/src/idl_gen_ts.cpp b/src/idl_gen_ts.cpp index 44e8cb6cbf02..48520ac54088 100644 --- a/src/idl_gen_ts.cpp +++ b/src/idl_gen_ts.cpp @@ -406,6 +406,21 @@ class TsGenerator : public BaseGenerator { // return the bigint value directly since typescript does not support // enums with bigint backing types. switch (value.type.base_type) { + case BASE_TYPE_ARRAY: { + std::string ret = "["; + for (auto i = 0; i < value.type.fixed_length; ++i) { + ret += + AddImport(imports, *value.type.enum_def, *value.type.enum_def) + .name + + "." + + namer_.Variant( + *value.type.enum_def->FindByValue(value.constant)); + if (i < value.type.fixed_length - 1) { ret += ", "; } + } + ret += "]"; + return ret; + break; + } case BASE_TYPE_LONG: case BASE_TYPE_ULONG: { return "BigInt('" + value.constant + "')"; @@ -432,6 +447,7 @@ class TsGenerator : public BaseGenerator { return "null"; } + case BASE_TYPE_ARRAY: case BASE_TYPE_VECTOR: return "[]"; case BASE_TYPE_LONG: @@ -464,6 +480,18 @@ class TsGenerator : public BaseGenerator { case BASE_TYPE_BOOL: return allowNull ? "boolean|null" : "boolean"; case BASE_TYPE_LONG: case BASE_TYPE_ULONG: return allowNull ? "bigint|null" : "bigint"; + case BASE_TYPE_ARRAY: { + if (type.element == BASE_TYPE_LONG || type.element == BASE_TYPE_ULONG) { + return allowNull ? "bigint[]|null" : "bigint[]"; + } + if (type.element != BASE_TYPE_STRUCT) { + return allowNull ? "number[]|null" : "number[]"; + } + + auto className = + GetTypeName(*type.struct_def, /*object_api=*/true) + "[]"; + return allowNull ? className + "|null" : className; + } default: if (IsScalar(type.base_type)) { if (type.enum_def) { @@ -521,27 +549,97 @@ class TsGenerator : public BaseGenerator { } void GenStructBody(const StructDef &struct_def, std::string *body, - const std::string &nameprefix) { - *body += " builder.prep("; + const std::string &nameprefix, int32_t inNumFors = 0) { + + std::string indent_spaces = ""; + + for (auto i = 0; i < inNumFors; i++) { + indent_spaces += " "; + } + + *body += indent_spaces + " builder.prep("; *body += NumToString(struct_def.minalign) + ", "; *body += NumToString(struct_def.bytesize) + ");\n"; + for (auto it = struct_def.fields.vec.rbegin(); it != struct_def.fields.vec.rend(); ++it) { auto &field = **it; if (field.padding) { - *body += " builder.pad(" + NumToString(field.padding) + ");\n"; + *body += indent_spaces + " builder.pad(" + NumToString(field.padding) + ");\n"; } if (IsStruct(field.value.type)) { - // Generate arguments for a struct inside a struct. To ensure names - // don't clash, and to make it obvious these arguments are constructing - // a nested struct, prefix the name with the field name. GenStructBody(*field.value.type.struct_def, body, - nameprefix + field.name + "_"); + nameprefix + field.name + "_", inNumFors); } else { - *body += " builder.write" + GenWriteMethod(field.value.type) + "("; - if (field.value.type.base_type == BASE_TYPE_BOOL) { *body += "+"; } - *body += nameprefix + field.name + ");\n"; + std::string field_name_n = namer_.Method(nameprefix + field.name); + std::string field_name_n_with_dot = + namer_.Method(nameprefix + "" + field.name); + // *body += "/*\n nameprefix:\"" + nameprefix + "\" \n"; + // *body += " field.name:\"" + field.name + "\" \n"; + // *body += " field_name_n:\"" + field_name_n + "\" \n*/"; + auto element_type = field.value.type.element; + + if (field.value.type.base_type == BASE_TYPE_ARRAY) { + switch (field.value.type.element) { + case BASE_TYPE_STRUCT: { + std::string str_last_item_idx = + NumToString(field.value.type.fixed_length - 1); + std::string it_name = field_name_n + "Idx"; + std::string item_name = field_name_n + "Item"; + + *body += "\n" + indent_spaces + " for (let " + it_name + " = " + + str_last_item_idx + "; " + it_name + " >= 0; --" + it_name + + ") {\n"; + *body += indent_spaces +" const " + item_name + " = " + + field_name_n + "?.[" + it_name + "];\n"; + GenStructBody(*field.value.type.struct_def, body, item_name, + inNumFors + 1); + *body += indent_spaces + " }\n\n"; + + break; + } + default: { + std::string str_last_item_idx = + NumToString(field.value.type.fixed_length - 1); + std::string it_name = field_name_n + "Idx"; + std::string item_name = field_name_n + "Item"; + + *body += "\n" + indent_spaces + " for (let " + it_name + " = " + + str_last_item_idx + "; " + it_name + " >= 0; --" + + it_name + + ") {\n"; + *body += indent_spaces + " const " + item_name + " = " + nameprefix + + (nameprefix.length() ? "?." : "") + field.name + "?.[" + + it_name + "];\n"; + *body += indent_spaces + " builder.write"; + *body += + GenWriteMethod((flatbuffers::Type)field.value.type.element); + *body += "("; + *body += element_type == BASE_TYPE_BOOL ? "+" : ""; + + if (element_type == BASE_TYPE_LONG || + element_type == BASE_TYPE_ULONG) { + *body += "BigInt(" + item_name + " ?? 0));\n"; + } else { + *body += item_name + " ?? 0);\n\n"; + } + *body += indent_spaces + " }\n\n"; + break; + } + } + } else { + *body += indent_spaces + " builder.write" + + GenWriteMethod(field.value.type) + "("; + if (field.value.type.base_type == BASE_TYPE_BOOL) { + *body += "+"; + } else if (element_type == BASE_TYPE_LONG || + element_type == BASE_TYPE_ULONG) { + *body += "BigInt(" + field_name_n + " ?? 0);\n"; + return; + } + *body += nameprefix + ((inNumFors > 0) ? "?." : "") + field.name + " ?? 0);\n"; + } } } } @@ -973,6 +1071,11 @@ class TsGenerator : public BaseGenerator { std::string nullValue = "0"; if (field.value.type.base_type == BASE_TYPE_BOOL) { nullValue = "false"; + } else if (field.value.type.base_type == BASE_TYPE_LONG || + field.value.type.base_type == BASE_TYPE_ULONG) { + nullValue = "BigInt(0)"; + } else if (field.value.type.base_type == BASE_TYPE_ARRAY) { + nullValue = "[]"; } ret += "(" + curr_member_accessor + " ?? " + nullValue + ")"; } else { @@ -1091,6 +1194,95 @@ class TsGenerator : public BaseGenerator { break; } + case BASE_TYPE_ARRAY: { + auto vectortype = field.value.type.VectorType(); + auto vectortypename = + GenTypeName(imports, struct_def, vectortype, false); + is_vector = true; + + field_type = "("; + + switch (vectortype.base_type) { + case BASE_TYPE_STRUCT: { + const auto &sd = *field.value.type.struct_def; + const auto field_type_name = + GetTypeName(sd, /*object_api=*/true); + field_type += field_type_name; + field_type += ")[]"; + + field_val = GenBBAccess() + ".createObjList<" + vectortypename + + ", " + field_type_name + ">(" + + field_binded_method + ", " + + NumToString(field.value.type.fixed_length) + ")"; + + if (sd.fixed) { + field_offset_decl = + "builder.createStructOffsetList(this." + field_field + + ", " + AddImport(imports, struct_def, struct_def).name + + "." + namer_.Method("start", field, "Vector") + ")"; + } else { + field_offset_decl = + AddImport(imports, struct_def, struct_def).name + "." + + namer_.Method("create", field, "Vector") + + "(builder, builder.createObjectOffsetList(" + "this." + + field_field + "))"; + } + + break; + } + + case BASE_TYPE_STRING: { + field_type += "string)[]"; + field_val = GenBBAccess() + ".createScalarList(" + + field_binded_method + ", this." + + namer_.Field(field, "Length") + "())"; + field_offset_decl = + AddImport(imports, struct_def, struct_def).name + "." + + namer_.Method("create", field, "Vector") + + "(builder, builder.createObjectOffsetList(" + "this." + + namer_.Field(field) + "))"; + break; + } + + case BASE_TYPE_UNION: { + field_type += GenObjApiUnionTypeTS( + imports, struct_def, parser.opts, *(vectortype.enum_def)); + field_type += ")[]"; + field_val = GenUnionValTS(imports, struct_def, field_method, + vectortype, true); + + field_offset_decl = + AddImport(imports, struct_def, struct_def).name + "." + + namer_.Method("create", field, "Vector") + + "(builder, builder.createObjectOffsetList(" + "this." + + namer_.Field(field) + "))"; + + break; + } + default: { + if (vectortype.enum_def) { + field_type += GenTypeName(imports, struct_def, vectortype, + false, HasNullDefault(field)); + } else { + field_type += vectortypename; + } + field_type += ")[]"; + field_val = GenBBAccess() + ".createScalarList<" + + vectortypename + ">(" + field_binded_method + ", " + + NumToString(field.value.type.fixed_length) + ")"; + + field_offset_decl = + AddImport(imports, struct_def, struct_def).name + "." + + namer_.Method("create", field, "Vector") + + "(builder, this." + field_field + ")"; + + break; + } + } + + break; + } + case BASE_TYPE_VECTOR: { auto vectortype = field.value.type.VectorType(); auto vectortypename = @@ -1344,9 +1536,16 @@ class TsGenerator : public BaseGenerator { it != struct_def.fields.vec.end(); ++it) { auto &field = **it; if (field.deprecated) continue; - auto offset_prefix = - " const offset = " + GenBBAccess() + ".__offset(this.bb_pos, " + - NumToString(field.value.offset) + ");\n return offset ? "; + std::string offset_prefix = ""; + + if (field.value.type.base_type == BASE_TYPE_ARRAY) { + offset_prefix = " return "; + } else { + offset_prefix = " const offset = " + GenBBAccess() + + ".__offset(this.bb_pos, " + + NumToString(field.value.offset) + ");\n"; + offset_prefix += " return offset ? "; + } // Emit a scalar field const auto is_string = IsString(field.value.type); @@ -1386,9 +1585,11 @@ class TsGenerator : public BaseGenerator { } else { std::string index = "this.bb_pos + offset"; if (is_string) { index += ", optionalEncoding"; } - code += offset_prefix + - GenGetter(field.value.type, "(" + index + ")") + " : " + - GenDefaultValue(field, imports); + code += + offset_prefix + GenGetter(field.value.type, "(" + index + ")"); + if (field.value.type.base_type != BASE_TYPE_ARRAY) { + code += " : " + GenDefaultValue(field, imports); + } code += ";\n"; } } @@ -1421,6 +1622,96 @@ class TsGenerator : public BaseGenerator { break; } + case BASE_TYPE_ARRAY: { + // create kodunu burda arama! + auto vectortype = field.value.type.VectorType(); + auto vectortypename = + GenTypeName(imports, struct_def, vectortype, false); + auto inline_size = InlineSize(vectortype); + auto index = "this.bb_pos + " + NumToString(field.value.offset) + + " + index" + MaybeScale(inline_size); + std::string ret_type; + bool is_union = false; + switch (vectortype.base_type) { + case BASE_TYPE_STRUCT: ret_type = vectortypename; break; + case BASE_TYPE_STRING: ret_type = vectortypename; break; + case BASE_TYPE_UNION: + ret_type = "?flatbuffers.Table"; + is_union = true; + break; + default: ret_type = vectortypename; + } + GenDocComment(field.doc_comment, code_ptr); + std::string prefix = namer_.Method(field); + // TODO: make it work without any + // if (is_union) { prefix += ""; } + if (is_union) { prefix += ""; } + prefix += "(index: number"; + if (is_union) { + const auto union_type = + GenUnionGenericTypeTS(*(field.value.type.enum_def)); + + vectortypename = union_type; + code += prefix + ", obj:" + union_type; + } else if (vectortype.base_type == BASE_TYPE_STRUCT) { + code += prefix + ", obj?:" + vectortypename; + } else if (IsString(vectortype)) { + code += prefix + "):string\n"; + code += prefix + ",optionalEncoding:flatbuffers.Encoding" + + "):" + vectortypename + "\n"; + code += prefix + ",optionalEncoding?:any"; + } else { + code += prefix; + } + code += "):" + vectortypename + "|null {\n"; + + if (vectortype.base_type == BASE_TYPE_STRUCT) { + code += offset_prefix + "(obj || " + + GenerateNewExpression(vectortypename); + code += ").__init("; + code += vectortype.struct_def->fixed + ? index + : GenBBAccess() + ".__indirect(" + index + ")"; + code += ", " + GenBBAccess() + ")"; + } else { + if (is_union) { + index = "obj, " + index; + } else if (IsString(vectortype)) { + index += ", optionalEncoding"; + } + code += offset_prefix + GenGetter(vectortype, "(" + index + ")"); + } + + switch (field.value.type.base_type) { + case BASE_TYPE_ARRAY: { + break; + } + case BASE_TYPE_BOOL: { + code += " : false"; + break; + } + case BASE_TYPE_LONG: + case BASE_TYPE_ULONG: { + code += " : BigInt(0)"; + break; + } + default: { + if (IsScalar(field.value.type.element)) { + if (field.value.type.enum_def) { + code += field.value.constant; + } else { + code += " : 0"; + } + } else { + code += ": null"; + } + break; + } + } + code += ";\n"; + break; + } + case BASE_TYPE_VECTOR: { auto vectortype = field.value.type.VectorType(); auto vectortypename = diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 9d9079a36c29..e2c69fd2861a 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -2581,7 +2581,7 @@ bool Parser::SupportsAdvancedArrayFeatures() const { return (opts.lang_to_generate & ~(IDLOptions::kCpp | IDLOptions::kPython | IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kJsonSchema | IDLOptions::kJson | - IDLOptions::kBinary | IDLOptions::kRust)) == 0; + IDLOptions::kBinary | IDLOptions::kRust | IDLOptions::kTs)) == 0; } Namespace *Parser::UniqueNamespace(Namespace *ns) {