mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-12 07:50:59 +00:00
Vector of unions for TS/JS and PHP (#4404)
* Eclipse ignore * TypeScript support * Prefixing enums * Test results * Merged JS and TS generators * Fixed AppVeyor build problems * Fixed more AppVeyor build problems * Fixed more AppVeyor build problems * Changed TS flag to options struct * Storing options by value * Removed unneeded const * Re-export support for unions * Uint support * Casting bools to numbers for mutation * TS shell tests * Reverted generates js test file to original version * Backing up js tests and properly generating test data * Not importing flatbuffers for TS test generation * Not overwriting generated js for tests * AppVeyor test fixes * Generating the most strict TS code possible * Not returning null when creating vectors * Not returning null from struct contructors * Vector of unions for ts/js * Sanity check for languages * Indentation fix + output test files * Vectors of unions for php * Fixes to union vector handling + tests
This commit is contained in:
committed by
Wouter van Oortmerssen
parent
7cc72e4b11
commit
46bb05d952
@@ -289,9 +289,12 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr,
|
||||
std::string &code = *code_ptr;
|
||||
std::string &exports = *exports_ptr;
|
||||
GenDocComment(enum_def.doc_comment, code_ptr, "@enum");
|
||||
std::string ns = GetNameSpace(enum_def);
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "export namespace " + GetNameSpace(enum_def) + "{\n" +
|
||||
"export enum " + enum_def.name + "{\n";
|
||||
if (!ns.empty()) {
|
||||
code += "export namespace " + ns + "{\n";
|
||||
}
|
||||
code += "export enum " + enum_def.name + "{\n";
|
||||
} else {
|
||||
if (enum_def.defined_namespace->components.empty()) {
|
||||
code += "var ";
|
||||
@@ -329,11 +332,10 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr,
|
||||
}
|
||||
}
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "}};\n\n";
|
||||
} else {
|
||||
code += "};\n\n";
|
||||
if (lang_.language == IDLOptions::kTs && !ns.empty()) {
|
||||
code += "}";
|
||||
}
|
||||
code += "};\n\n";
|
||||
}
|
||||
|
||||
static std::string GenType(const Type &type) {
|
||||
@@ -554,13 +556,15 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
|
||||
std::string &exports = *exports_ptr;
|
||||
|
||||
std::string object_name;
|
||||
std::string object_namespace = GetNameSpace(struct_def);
|
||||
|
||||
// Emit constructor
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
object_name = struct_def.name;
|
||||
std::string object_namespace = GetNameSpace(struct_def);
|
||||
GenDocComment(struct_def.doc_comment, code_ptr, "@constructor");
|
||||
code += "export namespace " + object_namespace + "{\n";
|
||||
if (!object_namespace.empty()) {
|
||||
code += "export namespace " + object_namespace + "{\n";
|
||||
}
|
||||
code += "export class " + struct_def.name;
|
||||
code += " {\n";
|
||||
code += " /**\n";
|
||||
@@ -754,17 +758,37 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
|
||||
auto index = "this.bb.__vector(this.bb_pos + offset) + index" +
|
||||
MaybeScale(inline_size);
|
||||
std::string args = "@param {number} index\n";
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
args += "@param {" + vectortypename + "=} obj\n";
|
||||
} else if (vectortype.base_type == BASE_TYPE_STRING) {
|
||||
args += "@param {flatbuffers.Encoding=} optionalEncoding\n";
|
||||
std::string ret_type;
|
||||
bool is_union = false;
|
||||
switch (vectortype.base_type) {
|
||||
case BASE_TYPE_STRUCT:
|
||||
args += "@param {" + vectortypename + "=} obj\n";
|
||||
ret_type = vectortypename;
|
||||
break;
|
||||
case BASE_TYPE_STRING:
|
||||
args += "@param {flatbuffers.Encoding=} optionalEncoding\n";
|
||||
ret_type = vectortypename;
|
||||
break;
|
||||
case BASE_TYPE_UNION:
|
||||
args += "@param {flatbuffers.Table=} obj\n";
|
||||
ret_type = "?flatbuffers.Table";
|
||||
is_union = true;
|
||||
break;
|
||||
default:
|
||||
ret_type = vectortypename;
|
||||
}
|
||||
GenDocComment(field.doc_comment, code_ptr, args +
|
||||
"@returns {" + vectortypename + "}");
|
||||
"@returns {" + ret_type + "}");
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
std::string prefix = MakeCamel(field.name, false);
|
||||
if (is_union) {
|
||||
prefix += "<T extends flatbuffers.Table>";
|
||||
}
|
||||
prefix += "(index: number";
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
if (is_union) {
|
||||
vectortypename = "T";
|
||||
code += prefix + ", obj:T";
|
||||
} else if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
vectortypename = GenPrefixedTypeName(vectortypename,
|
||||
vectortype.struct_def->file);
|
||||
code += prefix + ", obj?:" + vectortypename;
|
||||
@@ -781,7 +805,7 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
|
||||
} else {
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += " = function(index";
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT || is_union) {
|
||||
code += ", obj";
|
||||
} else if (vectortype.base_type == BASE_TYPE_STRING) {
|
||||
code += ", optionalEncoding";
|
||||
@@ -797,7 +821,9 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
|
||||
: "this.bb.__indirect(" + index + ")";
|
||||
code += ", this.bb)";
|
||||
} else {
|
||||
if (vectortype.base_type == BASE_TYPE_STRING) {
|
||||
if (is_union) {
|
||||
index = "obj, " + index;
|
||||
} else if (vectortype.base_type == BASE_TYPE_STRING) {
|
||||
index += ", optionalEncoding";
|
||||
}
|
||||
code += offset_prefix + GenGetter(vectortype, "(" + index + ")");
|
||||
@@ -1137,7 +1163,10 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
|
||||
}
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "}\n}\n";
|
||||
if (!object_namespace.empty()) {
|
||||
code += "}\n";
|
||||
}
|
||||
code += "}\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -67,7 +67,10 @@ namespace php {
|
||||
std::string &code = *code_ptr;
|
||||
code += "<?php\n";
|
||||
code = code + "// " + FlatBuffersGeneratedWarning() + "\n\n";
|
||||
code += "namespace " + name_space_name + ";\n\n";
|
||||
|
||||
if (!name_space_name.empty()) {
|
||||
code += "namespace " + name_space_name + ";\n\n";
|
||||
}
|
||||
|
||||
if (needs_imports) {
|
||||
code += "use \\Google\\FlatBuffers\\Struct;\n";
|
||||
@@ -428,6 +431,31 @@ namespace php {
|
||||
code += Indent + "}\n\n";
|
||||
}
|
||||
|
||||
// Get the value of a vector's union member. Uses a named return
|
||||
// argument to conveniently set the zero value for the result.
|
||||
void GetMemberOfVectorOfUnion(const FieldDef &field,
|
||||
std::string *code_ptr) {
|
||||
std::string &code = *code_ptr;
|
||||
auto vectortype = field.value.type.VectorType();
|
||||
|
||||
code += Indent + "/**\n";
|
||||
code += Indent + " * @param int offset\n";
|
||||
code += Indent + " * @return " + GenTypeGet(field.value.type) + "\n";
|
||||
code += Indent + " */\n";
|
||||
code += Indent + "public function get";
|
||||
code += MakeCamel(field.name);
|
||||
code += "($j, $obj)\n";
|
||||
code += Indent + "{\n";
|
||||
code += Indent + Indent +
|
||||
"$o = $this->__offset(" +
|
||||
NumToString(field.value.offset) +
|
||||
");\n";
|
||||
code += Indent + Indent + "return $o != 0 ? ";
|
||||
code += "$this->__union($obj, $this->__vector($o) + $j * ";
|
||||
code += NumToString(InlineSize(vectortype)) + " - $this->bb_pos) : null;\n";
|
||||
code += Indent + "}\n\n";
|
||||
}
|
||||
|
||||
// Recursively generate arguments for a constructor, to deal with nested
|
||||
// structs.
|
||||
static void StructBuilderArgs(const StructDef &struct_def,
|
||||
@@ -703,7 +731,9 @@ namespace php {
|
||||
break;
|
||||
case BASE_TYPE_VECTOR: {
|
||||
auto vectortype = field.value.type.VectorType();
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
if (vectortype.base_type == BASE_TYPE_UNION) {
|
||||
GetMemberOfVectorOfUnion(field, code_ptr);
|
||||
} else if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
|
||||
} else {
|
||||
GetMemberOfVectorOfNonStruct(field, code_ptr);
|
||||
|
||||
@@ -628,8 +628,8 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
|
||||
type.enum_def->underlying_type, &typefield));
|
||||
} else if (type.base_type == BASE_TYPE_VECTOR &&
|
||||
type.element == BASE_TYPE_UNION) {
|
||||
// Only cpp supports the union vector feature so far.
|
||||
if (opts.lang_to_generate != IDLOptions::kCpp) {
|
||||
// Only cpp, js and ts supports the union vector feature so far.
|
||||
if (!SupportsVectorOfUnions()) {
|
||||
return Error("Vectors of unions are not yet supported in all "
|
||||
"the specified programming languages.");
|
||||
}
|
||||
@@ -1571,6 +1571,11 @@ CheckedError Parser::CheckClash(std::vector<FieldDef*> &fields,
|
||||
return NoError();
|
||||
}
|
||||
|
||||
bool Parser::SupportsVectorOfUnions() const {
|
||||
return opts.lang_to_generate != 0 && (opts.lang_to_generate &
|
||||
~(IDLOptions::kCpp | IDLOptions::kJs | IDLOptions::kTs | IDLOptions::kPhp)) == 0;
|
||||
}
|
||||
|
||||
static bool compareFieldDefs(const FieldDef *a, const FieldDef *b) {
|
||||
auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str());
|
||||
auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str());
|
||||
@@ -2141,7 +2146,7 @@ CheckedError Parser::ParseRoot(const char *source, const char **include_paths,
|
||||
val_it != enum_def.vals.vec.end();
|
||||
++val_it) {
|
||||
auto &val = **val_it;
|
||||
if (opts.lang_to_generate != IDLOptions::kCpp &&
|
||||
if (!SupportsVectorOfUnions() &&
|
||||
val.union_type.struct_def && val.union_type.struct_def->fixed)
|
||||
return Error(
|
||||
"only tables can be union elements in the generated language: "
|
||||
|
||||
Reference in New Issue
Block a user