Fix 64-bit numeric enum values in typescript (#7135)

* Fix 64-bit default numeric enum values in typescript

If you had a default value that wasn't a valid enum value (e.g., a zero
if you used a bit_flag setting, like you get with AdvancedFeatures
in reflection.fbs), we weren't using BigInt.

* Run generate_code.py

* [DART] Handle deprecated fields & invalid enum defaults

* Update .NET test
This commit is contained in:
James Kuszmaul
2022-03-04 21:57:48 -08:00
committed by GitHub
parent 1a4c405662
commit 9ed1323044
39 changed files with 1342 additions and 275 deletions

View File

@@ -227,7 +227,11 @@ class DartGenerator : public BaseGenerator {
GenDocComment(enum_def.doc_comment, &code, "");
auto name = enum_def.is_union ? enum_def.name + "TypeId" : enum_def.name;
auto is_bit_flags = enum_def.attributes.Lookup("bit_flags");
const bool is_bit_flags =
enum_def.attributes.Lookup("bit_flags") != nullptr;
// The flatbuffer schema language allows bit flag enums to potentially have
// a default value of zero, even if it's not a valid enum value...
const bool permit_zero = is_bit_flags;
code += "class " + name + " {\n";
code += " final int value;\n";
@@ -235,8 +239,14 @@ class DartGenerator : public BaseGenerator {
code += " factory " + name + ".fromValue(int value) {\n";
code += " final result = values[value];\n";
code += " if (result == null) {\n";
code += " throw StateError('Invalid value $value for bit flag enum ";
if (permit_zero) {
code += " if (value == 0) {\n";
code += " return " + name + "._(0);\n";
code += " } else {\n";
}
code += " throw StateError('Invalid value $value for bit flag enum ";
code += name + "');\n";
if (permit_zero) { code += " }\n"; }
code += " }\n";
code += " return result;\n";
@@ -538,13 +548,11 @@ class DartGenerator : public BaseGenerator {
if (!struct_def.fixed && !defaultValue.empty()) {
if (IsEnum(field.value.type)) {
auto &enum_def = *field.value.type.enum_def;
for (auto enumIt = enum_def.Vals().begin();
enumIt != enum_def.Vals().end(); ++enumIt) {
auto &ev = **enumIt;
if (enum_def.ToString(ev) == defaultValue) {
constructor_args += " = " + enum_def.name + "." + ev.name;
break;
}
if (auto val = enum_def.FindByValue(defaultValue)) {
constructor_args += " = " + enum_def.name + "." + val->name;
} else {
constructor_args +=
" = const " + enum_def.name + "._(" + defaultValue + ")";
}
} else {
constructor_args += " = " + defaultValue;
@@ -870,7 +878,7 @@ class DartGenerator : public BaseGenerator {
code += " void begin() {\n";
code += " fbBuilder.startTable(" +
NumToString(non_deprecated_fields.size()) + ");\n";
NumToString(struct_def.fields.vec.size()) + ");\n";
code += " }\n\n";
for (auto it = non_deprecated_fields.begin();
@@ -1051,8 +1059,8 @@ class DartGenerator : public BaseGenerator {
code += StructObjectBuilderBody(non_deprecated_fields, prependUnderscore,
pack);
} else {
code += TableObjectBuilderBody(non_deprecated_fields, prependUnderscore,
pack);
code += TableObjectBuilderBody(struct_def, non_deprecated_fields,
prependUnderscore, pack);
}
return code;
}
@@ -1089,11 +1097,12 @@ class DartGenerator : public BaseGenerator {
}
std::string TableObjectBuilderBody(
const StructDef &struct_def,
const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
bool prependUnderscore = true, bool pack = false) {
std::string code;
code += " fbBuilder.startTable(" +
NumToString(non_deprecated_fields.size()) + ");\n";
NumToString(struct_def.fields.vec.size()) + ");\n";
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {

View File

@@ -237,7 +237,16 @@ class TsGenerator : public BaseGenerator {
} else {
code += " " + ev.name;
code += " = ";
code += enum_def.ToString(ev);
// Unfortunately, because typescript does not support bigint enums,
// for 64-bit enums, we instead map the enum names to strings.
switch (enum_def.underlying_type.base_type) {
case BASE_TYPE_LONG:
case BASE_TYPE_ULONG: {
code += "'" + enum_def.ToString(ev) + "'";
break;
}
default: code += enum_def.ToString(ev);
}
}
code += (it + 1) != enum_def.Vals().end() ? ",\n" : "\n";
@@ -299,11 +308,23 @@ class TsGenerator : public BaseGenerator {
const auto &value = field.value;
if (value.type.enum_def && value.type.base_type != BASE_TYPE_UNION &&
value.type.base_type != BASE_TYPE_VECTOR) {
if (auto val = value.type.enum_def->FindByValue(value.constant)) {
return AddImport(imports, *value.type.enum_def, *value.type.enum_def) +
"." + val->name;
} else {
return value.constant;
// If the value is an enum with a 64-bit base type, we have to just
// return the bigint value directly since typescript does not support
// enums with bigint backing types.
switch (value.type.base_type) {
case BASE_TYPE_LONG:
case BASE_TYPE_ULONG: {
return "BigInt('" + value.constant + "')";
}
default: {
if (auto val = value.type.enum_def->FindByValue(value.constant)) {
return AddImport(imports, *value.type.enum_def,
*value.type.enum_def) +
"." + val->name;
} else {
return value.constant;
}
}
}
}