mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-26 21:52:18 +00:00
[TS] Escape keywords in typescript object names (#7137)
* Add Object to the list of reserved keywords. * Properly escape keywords in type names. * Properly escape keywords in enum names. * Properly escape keywords in enum field names.
This commit is contained in:
@@ -80,6 +80,7 @@ class TsGenerator : public BaseGenerator {
|
|||||||
"instanceof",
|
"instanceof",
|
||||||
"new",
|
"new",
|
||||||
"null",
|
"null",
|
||||||
|
"Object",
|
||||||
"return",
|
"return",
|
||||||
"super",
|
"super",
|
||||||
"switch",
|
"switch",
|
||||||
@@ -219,9 +220,7 @@ class TsGenerator : public BaseGenerator {
|
|||||||
if (reverse) return; // FIXME.
|
if (reverse) return; // FIXME.
|
||||||
std::string &code = *code_ptr;
|
std::string &code = *code_ptr;
|
||||||
GenDocComment(enum_def.doc_comment, code_ptr);
|
GenDocComment(enum_def.doc_comment, code_ptr);
|
||||||
std::string ns = GetNameSpace(enum_def);
|
code += "export enum " + EscapeKeyword(enum_def.name) + "{\n";
|
||||||
std::string enum_def_name = enum_def.name + (reverse ? "Name" : "");
|
|
||||||
code += "export enum " + enum_def.name + "{\n";
|
|
||||||
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
|
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
|
||||||
auto &ev = **it;
|
auto &ev = **it;
|
||||||
if (!ev.doc_comment.empty()) {
|
if (!ev.doc_comment.empty()) {
|
||||||
@@ -229,13 +228,15 @@ class TsGenerator : public BaseGenerator {
|
|||||||
GenDocComment(ev.doc_comment, code_ptr, " ");
|
GenDocComment(ev.doc_comment, code_ptr, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string escaped_name = EscapeKeyword(ev.name);
|
||||||
|
|
||||||
// Generate mapping between EnumName: EnumValue(int)
|
// Generate mapping between EnumName: EnumValue(int)
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
code += " '" + enum_def.ToString(ev) + "'";
|
code += " '" + enum_def.ToString(ev) + "'";
|
||||||
code += " = ";
|
code += " = ";
|
||||||
code += "'" + ev.name + "'";
|
code += "'" + escaped_name + "'";
|
||||||
} else {
|
} else {
|
||||||
code += " " + ev.name;
|
code += " " + escaped_name;
|
||||||
code += " = ";
|
code += " = ";
|
||||||
// Unfortunately, because typescript does not support bigint enums,
|
// Unfortunately, because typescript does not support bigint enums,
|
||||||
// for 64-bit enums, we instead map the enum names to strings.
|
// for 64-bit enums, we instead map the enum names to strings.
|
||||||
@@ -318,9 +319,9 @@ class TsGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
if (auto val = value.type.enum_def->FindByValue(value.constant)) {
|
if (auto val = value.type.enum_def->FindByValue(value.constant)) {
|
||||||
return AddImport(imports, *value.type.enum_def,
|
return EscapeKeyword(AddImport(imports, *value.type.enum_def,
|
||||||
*value.type.enum_def) +
|
*value.type.enum_def)) +
|
||||||
"." + val->name;
|
"." + EscapeKeyword(val->name);
|
||||||
} else {
|
} else {
|
||||||
return value.constant;
|
return value.constant;
|
||||||
}
|
}
|
||||||
@@ -357,7 +358,7 @@ class TsGenerator : public BaseGenerator {
|
|||||||
if (IsString(type)) {
|
if (IsString(type)) {
|
||||||
name = "string|Uint8Array";
|
name = "string|Uint8Array";
|
||||||
} else {
|
} else {
|
||||||
name = AddImport(imports, owner, *type.struct_def);
|
name = EscapeKeyword(AddImport(imports, owner, *type.struct_def));
|
||||||
}
|
}
|
||||||
return allowNull ? (name + "|null") : name;
|
return allowNull ? (name + "|null") : name;
|
||||||
}
|
}
|
||||||
@@ -450,7 +451,7 @@ class TsGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string GenerateNewExpression(const std::string &object_name) {
|
std::string GenerateNewExpression(const std::string &object_name) {
|
||||||
return "new " + object_name + "()";
|
return "new " + EscapeKeyword(object_name) + "()";
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateRootAccessor(StructDef &struct_def, std::string *code_ptr,
|
void GenerateRootAccessor(StructDef &struct_def, std::string *code_ptr,
|
||||||
@@ -570,11 +571,12 @@ class TsGenerator : public BaseGenerator {
|
|||||||
export_statement += "export { ";
|
export_statement += "export { ";
|
||||||
std::string symbols_expression;
|
std::string symbols_expression;
|
||||||
if (long_import_name.empty()) {
|
if (long_import_name.empty()) {
|
||||||
symbols_expression += import_name;
|
symbols_expression += EscapeKeyword(import_name);
|
||||||
if (parser_.opts.generate_object_based_api)
|
if (parser_.opts.generate_object_based_api)
|
||||||
symbols_expression += ", " + import_name + "T";
|
symbols_expression += ", " + import_name + "T";
|
||||||
} else {
|
} else {
|
||||||
symbols_expression += dependency.name + " as " + long_import_name;
|
symbols_expression += EscapeKeyword(dependency.name) + " as " +
|
||||||
|
EscapeKeyword(long_import_name);
|
||||||
if (parser_.opts.generate_object_based_api)
|
if (parser_.opts.generate_object_based_api)
|
||||||
symbols_expression +=
|
symbols_expression +=
|
||||||
", " + dependency.name + "T as " + long_import_name + "T";
|
", " + dependency.name + "T as " + long_import_name + "T";
|
||||||
@@ -616,7 +618,7 @@ class TsGenerator : public BaseGenerator {
|
|||||||
const auto &depc_comps = dependency.defined_namespace->components;
|
const auto &depc_comps = dependency.defined_namespace->components;
|
||||||
for (auto it = depc_comps.begin(); it != depc_comps.end(); it++) ns += *it;
|
for (auto it = depc_comps.begin(); it != depc_comps.end(); it++) ns += *it;
|
||||||
std::string unique_name = ns + dependency.name;
|
std::string unique_name = ns + dependency.name;
|
||||||
std::string import_name = dependency.name;
|
std::string import_name = EscapeKeyword(dependency.name);
|
||||||
std::string long_import_name;
|
std::string long_import_name;
|
||||||
if (imports.find(unique_name) != imports.end())
|
if (imports.find(unique_name) != imports.end())
|
||||||
return imports.find(unique_name)->second.name;
|
return imports.find(unique_name)->second.name;
|
||||||
@@ -900,7 +902,8 @@ class TsGenerator : public BaseGenerator {
|
|||||||
std::string pack_func_offset_decl;
|
std::string pack_func_offset_decl;
|
||||||
std::string pack_func_create_call;
|
std::string pack_func_create_call;
|
||||||
|
|
||||||
const auto struct_name = AddImport(imports, struct_def, struct_def);
|
const auto struct_name =
|
||||||
|
EscapeKeyword(AddImport(imports, struct_def, struct_def));
|
||||||
|
|
||||||
if (has_create) {
|
if (has_create) {
|
||||||
pack_func_create_call = " return " + struct_name + ".create" +
|
pack_func_create_call = " return " + struct_name + ".create" +
|
||||||
@@ -1096,6 +1099,8 @@ class TsGenerator : public BaseGenerator {
|
|||||||
unpack_func += " " + field_val;
|
unpack_func += " " + field_val;
|
||||||
unpack_to_func += " _o." + field_name_escaped + " = " + field_val + ";";
|
unpack_to_func += " _o." + field_name_escaped + " = " + field_val + ";";
|
||||||
|
|
||||||
|
// FIXME: if field_type and field_name_escaped are identical, then
|
||||||
|
// this generates invalid typescript.
|
||||||
constructor_func += " public " + field_name_escaped + ": " + field_type +
|
constructor_func += " public " + field_name_escaped + ": " + field_type +
|
||||||
" = " +
|
" = " +
|
||||||
field_default_val;
|
field_default_val;
|
||||||
@@ -1184,9 +1189,9 @@ class TsGenerator : public BaseGenerator {
|
|||||||
std::string object_namespace = GetNameSpace(struct_def);
|
std::string object_namespace = GetNameSpace(struct_def);
|
||||||
|
|
||||||
// Emit constructor
|
// Emit constructor
|
||||||
object_name = struct_def.name;
|
object_name = EscapeKeyword(struct_def.name);
|
||||||
GenDocComment(struct_def.doc_comment, code_ptr);
|
GenDocComment(struct_def.doc_comment, code_ptr);
|
||||||
code += "export class " + struct_def.name;
|
code += "export class " + object_name;
|
||||||
code += " {\n";
|
code += " {\n";
|
||||||
code += " bb: flatbuffers.ByteBuffer|null = null;\n";
|
code += " bb: flatbuffers.ByteBuffer|null = null;\n";
|
||||||
code += " bb_pos = 0;\n";
|
code += " bb_pos = 0;\n";
|
||||||
@@ -1274,8 +1279,8 @@ class TsGenerator : public BaseGenerator {
|
|||||||
else {
|
else {
|
||||||
switch (field.value.type.base_type) {
|
switch (field.value.type.base_type) {
|
||||||
case BASE_TYPE_STRUCT: {
|
case BASE_TYPE_STRUCT: {
|
||||||
const auto type =
|
const auto type = EscapeKeyword(
|
||||||
AddImport(imports, struct_def, *field.value.type.struct_def);
|
AddImport(imports, struct_def, *field.value.type.struct_def));
|
||||||
GenDocComment(field.doc_comment, code_ptr);
|
GenDocComment(field.doc_comment, code_ptr);
|
||||||
code += ConvertCase(field.name, Case::kLowerCamel);
|
code += ConvertCase(field.name, Case::kLowerCamel);
|
||||||
code += "(obj?:" + type + "):" + type + "|null {\n";
|
code += "(obj?:" + type + "):" + type + "|null {\n";
|
||||||
@@ -1617,10 +1622,10 @@ class TsGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
code += "):flatbuffers.Offset {\n";
|
code += "):flatbuffers.Offset {\n";
|
||||||
code += " " + struct_def.name + ".start" +
|
code += " " + object_name + ".start" +
|
||||||
GetPrefixedName(struct_def) + "(builder);\n";
|
GetPrefixedName(struct_def) + "(builder);\n";
|
||||||
|
|
||||||
std::string methodPrefix = struct_def.name;
|
std::string methodPrefix = object_name;
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
for (auto it = struct_def.fields.vec.begin();
|
||||||
it != struct_def.fields.vec.end(); ++it) {
|
it != struct_def.fields.vec.end(); ++it) {
|
||||||
const auto &field = **it;
|
const auto &field = **it;
|
||||||
@@ -1651,8 +1656,10 @@ class TsGenerator : public BaseGenerator {
|
|||||||
code += "}\n";
|
code += "}\n";
|
||||||
|
|
||||||
code += "\n";
|
code += "\n";
|
||||||
code += "static deserialize(buffer: Uint8Array):" + name + " {\n";
|
code += "static deserialize(buffer: Uint8Array):" + EscapeKeyword(name) +
|
||||||
code += " return " + AddImport(imports, struct_def, struct_def) +
|
" {\n";
|
||||||
|
code += " return " +
|
||||||
|
EscapeKeyword(AddImport(imports, struct_def, struct_def)) +
|
||||||
".getRootAs" + name + "(new flatbuffers.ByteBuffer(buffer))\n";
|
".getRootAs" + name + "(new flatbuffers.ByteBuffer(buffer))\n";
|
||||||
code += "}\n";
|
code += "}\n";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ if [ -x ../flatc ]; then
|
|||||||
../flatc --gen-object-api -b -I include_test monster_test.fbs unicode_test.json
|
../flatc --gen-object-api -b -I include_test monster_test.fbs unicode_test.json
|
||||||
../flatc --ts --gen-name-strings --gen-mutable --gen-object-api -o union_vector union_vector/union_vector.fbs
|
../flatc --ts --gen-name-strings --gen-mutable --gen-object-api -o union_vector union_vector/union_vector.fbs
|
||||||
../flatc --ts --gen-name-strings optional_scalars.fbs
|
../flatc --ts --gen-name-strings optional_scalars.fbs
|
||||||
|
../flatc --ts --gen-name-strings --gen-object-api --gen-mutable typescript_keywords.fbs
|
||||||
fi
|
fi
|
||||||
tsc
|
tsc
|
||||||
node -r esm JavaScriptTest
|
node -r esm JavaScriptTest
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"monster_test.ts",
|
"monster_test.ts",
|
||||||
|
"typescript_keywords.ts",
|
||||||
"my-game/**/*.ts",
|
"my-game/**/*.ts",
|
||||||
|
"typescript/**/*.ts",
|
||||||
"optional_scalars/**/*.ts",
|
"optional_scalars/**/*.ts",
|
||||||
"namespace_test/**/*.ts",
|
"namespace_test/**/*.ts",
|
||||||
"union_vector/**/*.ts"
|
"union_vector/**/*.ts"
|
||||||
|
|||||||
15
tests/typescript_keywords.fbs
Normal file
15
tests/typescript_keywords.fbs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// This file includes a variety of keywords meant to deliberately interfere
|
||||||
|
// with typescript keywords.
|
||||||
|
namespace typescript;
|
||||||
|
|
||||||
|
enum class: int {
|
||||||
|
new,
|
||||||
|
instanceof,
|
||||||
|
}
|
||||||
|
|
||||||
|
table Object {
|
||||||
|
return:int;
|
||||||
|
if:int;
|
||||||
|
switch:int;
|
||||||
|
enum:class;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user