Squashed 'third_party/flatbuffers/' changes from e5f331db9..bc44fad35
bc44fad35 UnPackTo disable merge by default (#7527)
4fca4dc60 [TS/JS] Move TS tests to dedicated folder and deps upgrade (#7508)
036032373 Bump junit from 4.13 to 4.13.1 in /java (#7526)
89dfb43f3 Replace `bash JavaTest.sh` with `mvn test` (#7500)
c49aff4b6 enabled cpp17 tests in CI (#7524)
56e60223c prevent force_align attribute on enums (#7523)
89b1f5aa1 remove travis config (#7522)
b90159823 [Java][Flexbuffers] Add API to add nullables into the buffer. (#7521)
8cdc6a288 Install BuildFlatBuffers.cmake (#7519)
a67e35aff Moves all of the swift test code into tests/swift (#7509)
f124e41ae Updated Readme
4c954181c [Java][FlexBuffers] throwing exception for untyped fixed vectors (#7507)
7f7547737 [Android] Remove maven dependency of flatbuffers and use source folder (#7503)
a79d61ea8 Fixes issue with cocoapods failing to be published because of docc (#7505)
d465b39c3 [CMake]: fix breaking find_package change (#7499) (#7502)
c5a609dc2 [C#] Prepares for official Nuget release (#7496)
5634dc3d0 [ISSUE-6268] returns NaN insteadof nan (#7498)
37e37b8ca Updates cocoapods version (#7497)
8fd4534fb update android multidex setting (#7495)
d5427da52 Disable Android Build (#7494)
06c5c7ed0 FlatBuffers Version 2.0.8 (#7492)
b190ce11b Verifier Refinements (#7490)
bf5d23230 Namer applied to Typescript generator (#7488)
ce382d6dd [TS/JS] Add rollup and config to generate iife flatbuffers bundle (#7449)
41d9add7e C++: Add option to skip verifying nested flatbuffers (#7489)
6a8742754 [C++] support native_inline attribute for vector of tables (#7479)
694add668 Refactor test.cpp (#7487)
7edf8c908 Update scorecard to 1.1.2
b86387442 Fix typos (#7483)
e2eb5ee67 Include <array> head in stl_emulation.h (#7480)
994502b6d Version number in file package.json updated to 2.0.7 (#7476)
fa41e8367 [C++] Fixed crash when copying table with empty shared strings (#7477)
799cc8f7b Use type traits for specialization (#7475)
b7eb44147 Disable RTTI and rework use in idl_gen_ts.cpp (#7474)
8d01c5859 CMake project version detection made more robust (#7473)
237e8b71f Moved compiler warnings around (#7471)
eeb8fd60d Include builder.addOffset for vector of structs (#7470)
fef2ffc4d Use schema include name for keep-prefix (#7469)
8367664f1 Flatbuffers Version 2.0.7 (#7462)
d6f06c33f Reworked keep prefix (#7456)
627e8bf36 update grpc version (#7457)
883c42b7d disabling unpackto optimization (#7459)
7aae0af30 Remove old GRPC bash script and convert to python3 (#7454)
b057aa917 Grouped anonymous namespaces together, (#7455)
f1b26ff7f Change to GetTypeName (#7453)
9610a666b Generate SLSA signatures for Released zip files (#7450)
1e0f75a64 [WIP] speedup (#7452)
82b75407a Wrap types in namespace for --ts-flat-files and --gen-all (#7451)
f7c511957 Audit and fixups for GCC and Clang (#7212)
a66de58af Partial support for --ts-flat-files and --gen-all (#7446)
a3508f36d [Kotlin] Make sure namespace path exist for code generation (#7357)
137fec716 Stop using __has_trivial_copy on recent clang versions. (#7443)
214125e41 [C#] Rework how sorted vectors are looked up (#7441)
44a7dc999 Define minimum buffer size (#7440)
3cc2daa78 make_span overloads for pointer to vector (#7374) (#7435)
fa1174aa7 [TypeScript] Fix namespaceless schema generation (#7432)
83d4e2a10 Add checks to verifier (#7438)
8a09f3fb0 Fix FlexBuffers JS/TS bug https://github.com/google/flatbuffers/issues/6934 (#7434)
9dbe819ef Add flatc python tests to CI (#7437)
67c414958 Update TypeScriptTest.py to work better cross platform (#7436)
8b8c7dbdf Update gitingore to reflect name change (#7431)
2ee20a5f3 Remove auto including locale functions (#7430)
4be605604 [C++] Set StructDef::has_key property when deserializing from binary schema (#7386) (#7428)
fc5d86f1e [C++] Make template parameter in stl_emulation.h more explicit to avoid conflicts with cpprestsdk U macro (#7424)
9dce287ad Issue#6959 :Updated Automatically generated rust files. (#7425)
7798be3bb avoid zero-as-null-pointer warning (#7423)
966362e07 [C++] Vector of Tables equality (#7415)
a89c279ed [golang] Perform keyword escaping after case conversion (#7421)
a212b3c03 Turn of fail fast for C++ CI
9230f600d Remove stringop-overflow from error (#7422)
c79362156 [golang] Add support for text parsing with json struct tags (#7353)
ee2ced236 Moved TypeScriptTests to python script (#7411)
468c00a3f Rebased: grpc/compiler: Respect filename suffix and extension during code generation (#7414)
47c757f71 Add tests for flatc (#7405)
9a5ff8900 Add FLATBUFFERS_STRICT_MODE (#7408)
950444a34 [TS] Use TextEncoder and TextDecoder (#7400)
30d76198c Compilation issue msys2 #7399 (#7409)
cce3a66f0 Delete .travis directory
8d1cc6ac7 Revert "Compilation issue msys2 (#7403)" (#7407)
5b207639a Update readme.md
359e0f9d6 Revert "grpc/compiler: Respect filename suffix and extension during code generation (#7343)" (#7406)
ebbed0513 Delete cpp-linter.yml
aa395e5a5 (#7323) Rename CMake files according to project name (#7378)
32328075d Fix error msg format when generate GRPC failed (#7350)
97e89c5ac grpc/compiler: Respect filename suffix and extension during code generation (#7343)
5f6672be4 Fix Clang-Cl compile on Windows (#7308)
28e858c85 [TS/Bazel] Minor improvements to typescript.bzl (#7300)
987bebe67 [TS] fix incorrect reverse when writting array of structs (#7271)
ec0129369 Fix FlexBuffers Verifier tracking vectors reuse at wrong offset
50dd385b3 Add missing const (#7401)
da702cfd8 Compilation issue msys2 (#7403)
6e2791640 keep-prefix keeps relative pathing (#7394)
52fce5e53 fix(#7360): grpc used deprecated functions (#7361)
b7f13cd8e cpp_generator: comment out unused parameter to avoid warnings (#7381)
e42985e5a Updated Newtonsoft.Json to 13.0.1 (#7393)
0a8064637 Fix references to LICENSE file (#7377)
b9eea76a8 [Dart] Implement putBool to fix errors when serializing structs with bools (#7359)
1b9030015 Bump Newtonsoft.Json from 12.0.3 to 13.0.1 in /tests/FlatBuffers.Test (#7363)
83a43fc79 Reenable optional json (#7352)
5f0137602 Only include direct included filed (#7348)
9a1913a87 Revert "Implement optional scalars for JSON (#7322)" (#7351)
b4647beb8 Revert "Move reflection_ts_fbs into a separate directory (#7342)" (#7349)
d6060977a Remove asserting in verifier for flattests
987aa5b5e move -Wextra-semi to GCC 8.0+
42acdb63c [TS] Don't generate self-imports with --ts-flat-file (#7340)
0cc1aeb8c [golang] Create missing namespace directory structure (#7324) (#7325)
ba6c67170 [Kotlin] Remove download benchmark files dependency (#7314)
d2f33fc45 Disable Android on Linux CI build
0d1b72cbc [TS] fix ts import path issue (#7298)
9fce2fbf2 replace io/ioutil to os (#7281)
a18ea40d6 Implement optional scalars for JSON (#7322)
090caa280 Move reflection_ts_fbs into a separate directory (#7342)
49e1ea333 Implement optional scalars for Python (#7318)
11a198870 Started implementation for private flags in rust (#7269)
967df08b1 Adds full supposed for Wasm in the swift lib (#7328)
9aa08a429 Use keep case for Rust union discriminant type. (#7321)
9e8c758f5 Add explicit return types to lobster generated code (#7312)
74a25536b Add size check to fix out of bounds read risk (#7304)
12917af8a Update Rust docs page (#7296)
1ea2472f7 [swift] add had<ArrayName> property for arrays to check presence in a message (#7280)
0fe13cb28 Remove span ConstIterator/cbegin()/cend(). (#7295)
385dddc66 Namerkot (#7245)
750dde766 Make `flatc` generate Rust files not requiring `std` (#7273)
9917a168c [swift] Make swift module public (#7274)
76d3cca19 Rust: fix a name conflict when building with "no_std" feature (#7268)
c86e6d0e3 json inf parsing
d34dc32c2 fix include order
234d86c92 fixed off-by-one in parser
746c73b91 Add Annotations for Monster schema and example buffer
0bbfd4b2e fixes for annotator
716521953 Update readme.md (#7257)
a45f564cf [performance] Add aggressive systematic inlining in ByteBuffer and FlatBufferBuilder (#7253)
9d45a6403 more google merge fixes
ccfb4c20b Handle +/-inf in protos (#7256)
7bcd857b8 Specialize CreateVector with std::initializer_list (#7254)
23c8ab34c Swift update performance benchmark infrastructure (#7255)
70002dc5c various fixes for google merge
6e0e79f24 Add test for nested buffer verifier (#7252)
b856368d7 Turn off go modules temporary until we get a proper fix (#7251)
e37156a30 Keep the underlying storage capacity when clearing the FlatBufferBuilder. Gives a significant performance boost for serialisation of many small messages. (#7250)
a10b0e546 Java namer variable keep case (#7249)
275b73994 allow overriding FLATBUFFERS_MAX_ALIGNMENT
9d1ce9a10 Add parameter back to EndVector (#7246)
79afe6c3d Make Java namespaces keep case by default (#7243)
c6dbb2230 Add write permissions for labeller
18bacd3ea Expand test to make sure {}-initializers are properly understood by template. (#7242)
a2c913aec Add -Wnon-virtual-dtor
67b33b294 set workflows permissions to read-only (#7239)
7b5fd2bd0 [Kotlin] Fix key lookup returning null clashing with default value (#7237)
7181d7770 [Java] Fix key lookup returning null clashing with default value (#7236)
7f663b120 Allow CreateVectorOfStrings() to work with any string-type. (#7238)
173ebb694 Fixes a bug where the create function doesnt optional + required items (#7228)
d65823948 [Kotlin] Update gradle to 7.4.1 and simplify config files. (#7231)
ab4bf59e8 remove toascii (#7234)
eee44bbb2 disable cpp-linter (#7229)
a63fa51a1 Create cpp-linter.yml (#7208)
2049e5210 Adds a way to verify/exposes Entities ids (#7221)
832c618f5 Adds implementation flag for swift (#7202)
14615699f Started to migrate to target_compile_options (#7222)
20aad0c41 [C++] stl_emulation span::count_ is not const anymore (#7226) (#7227)
f083b33f2 code gen flexbuffer verifier (#7207)
bf17df346 [C++] generate sorted #include directives (#7213)
35281dedb Fix for [C++] flatc generates invalid Code in the default constructor for structs, when --cpp-field-case-style is used #7209 (#7211)
c9651b742 Add overloads for C# ByteBuffer/FlatBufferBuilder to allow adding vector blocks from ArraySegments or IntPtr (#7193)
26c3b3ada Update codeql.yml
da6e1b985 Update codeql.yml
ad27d751e Added Oss fuzz badge
0aab623cb Create codeql.yml
6a446bdd8 maximize parallel builds in CI (#7206)
21fb5cbbc Create scorecards.yml
0da6f9486 [C++] Static assert on Flatbuffers Version (#7203)
59e971308 reduce fuzzing time to 1 minute in CI
40866a892 fixed padding in struct for annotated binary (#7199)
b71d968fa Apply Namer prefix/suffix to other generators (#7197)
fac0d7be0 Apply Namer to Java. (#7194)
6c5603fd9 [C#] Fix collision of field name and type name (#7149)
2d21853a7 monster fuzzer fix for json default scalars
fec1a8d01 [swift] Add bazel configuration for Swift (#7195)
7fd857623 structured comments (#7192)
a4cb1599d Namerdart (#7187)
ae4ce7265 fuzzed binary annotator (#7188)
e2be0c0b0 Handle root offset and root table vtable invalidation (#7177)
2ad408697 [TS] Fix generation of struct members in object api (#7148)
4213d9105 VerifySizePrefixed (reflection::Schema) and GetAnySizePrefixedRoot added (#7181)
5a13f622c Correctly parse lists of enums in Dart generated code (#7157)
23a7e4e0b Adds no-includes flags to the swift code generator (#7182)
eeb49c275 Move flatbuffer_ts_library to typescript.bzl (#7183)
824763b31 Typo in flatc options (warning-as-errors instead of warnings-as-errors) (#7180)
d3aeee32b Annotated Flatbuffer Binary (#7174)
0bceba24d [Lua] Apply Namer to Lua (#7171)
b8c77d404 Make inclusion of header <optional> opt-out via macro (#7168)
8468eab83 Namersw (#7167)
2b2e8d4ae Nameroverloads (#7164)
b80b32bfa Use DESCRIPTION only if CMake version >= 3.9 (#7166)
Change-Id: Ic2681dabb1a798b7515e62753ee06aecb9933260
git-subtree-dir: third_party/flatbuffers
git-subtree-split: bc44fad35271e43fd7a79b4d691ac9e41708797f
Signed-off-by: Austin Schuh <austin.schuh@bluerivertech.com>
diff --git a/src/idl_gen_ts.cpp b/src/idl_gen_ts.cpp
index faf4345..32ab863 100644
--- a/src/idl_gen_ts.cpp
+++ b/src/idl_gen_ts.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-// independent from idl_parser, since this code is not needed for most clients
#include <algorithm>
#include <cassert>
#include <unordered_map>
@@ -24,21 +23,67 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
+#include "idl_namer.h"
namespace flatbuffers {
-
+namespace {
struct ImportDefinition {
std::string name;
std::string import_statement;
std::string export_statement;
std::string bare_file_path;
std::string rel_file_path;
+ std::string object_name;
const Definition *dependent = nullptr;
const Definition *dependency = nullptr;
};
+Namer::Config TypeScriptDefaultConfig() {
+ return { /*types=*/Case::kKeep,
+ /*constants=*/Case::kUnknown,
+ /*methods=*/Case::kLowerCamel,
+ /*functions=*/Case::kLowerCamel,
+ /*fields=*/Case::kLowerCamel,
+ /*variables=*/Case::kLowerCamel,
+ /*variants=*/Case::kKeep,
+ /*enum_variant_seperator=*/"::",
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+ /*namespaces=*/Case::kKeep,
+ /*namespace_seperator=*/"_",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kDasher,
+ /*directories=*/Case::kDasher,
+ /*output_path=*/"",
+ /*filename_suffix=*/"_generated",
+ /*filename_extension=*/".ts" };
+}
+
+std::set<std::string> TypescriptKeywords() {
+ // List of keywords retrieved from here:
+ // https://github.com/microsoft/TypeScript/issues/2536
+ return {
+ "arguments", "break", "case", "catch", "class", "const",
+ "continue", "debugger", "default", "delete", "do", "else",
+ "enum", "export", "extends", "false", "finally", "for",
+ "function", "if", "import", "in", "instanceof", "new",
+ "null", "Object", "return", "super", "switch", "this",
+ "throw", "true", "try", "typeof", "var", "void",
+ "while", "with", "as", "implements", "interface", "let",
+ "package", "private", "protected", "public", "static", "yield",
+ };
+}
+
enum AnnotationType { kParam = 0, kType = 1, kReturns = 2 };
+template<typename T> struct SupportsObjectAPI : std::false_type {};
+
+template<> struct SupportsObjectAPI<StructDef> : std::true_type {};
+
+} // namespace
+
namespace ts {
// Iterate through all definitions we haven't generate code for (enums, structs,
// and tables) and output them to a single file.
@@ -48,83 +93,53 @@
TsGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
- : BaseGenerator(parser, path, file_name, "", ".", "ts") {
- // clang-format off
+ : BaseGenerator(parser, path, file_name, "", "_", "ts"),
+ namer_(WithFlagOptions(TypeScriptDefaultConfig(), parser.opts, path),
+ TypescriptKeywords()) {}
- // List of keywords retrieved from here:
- // https://github.com/microsoft/TypeScript/issues/2536
- // One per line to ease comparisons to that list are easier
- static const char *const keywords[] = {
- "argument",
- "break",
- "case",
- "catch",
- "class",
- "const",
- "continue",
- "debugger",
- "default",
- "delete",
- "do",
- "else",
- "enum",
- "export",
- "extends",
- "false",
- "finally",
- "for",
- "function",
- "if",
- "import",
- "in",
- "instanceof",
- "new",
- "null",
- "Object",
- "return",
- "super",
- "switch",
- "this",
- "throw",
- "true",
- "try",
- "typeof",
- "var",
- "void",
- "while",
- "with",
- "as",
- "implements",
- "interface",
- "let",
- "package",
- "private",
- "protected",
- "public",
- "static",
- "yield",
- nullptr,
- // clang-format on
- };
-
- for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
- }
bool generate() {
- if (parser_.opts.ts_flat_file && parser_.opts.generate_all) {
- // Not implemented; warning message should have beem emitted by flatc.
- return false;
- }
generateEnums();
generateStructs();
generateEntry();
return true;
}
+ bool IncludeNamespace() const {
+ // When generating a single flat file and all its includes, namespaces are
+ // important to avoid type name clashes.
+ return parser_.opts.ts_flat_file && parser_.opts.generate_all;
+ }
+
+ std::string GetTypeName(const EnumDef &def, const bool = false,
+ const bool force_ns_wrap = false) {
+ if (IncludeNamespace() || force_ns_wrap) {
+ return namer_.NamespacedType(def);
+ }
+ return namer_.Type(def);
+ }
+
+ std::string GetTypeName(const StructDef &def, const bool object_api = false,
+ const bool force_ns_wrap = false) {
+ if (object_api && parser_.opts.generate_object_based_api) {
+ if (IncludeNamespace() || force_ns_wrap) {
+ return namer_.NamespacedObjectType(def);
+ } else {
+ return namer_.ObjectType(def);
+ }
+ } else {
+ if (IncludeNamespace() || force_ns_wrap) {
+ return namer_.NamespacedType(def);
+ } else {
+ return namer_.Type(def);
+ }
+ }
+ }
+
// Save out the generated code for a single class while adding
// declaration boilerplate.
- bool SaveType(const Definition &definition, const std::string &classcode,
+ bool SaveType(const Definition &definition, const std::string &class_code,
import_set &imports, import_set &bare_imports) {
- if (!classcode.length()) return true;
+ if (!class_code.length()) return true;
std::string code;
@@ -144,25 +159,24 @@
if (!imports.empty()) code += "\n\n";
}
- code += classcode;
- auto filename =
- NamespaceDir(*definition.defined_namespace, true) +
- ConvertCase(definition.name, Case::kDasher, Case::kUpperCamel) + ".ts";
+ code += class_code;
+
if (parser_.opts.ts_flat_file) {
flat_file_ += code;
+ flat_file_ += "\n";
flat_file_definitions_.insert(&definition);
return true;
} else {
- return SaveFile(filename.c_str(), code, false);
+ auto dirs = namer_.Directories(*definition.defined_namespace);
+ EnsureDirExists(dirs);
+ auto basename = dirs + namer_.File(definition, SkipFile::Suffix);
+
+ return SaveFile(basename.c_str(), code, false);
}
}
private:
- std::unordered_set<std::string> keywords_;
-
- std::string EscapeKeyword(const std::string &name) const {
- return keywords_.find(name) == keywords_.end() ? name : name + "_";
- }
+ IdlNamer namer_;
import_set imports_all_;
@@ -177,6 +191,10 @@
// This maps from import names to types to import.
std::map<std::string, std::map<std::string, std::string>>
flat_file_import_declarations_;
+ // For flat file codegen, tracks whether we need to import the flatbuffers
+ // library itself (not necessary for files that solely consist of enum
+ // definitions).
+ bool import_flatbuffers_lib_ = false;
// Generate code for all enums.
void generateEnums() {
@@ -200,6 +218,7 @@
import_set bare_imports;
import_set imports;
AddImport(bare_imports, "* as flatbuffers", "flatbuffers");
+ import_flatbuffers_lib_ = true;
auto &struct_def = **it;
std::string declcode;
GenStruct(parser_, struct_def, &declcode, imports);
@@ -210,38 +229,45 @@
// Generate code for a single entry point module.
void generateEntry() {
- std::string code;
+ std::string code =
+ "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
if (parser_.opts.ts_flat_file) {
- code += "import * as flatbuffers from 'flatbuffers';\n";
- for (const auto &it : flat_file_import_declarations_) {
- // Note that we do end up generating an import for ourselves, which
- // should generally be harmless.
- // TODO: Make it so we don't generate a self-import; this will also
- // require modifying AddImport to ensure that we don't use
- // namespace-prefixed names anywhere...
- std::string file = it.first;
- if (file.empty()) {
- continue;
- }
- std::string noext = flatbuffers::StripExtension(file);
- std::string basename = flatbuffers::StripPath(noext);
- std::string include_file = GeneratedFileName(
- parser_.opts.include_prefix,
- parser_.opts.keep_include_path ? noext : basename, parser_.opts);
- // TODO: what is the right behavior when different include flags are
- // specified here? Should we always be adding the "./" for a relative
- // path or turn it off if --include-prefix is specified, or something
- // else?
- std::string include_name = "./" + flatbuffers::StripExtension(include_file);
- code += "import {";
- for (const auto &pair : it.second) {
- code += EscapeKeyword(pair.first) + " as " +
- EscapeKeyword(pair.second) + ", ";
- }
- code.resize(code.size() - 2);
- code += "} from '" + include_name + "';\n";
+ if (import_flatbuffers_lib_) {
+ code += "import * as flatbuffers from 'flatbuffers';\n";
+ code += "\n";
}
- code += "\n\n";
+ // Only include import statements when not generating all.
+ if (!parser_.opts.generate_all) {
+ for (const auto &it : flat_file_import_declarations_) {
+ // Note that we do end up generating an import for ourselves, which
+ // should generally be harmless.
+ // TODO: Make it so we don't generate a self-import; this will also
+ // require modifying AddImport to ensure that we don't use
+ // namespace-prefixed names anywhere...
+ std::string file = it.first;
+ if (file.empty()) { continue; }
+ std::string noext = flatbuffers::StripExtension(file);
+ std::string basename = flatbuffers::StripPath(noext);
+ std::string include_file = GeneratedFileName(
+ parser_.opts.include_prefix,
+ parser_.opts.keep_prefix ? noext : basename, parser_.opts);
+ // TODO: what is the right behavior when different include flags are
+ // specified here? Should we always be adding the "./" for a relative
+ // path or turn it off if --include-prefix is specified, or something
+ // else?
+ std::string include_name =
+ "./" + flatbuffers::StripExtension(include_file);
+ code += "import {";
+ for (const auto &pair : it.second) {
+ code += namer_.EscapeKeyword(pair.first) + " as " +
+ namer_.EscapeKeyword(pair.second) + ", ";
+ }
+ code.resize(code.size() - 2);
+ code += "} from '" + include_name + ".js';\n";
+ }
+ code += "\n";
+ }
+
code += flat_file_;
const std::string filename =
GeneratedFileName(path_, file_name_, parser_.opts);
@@ -250,7 +276,8 @@
for (auto it = imports_all_.begin(); it != imports_all_.end(); it++) {
code += it->second.export_statement + "\n";
}
- std::string path = "./" + path_ + file_name_ + ".ts";
+ const std::string path =
+ GeneratedFileName(path_, file_name_, parser_.opts);
SaveFile(path.c_str(), code, false);
}
}
@@ -286,7 +313,9 @@
if (reverse) return; // FIXME.
std::string &code = *code_ptr;
GenDocComment(enum_def.doc_comment, code_ptr);
- code += "export enum " + EscapeKeyword(enum_def.name) + "{\n";
+ code += "export enum ";
+ code += GetTypeName(enum_def);
+ code += " {\n";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
if (!ev.doc_comment.empty()) {
@@ -294,15 +323,13 @@
GenDocComment(ev.doc_comment, code_ptr, " ");
}
- const std::string escaped_name = EscapeKeyword(ev.name);
-
// Generate mapping between EnumName: EnumValue(int)
if (reverse) {
code += " '" + enum_def.ToString(ev) + "'";
code += " = ";
- code += "'" + escaped_name + "'";
+ code += "'" + namer_.Variant(ev) + "'";
} else {
- code += " " + escaped_name;
+ code += " " + namer_.Variant(ev);
code += " = ";
// Unfortunately, because typescript does not support bigint enums,
// for 64-bit enums, we instead map the enum names to strings.
@@ -324,7 +351,7 @@
code += GenUnionConvFunc(enum_def.underlying_type, imports);
}
- code += "\n\n";
+ code += "\n";
}
static std::string GenType(const Type &type) {
@@ -359,8 +386,8 @@
return GenBBAccess() + ".__union_with_string" + arguments;
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType(), arguments);
default: {
- auto getter = GenBBAccess() + ".read" +
- ConvertCase(GenType(type), Case::kUpperCamel) + arguments;
+ auto getter = GenBBAccess() + "." +
+ namer_.Method("read_" + GenType(type)) + arguments;
if (type.base_type == BASE_TYPE_BOOL) { getter = "!!" + getter; }
return getter;
}
@@ -385,9 +412,10 @@
}
default: {
if (auto val = value.type.enum_def->FindByValue(value.constant)) {
- return EscapeKeyword(AddImport(imports, *value.type.enum_def,
- *value.type.enum_def)) +
- "." + EscapeKeyword(val->name);
+ return AddImport(imports, *value.type.enum_def,
+ *value.type.enum_def)
+ .name +
+ "." + namer_.Variant(*val);
} else {
return value.constant;
}
@@ -411,7 +439,9 @@
return "BigInt('" + value.constant + "')";
}
- default: return value.constant;
+ default:
+ if (value.constant == "nan") { return "NaN"; }
+ return value.constant;
}
}
@@ -424,7 +454,7 @@
if (IsString(type)) {
name = "string|Uint8Array";
} else {
- name = EscapeKeyword(AddImport(imports, owner, *type.struct_def));
+ name = AddImport(imports, owner, *type.struct_def).name;
}
return allowNull ? (name + "|null") : name;
}
@@ -437,7 +467,8 @@
default:
if (IsScalar(type.base_type)) {
if (type.enum_def) {
- const auto enum_name = AddImport(imports, owner, *type.enum_def);
+ const auto enum_name =
+ AddImport(imports, owner, *type.enum_def).name;
return allowNull ? (enum_name + "|null") : enum_name;
}
return allowNull ? "number|null" : "number";
@@ -447,7 +478,7 @@
}
// Returns the method name for use with add/put calls.
- static std::string GenWriteMethod(const Type &type) {
+ std::string GenWriteMethod(const Type &type) {
// Forward to signed versions since unsigned versions don't exist
switch (type.base_type) {
case BASE_TYPE_UTYPE:
@@ -458,9 +489,8 @@
default: break;
}
- return IsScalar(type.base_type)
- ? ConvertCase(GenType(type), Case::kUpperCamel)
- : (IsStruct(type) ? "Struct" : "Offset");
+ return IsScalar(type.base_type) ? namer_.Type(GenType(type))
+ : (IsStruct(type) ? "Struct" : "Offset");
}
template<typename T> static std::string MaybeAdd(T value) {
@@ -490,8 +520,8 @@
}
}
- static void GenStructBody(const StructDef &struct_def, std::string *body,
- const std::string &nameprefix) {
+ void GenStructBody(const StructDef &struct_def, std::string *body,
+ const std::string &nameprefix) {
*body += " builder.prep(";
*body += NumToString(struct_def.minalign) + ", ";
*body += NumToString(struct_def.bytesize) + ");\n";
@@ -517,7 +547,7 @@
}
std::string GenerateNewExpression(const std::string &object_name) {
- return "new " + EscapeKeyword(object_name) + "()";
+ return "new " + namer_.Type(object_name) + "()";
}
void GenerateRootAccessor(StructDef &struct_def, std::string *code_ptr,
@@ -563,16 +593,6 @@
}
}
- static std::string GetObjApiClassName(const StructDef &sd,
- const IDLOptions &opts) {
- return GetObjApiClassName(sd.name, opts);
- }
-
- static std::string GetObjApiClassName(const std::string &name,
- const IDLOptions &opts) {
- return opts.object_prefix + name + opts.object_suffix;
- }
-
bool UnionHasStringType(const EnumDef &union_enum) {
return std::any_of(union_enum.Vals().begin(), union_enum.Vals().end(),
[](const EnumVal *ev) {
@@ -601,7 +621,7 @@
if (IsString(ev.union_type)) {
type = "string"; // no need to wrap string type in namespace
} else if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
- type = AddImport(imports, union_enum, *ev.union_type.struct_def);
+ type = AddImport(imports, union_enum, *ev.union_type.struct_def).name;
} else {
FLATBUFFERS_ASSERT(false);
}
@@ -615,156 +635,140 @@
return ret;
}
- std::string AddImport(import_set &imports, const Definition &dependent,
- const StructDef &dependency) {
- std::string ns;
- const auto &depc_comps = dependency.defined_namespace->components;
- for (auto it = depc_comps.begin(); it != depc_comps.end(); it++) {
- ns += *it;
- }
- std::string unique_name = ns + dependency.name;
- std::string import_name = dependency.name;
- std::string long_import_name;
- if (imports.find(unique_name) != imports.end())
- return imports.find(unique_name)->second.name;
+ static bool CheckIfNameClashes(const import_set &imports,
+ const std::string &name) {
+ // TODO: this would be better as a hashset.
for (auto it = imports.begin(); it != imports.end(); it++) {
- if (it->second.name == import_name) {
- long_import_name = ns + import_name;
- break;
- }
+ if (it->second.name == name) { return true; }
}
-
- if (parser_.opts.ts_flat_file) {
- std::string file = dependency.declaration_file == nullptr
- ? dependency.file
- : dependency.declaration_file->substr(2);
- file = RelativeToRootPath(StripFileName(AbsolutePath(dependent.file)),
- dependency.file).substr(2);
- long_import_name = ns + import_name;
- flat_file_import_declarations_[file][import_name] = long_import_name;
- if (parser_.opts.generate_object_based_api) {
- flat_file_import_declarations_[file][import_name + "T"] = long_import_name + "T";
- }
- }
-
- std::string import_statement;
- std::string export_statement;
- import_statement += "import { ";
- export_statement += "export { ";
- std::string symbols_expression;
- if (long_import_name.empty()) {
- symbols_expression += EscapeKeyword(import_name);
- if (parser_.opts.generate_object_based_api)
- symbols_expression += ", " + import_name + "T";
- } else {
- symbols_expression += EscapeKeyword(dependency.name) + " as " +
- EscapeKeyword(long_import_name);
- if (parser_.opts.generate_object_based_api)
- symbols_expression +=
- ", " + dependency.name + "T as " + long_import_name + "T";
- }
- import_statement += symbols_expression + " } from '";
- export_statement += symbols_expression + " } from '";
- std::string bare_file_path;
- std::string rel_file_path;
- const auto &dep_comps = dependent.defined_namespace->components;
- for (size_t i = 0; i < dep_comps.size(); i++)
- rel_file_path += i == 0 ? ".." : (kPathSeparator + std::string(".."));
- if (dep_comps.size() == 0) rel_file_path += ".";
- for (auto it = depc_comps.begin(); it != depc_comps.end(); it++)
- bare_file_path +=
- kPathSeparator + ConvertCase(*it, Case::kDasher, Case::kUpperCamel);
- bare_file_path +=
- kPathSeparator +
- ConvertCase(dependency.name, Case::kDasher, Case::kUpperCamel);
- rel_file_path += bare_file_path;
- import_statement += rel_file_path + "';";
- export_statement += "." + bare_file_path + "';";
- ImportDefinition import;
- import.name = long_import_name.empty() ? import_name : long_import_name;
- import.bare_file_path = bare_file_path;
- import.rel_file_path = rel_file_path;
- import.import_statement = import_statement;
- import.export_statement = export_statement;
- import.dependency = &dependency;
- import.dependent = &dependent;
- imports.insert(std::make_pair(unique_name, import));
- return import.name;
+ return false;
}
- // TODO: largely (but not identical) duplicated code from above couln't find a
- // good way to refactor
- std::string AddImport(import_set &imports, const Definition &dependent,
- const EnumDef &dependency) {
- std::string ns;
- const auto &depc_comps = dependency.defined_namespace->components;
- for (auto it = depc_comps.begin(); it != depc_comps.end(); it++) {
- ns += *it;
- }
- std::string unique_name = ns + dependency.name;
- std::string import_name = EscapeKeyword(dependency.name);
- std::string long_import_name;
- if (imports.find(unique_name) != imports.end()) {
- return imports.find(unique_name)->second.name;
- }
- for (auto it = imports.begin(); it != imports.end(); it++) {
- if (it->second.name == import_name) {
- long_import_name = ns + import_name;
- break;
+ std::string GenSymbolExpression(const StructDef &struct_def,
+ const bool has_name_clash,
+ const std::string &import_name,
+ const std::string &name,
+ const std::string &object_name) {
+ std::string symbols_expression;
+
+ if (has_name_clash) {
+ // We have a name clash
+ symbols_expression += import_name + " as " + name;
+
+ if (parser_.opts.generate_object_based_api) {
+ symbols_expression += ", " +
+ GetTypeName(struct_def, /*object_api =*/true) +
+ " as " + object_name;
+ }
+ } else {
+ // No name clash, use the provided name
+ symbols_expression += name;
+
+ if (parser_.opts.generate_object_based_api) {
+ symbols_expression += ", " + object_name;
}
}
- if (parser_.opts.ts_flat_file) {
- std::string file = dependency.declaration_file == nullptr
- ? dependency.file
- : dependency.declaration_file->substr(2);
- file = RelativeToRootPath(StripFileName(AbsolutePath(dependent.file)),
- dependency.file).substr(2);
- long_import_name = ns + import_name;
- flat_file_import_declarations_[file][import_name] = long_import_name;
+ return symbols_expression;
+ }
+
+ std::string GenSymbolExpression(const EnumDef &enum_def,
+ const bool has_name_clash,
+ const std::string &import_name,
+ const std::string &name,
+ const std::string &) {
+ std::string symbols_expression;
+ if (has_name_clash) {
+ symbols_expression += import_name + " as " + name;
+ } else {
+ symbols_expression += name;
}
- std::string import_statement;
- std::string export_statement;
- import_statement += "import { ";
- export_statement += "export { ";
- std::string symbols_expression;
- if (long_import_name.empty())
- symbols_expression += import_name;
- else
- symbols_expression += EscapeKeyword(dependency.name) + " as " +
- EscapeKeyword(long_import_name);
- if (dependency.is_union) {
- symbols_expression += ", unionTo" + import_name;
- symbols_expression += ", unionListTo" + import_name;
+ if (enum_def.is_union) {
+ symbols_expression += ", unionTo" + name;
+ symbols_expression += ", unionListTo" + name;
}
- import_statement += symbols_expression + " } from '";
- export_statement += symbols_expression + " } from '";
+
+ return symbols_expression;
+ }
+
+ template<typename DefinitionT>
+ ImportDefinition AddImport(import_set &imports, const Definition &dependent,
+ const DefinitionT &dependency) {
+ // The unique name of the dependency, fully qualified in its namespace.
+ const std::string unique_name = GetTypeName(
+ dependency, /*object_api = */ false, /*force_ns_wrap=*/true);
+
+ // Look if we have already added this import and return its name if found.
+ const auto import_pair = imports.find(unique_name);
+ if (import_pair != imports.end()) { return import_pair->second; }
+
+ // Check if this name would have a name clash with another type. Just use
+ // the "base" name (properly escaped) without any namespacing applied.
+ const std::string import_name = GetTypeName(dependency);
+ const bool has_name_clash = CheckIfNameClashes(imports, import_name);
+
+ // If we have a name clash, use the unique name, otherwise use simple name.
+ std::string name = has_name_clash ? unique_name : import_name;
+
+ const std::string object_name =
+ GetTypeName(dependency, /*object_api=*/true, has_name_clash);
+
+ if (parser_.opts.ts_flat_file) {
+ // In flat-file generation, do not attempt to import things from ourselves
+ // *and* do not wrap namespaces (note that this does override the logic
+ // above, but since we force all non-self-imports to use namespace-based
+ // names in flat file generation, it's fine).
+ if (dependent.file == dependency.file) {
+ name = import_name;
+ } else {
+ const std::string file =
+ RelativeToRootPath(StripFileName(AbsolutePath(dependent.file)),
+ dependency.file)
+ // Strip the leading //
+ .substr(2);
+ flat_file_import_declarations_[file][import_name] = name;
+
+ if (parser_.opts.generate_object_based_api &&
+ SupportsObjectAPI<DefinitionT>::value) {
+ flat_file_import_declarations_[file][import_name + "T"] = object_name;
+ }
+ }
+ }
+
+ const std::string symbols_expression = GenSymbolExpression(
+ dependency, has_name_clash, import_name, name, object_name);
+
std::string bare_file_path;
std::string rel_file_path;
const auto &dep_comps = dependent.defined_namespace->components;
- for (size_t i = 0; i < dep_comps.size(); i++)
+ for (size_t i = 0; i < dep_comps.size(); i++) {
rel_file_path += i == 0 ? ".." : (kPathSeparator + std::string(".."));
- if (dep_comps.size() == 0) rel_file_path += ".";
- for (auto it = depc_comps.begin(); it != depc_comps.end(); it++)
- bare_file_path +=
- kPathSeparator + ConvertCase(*it, Case::kDasher, Case::kUpperCamel);
+ }
+ if (dep_comps.size() == 0) { rel_file_path += "."; }
+
bare_file_path +=
kPathSeparator +
- ConvertCase(dependency.name, Case::kDasher, Case::kUpperCamel);
+ namer_.Directories(dependency.defined_namespace->components,
+ SkipDir::OutputPath) +
+ namer_.File(dependency, SkipFile::SuffixAndExtension);
rel_file_path += bare_file_path;
- import_statement += rel_file_path + "';";
- export_statement += "." + bare_file_path + "';";
+
ImportDefinition import;
- import.name = long_import_name.empty() ? import_name : long_import_name;
+ import.name = name;
+ import.object_name = object_name;
import.bare_file_path = bare_file_path;
import.rel_file_path = rel_file_path;
- import.import_statement = import_statement;
- import.export_statement = export_statement;
+ import.import_statement =
+ "import { " + symbols_expression + " } from '" + rel_file_path + ".js';";
+ import.export_statement =
+ "export { " + symbols_expression + " } from '." + bare_file_path + ".js';";
import.dependency = &dependency;
import.dependent = &dependent;
+
imports.insert(std::make_pair(unique_name, import));
- return import.name;
+
+ return import;
}
void AddImport(import_set &imports, std::string import_name,
@@ -777,7 +781,9 @@
}
// Generate a TS union type based on a union's enum
- std::string GenObjApiUnionTypeTS(import_set &imports, const IDLOptions &opts,
+ std::string GenObjApiUnionTypeTS(import_set &imports,
+ const StructDef &dependent,
+ const IDLOptions &,
const EnumDef &union_enum) {
std::string ret = "";
std::set<std::string> type_list;
@@ -791,8 +797,8 @@
if (IsString(ev.union_type)) {
type = "string"; // no need to wrap string type in namespace
} else if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
- type = GetObjApiClassName(
- AddImport(imports, union_enum, *ev.union_type.struct_def), opts);
+ type = AddImport(imports, dependent, *ev.union_type.struct_def)
+ .object_name;
} else {
FLATBUFFERS_ASSERT(false);
}
@@ -809,11 +815,11 @@
}
std::string GenUnionConvFuncName(const EnumDef &enum_def) {
- return "unionTo" + enum_def.name;
+ return namer_.Function("unionTo", enum_def);
}
std::string GenUnionListConvFuncName(const EnumDef &enum_def) {
- return "unionListTo" + enum_def.name;
+ return namer_.Function("unionListTo", enum_def);
}
std::string GenUnionConvFunc(const Type &union_type, import_set &imports) {
@@ -824,12 +830,12 @@
const auto valid_union_type_with_null = valid_union_type + "|null";
auto ret = "\n\nexport function " + GenUnionConvFuncName(enum_def) +
- "(\n type: " + enum_def.name +
+ "(\n type: " + GetTypeName(enum_def) +
",\n accessor: (obj:" + valid_union_type + ") => " +
valid_union_type_with_null +
"\n): " + valid_union_type_with_null + " {\n";
- const auto enum_type = AddImport(imports, enum_def, enum_def);
+ const auto enum_type = AddImport(imports, enum_def, enum_def).name;
const auto union_enum_loop = [&](const std::string &accessor_str) {
ret += " switch(" + enum_type + "[type]) {\n";
@@ -840,13 +846,13 @@
const auto &ev = **it;
if (ev.IsZero()) { continue; }
- ret += " case '" + ev.name + "': ";
+ ret += " case '" + namer_.Variant(ev) + "': ";
if (IsString(ev.union_type)) {
ret += "return " + accessor_str + "'') as string;";
} else if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
const auto type =
- AddImport(imports, enum_def, *ev.union_type.struct_def);
+ AddImport(imports, enum_def, *ev.union_type.struct_def).name;
ret += "return " + accessor_str + "new " + type + "())! as " +
type + ";";
} else {
@@ -863,7 +869,7 @@
ret += "}";
ret += "\n\nexport function " + GenUnionListConvFuncName(enum_def) +
- "(\n type: " + enum_def.name +
+ "(\n type: " + GetTypeName(enum_def) +
", \n accessor: (index: number, obj:" + valid_union_type +
") => " + valid_union_type_with_null +
", \n index: number\n): " + valid_union_type_with_null + " {\n";
@@ -879,12 +885,13 @@
// Used for generating a short function that returns the correct class
// based on union enum type. Assume the context is inside the non object api
// type
- std::string GenUnionValTS(import_set &imports, const std::string &field_name,
+ std::string GenUnionValTS(import_set &imports, const StructDef &dependent,
+ const std::string &field_name,
const Type &union_type,
const bool is_array = false) {
if (union_type.enum_def) {
const auto &enum_def = *union_type.enum_def;
- const auto enum_type = AddImport(imports, enum_def, enum_def);
+ const auto enum_type = AddImport(imports, dependent, enum_def).name;
const std::string union_accessor = "this." + field_name;
const auto union_has_string = UnionHasStringType(enum_def);
@@ -894,11 +901,11 @@
if (!is_array) {
const auto conversion_function = GenUnionConvFuncName(enum_def);
- const auto target_enum = "this." + field_name + "Type()";
ret = "(() => {\n";
- ret += " let temp = " + conversion_function + "(" + target_enum +
- ", " + field_binded_method + ");\n";
+ ret += " let temp = " + conversion_function + "(this." +
+ namer_.Method(field_name, "Type") + "(), " +
+ field_binded_method + ");\n";
ret += " if(temp === null) { return null; }\n";
ret += union_has_string
? " if(typeof temp === 'string') { return temp; }\n"
@@ -907,17 +914,15 @@
ret += " })()";
} else {
const auto conversion_function = GenUnionListConvFuncName(enum_def);
- const auto target_enum_accesor = "this." + field_name + "Type";
- const auto target_enum_length = target_enum_accesor + "Length()";
ret = "(() => {\n";
ret += " let ret = [];\n";
- ret += " for(let targetEnumIndex = 0; targetEnumIndex < " +
- target_enum_length +
+ ret += " for(let targetEnumIndex = 0; targetEnumIndex < this." +
+ namer_.Method(field_name, "TypeLength") + "()" +
"; "
"++targetEnumIndex) {\n";
- ret += " let targetEnum = " + target_enum_accesor +
- "(targetEnumIndex);\n";
+ ret += " let targetEnum = this." +
+ namer_.Method(field_name, "Type") + "(targetEnumIndex);\n";
ret += " if(targetEnum === null || " + enum_type +
"[targetEnum!] === 'NONE') { "
"continue; }\n\n";
@@ -956,15 +961,20 @@
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
- const auto curr_member_accessor =
- prefix + "." + ConvertCase(field.name, Case::kLowerCamel);
+ auto curr_member_accessor = prefix + "." + namer_.Method(field);
+ if (prefix != "this") {
+ curr_member_accessor = prefix + "?." + namer_.Method(field);
+ }
if (IsStruct(field.value.type)) {
ret += GenStructMemberValueTS(*field.value.type.struct_def,
curr_member_accessor, delimiter);
} else {
if (nullCheck) {
- ret +=
- "(" + prefix + " === null ? 0 : " + curr_member_accessor + "!)";
+ std::string nullValue = "0";
+ if (field.value.type.base_type == BASE_TYPE_BOOL) {
+ nullValue = "false";
+ }
+ ret += "(" + curr_member_accessor + " ?? " + nullValue + ")";
} else {
ret += curr_member_accessor;
}
@@ -979,7 +989,7 @@
void GenObjApi(const Parser &parser, StructDef &struct_def,
std::string &obj_api_unpack_func, std::string &obj_api_class,
import_set &imports) {
- const auto class_name = GetObjApiClassName(struct_def, parser.opts);
+ const auto class_name = GetTypeName(struct_def, /*object_api=*/true);
std::string unpack_func = "\nunpack(): " + class_name +
" {\n return new " + class_name + "(" +
@@ -999,8 +1009,7 @@
std::string pack_func_offset_decl;
std::string pack_func_create_call;
- const auto struct_name =
- EscapeKeyword(AddImport(imports, struct_def, struct_def));
+ const auto struct_name = AddImport(imports, struct_def, struct_def).name;
if (has_create) {
pack_func_create_call = " return " + struct_name + ".create" +
@@ -1023,10 +1032,10 @@
auto &field = **it;
if (field.deprecated) continue;
- const auto field_name = ConvertCase(field.name, Case::kLowerCamel);
- const auto field_name_escaped = EscapeKeyword(field_name);
+ const auto field_method = namer_.Method(field);
+ const auto field_field = namer_.Field(field);
const std::string field_binded_method =
- "this." + field_name + ".bind(this)";
+ "this." + field_method + ".bind(this)";
std::string field_val;
std::string field_type;
@@ -1046,14 +1055,14 @@
field_type += GenTypeName(imports, field, field.value.type, false,
has_null_default);
- field_val = "this." + field_name + "()";
+ field_val = "this." + namer_.Method(field) + "()";
if (field.value.type.base_type != BASE_TYPE_STRING) {
- field_offset_val = "this." + field_name_escaped;
+ field_offset_val = "this." + namer_.Field(field);
} else {
field_offset_decl = GenNullCheckConditional(
- "this." + field_name_escaped,
- "builder.createString(this." + field_name_escaped + "!)", "0");
+ "this." + namer_.Field(field),
+ "builder.createString(this." + field_field + "!)", "0");
}
}
@@ -1063,17 +1072,15 @@
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
const auto &sd = *field.value.type.struct_def;
- field_type += GetObjApiClassName(AddImport(imports, struct_def, sd),
- parser.opts);
+ field_type += AddImport(imports, struct_def, sd).object_name;
const std::string field_accessor =
- "this." + field_name_escaped + "()";
+ "this." + namer_.Method(field) + "()";
field_val = GenNullCheckConditional(field_accessor,
field_accessor + "!.unpack()");
auto packing = GenNullCheckConditional(
- "this." + field_name_escaped,
- "this." + field_name_escaped + "!.pack(builder)",
- "0");
+ "this." + field_field,
+ "this." + field_field + "!.pack(builder)", "0");
if (sd.fixed) {
field_offset_val = std::move(packing);
@@ -1095,28 +1102,25 @@
switch (vectortype.base_type) {
case BASE_TYPE_STRUCT: {
const auto &sd = *field.value.type.struct_def;
- field_type += GetObjApiClassName(sd, parser.opts);
+ field_type += GetTypeName(sd, /*object_api=*/true);
+ ;
field_type += ")[]";
field_val = GenBBAccess() + ".createObjList(" +
- field_binded_method + ", this." + field_name +
- "Length())";
+ field_binded_method + ", this." +
+ namer_.Method(field, "Length") + "())";
if (sd.fixed) {
field_offset_decl =
- "builder.createStructOffsetList(this." +
- field_name_escaped + ", " +
- EscapeKeyword(
- AddImport(imports, struct_def, struct_def)) +
- ".start" + ConvertCase(field_name, Case::kUpperCamel) +
- "Vector)";
+ "builder.createStructOffsetList(this." + field_field +
+ ", " + AddImport(imports, struct_def, struct_def).name +
+ "." + namer_.Method("start", field, "Vector") + ")";
} else {
field_offset_decl =
- EscapeKeyword(
- AddImport(imports, struct_def, struct_def)) +
- ".create" + ConvertCase(field_name, Case::kUpperCamel) +
- "Vector(builder, builder.createObjectOffsetList(" +
- "this." + field_name_escaped + "))";
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ field_field + "))";
}
break;
@@ -1125,28 +1129,28 @@
case BASE_TYPE_STRING: {
field_type += "string)[]";
field_val = GenBBAccess() + ".createScalarList(" +
- field_binded_method + ", this." + field_name +
- "Length())";
+ field_binded_method + ", this." +
+ namer_.Field(field, "Length") + "())";
field_offset_decl =
- EscapeKeyword(AddImport(imports, struct_def, struct_def)) +
- ".create" + ConvertCase(field_name, Case::kUpperCamel) +
- "Vector(builder, builder.createObjectOffsetList(" +
- "this." + field_name_escaped + "))";
+ 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, parser.opts,
- *(vectortype.enum_def));
+ field_type += GenObjApiUnionTypeTS(
+ imports, struct_def, parser.opts, *(vectortype.enum_def));
field_type += ")[]";
- field_val =
- GenUnionValTS(imports, field_name, vectortype, true);
+ field_val = GenUnionValTS(imports, struct_def, field_method,
+ vectortype, true);
field_offset_decl =
- EscapeKeyword(AddImport(imports, struct_def, struct_def)) +
- ".create" + ConvertCase(field_name, Case::kUpperCamel) +
- "Vector(builder, builder.createObjectOffsetList(" +
- "this." + field_name_escaped + "))";
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ namer_.Field(field) + "))";
break;
}
@@ -1159,13 +1163,13 @@
}
field_type += ")[]";
field_val = GenBBAccess() + ".createScalarList(" +
- field_binded_method + ", this." + field_name +
- "Length())";
+ field_binded_method + ", this." +
+ namer_.Method(field, "Length") + "())";
field_offset_decl =
- EscapeKeyword(AddImport(imports, struct_def, struct_def)) +
- ".create" + ConvertCase(field_name, Case::kUpperCamel) +
- "Vector(builder, this." + field_name_escaped + ")";
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, this." + field_field + ")";
break;
}
@@ -1175,12 +1179,13 @@
}
case BASE_TYPE_UNION: {
- field_type += GenObjApiUnionTypeTS(imports, parser.opts,
+ field_type += GenObjApiUnionTypeTS(imports, struct_def, parser.opts,
*(field.value.type.enum_def));
- field_val = GenUnionValTS(imports, field_name, field.value.type);
+ field_val = GenUnionValTS(imports, struct_def, field_method,
+ field.value.type);
field_offset_decl =
- "builder.createObjectOffset(this." + field_name_escaped + ")";
+ "builder.createObjectOffset(this." + field_field + ")";
break;
}
@@ -1193,18 +1198,17 @@
if (!field_offset_decl.empty()) {
field_offset_decl =
- " const " + field_name_escaped + " = " + field_offset_decl + ";";
+ " const " + field_field + " = " + field_offset_decl + ";";
}
- if (field_offset_val.empty()) { field_offset_val = field_name_escaped; }
+ if (field_offset_val.empty()) { field_offset_val = field_field; }
unpack_func += " " + field_val;
- unpack_to_func += " _o." + field_name_escaped + " = " + field_val + ";";
+ unpack_to_func += " _o." + field_field + " = " + field_val + ";";
- // FIXME: if field_type and field_name_escaped are identical, then
+ // FIXME: if field_type and field_field are identical, then
// this generates invalid typescript.
- constructor_func += " public " + field_name_escaped + ": " + field_type +
- " = " +
- field_default_val;
+ constructor_func += " public " + field_field + ": " + field_type +
+ " = " + field_default_val;
if (!struct_def.fixed) {
if (!field_offset_decl.empty()) {
@@ -1215,11 +1219,12 @@
pack_func_create_call += field_offset_val;
} else {
if (field.IsScalarOptional()) {
- pack_func_create_call += " if (" + field_offset_val + " !== null)\n ";
+ pack_func_create_call +=
+ " if (" + field_offset_val + " !== null)\n ";
}
- pack_func_create_call += " " + struct_name + ".add" +
- ConvertCase(field.name, Case::kUpperCamel) +
- "(builder, " + field_offset_val + ");\n";
+ pack_func_create_call += " " + struct_name + "." +
+ namer_.Method("add", field) + "(builder, " +
+ field_offset_val + ");\n";
}
}
@@ -1252,10 +1257,10 @@
pack_func_create_call += "return " + struct_name + ".end" +
GetPrefixedName(struct_def) + "(builder);";
}
-
- obj_api_class = "\nexport class " +
- GetObjApiClassName(struct_def, parser.opts) + " {\n";
-
+ obj_api_class = "\n";
+ obj_api_class += "export class ";
+ obj_api_class += GetTypeName(struct_def, /*object_api=*/true);
+ obj_api_class += " {\n";
obj_api_class += constructor_func;
obj_api_class += pack_func_prototype + pack_func_offset_decl +
pack_func_create_call + "\n}";
@@ -1286,13 +1291,18 @@
if (struct_def.generated) return;
std::string &code = *code_ptr;
- std::string object_name;
- std::string object_namespace = GetNameSpace(struct_def);
+ // Special case for the root struct, since no one will necessarily reference
+ // it, we have to explicitly add it to the import list.
+ if (&struct_def == parser_.root_struct_def_) {
+ AddImport(imports, struct_def, struct_def);
+ }
+
+ const std::string object_name = GetTypeName(struct_def);
// Emit constructor
- object_name = EscapeKeyword(struct_def.name);
GenDocComment(struct_def.doc_comment, code_ptr);
- code += "export class " + object_name;
+ code += "export class ";
+ code += object_name;
code += " {\n";
code += " bb: flatbuffers.ByteBuffer|null = null;\n";
code += " bb_pos = 0;\n";
@@ -1300,7 +1310,7 @@
// Generate the __init method that sets the field in a pre-existing
// accessor object. This is to allow object reuse.
code +=
- "__init(i:number, bb:flatbuffers.ByteBuffer):" + object_name + " {\n";
+ " __init(i:number, bb:flatbuffers.ByteBuffer):" + object_name + " {\n";
code += " this.bb_pos = i;\n";
code += " this.bb = bb;\n";
code += " return this;\n";
@@ -1337,7 +1347,7 @@
const auto has_null_default = is_string || HasNullDefault(field);
GenDocComment(field.doc_comment, code_ptr);
- std::string prefix = ConvertCase(field.name, Case::kLowerCamel) + "(";
+ std::string prefix = namer_.Method(field) + "(";
if (is_string) {
code += prefix + "):string|null\n";
code +=
@@ -1380,10 +1390,11 @@
else {
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
- const auto type = EscapeKeyword(
- AddImport(imports, struct_def, *field.value.type.struct_def));
+ const auto type =
+ AddImport(imports, struct_def, *field.value.type.struct_def)
+ .name;
GenDocComment(field.doc_comment, code_ptr);
- code += ConvertCase(field.name, Case::kLowerCamel);
+ code += namer_.Method(field);
code += "(obj?:" + type + "):" + type + "|null {\n";
if (struct_def.fixed) {
@@ -1423,7 +1434,7 @@
default: ret_type = vectortypename;
}
GenDocComment(field.doc_comment, code_ptr);
- std::string prefix = ConvertCase(field.name, Case::kLowerCamel);
+ std::string prefix = namer_.Method(field);
// TODO: make it work without any
// if (is_union) { prefix += "<T extends flatbuffers.Table>"; }
if (is_union) { prefix += ""; }
@@ -1483,7 +1494,7 @@
case BASE_TYPE_UNION: {
GenDocComment(field.doc_comment, code_ptr);
- code += ConvertCase(field.name, Case::kLowerCamel);
+ code += namer_.Method(field);
const auto &union_enum = *(field.value.type.enum_def);
const auto union_type = GenUnionGenericTypeTS(union_enum);
@@ -1508,12 +1519,15 @@
std::string type =
GenTypeName(imports, struct_def, field.value.type, true);
- code += "mutate_" + field.name + "(value:" + type + "):boolean {\n";
+ code += namer_.LegacyTsMutateMethod(field) + "(value:" + type +
+ "):boolean {\n";
+
+ const std::string write_method =
+ "." + namer_.Method("write", GenType(field.value.type));
if (struct_def.fixed) {
- code += " " + GenBBAccess() + ".write" +
- ConvertCase(GenType(field.value.type), Case::kUpperCamel) +
- "(this.bb_pos + " + NumToString(field.value.offset) + ", ";
+ code += " " + GenBBAccess() + write_method + "(this.bb_pos + " +
+ NumToString(field.value.offset) + ", ";
} else {
code += " const offset = " + GenBBAccess() +
".__offset(this.bb_pos, " + NumToString(field.value.offset) +
@@ -1523,9 +1537,8 @@
code += " }\n\n";
// special case for bools, which are treated as uint8
- code += " " + GenBBAccess() + ".write" +
- ConvertCase(GenType(field.value.type), Case::kUpperCamel) +
- "(this.bb_pos + offset, ";
+ code +=
+ " " + GenBBAccess() + write_method + "(this.bb_pos + offset, ";
if (field.value.type.base_type == BASE_TYPE_BOOL) { code += "+"; }
}
@@ -1538,8 +1551,8 @@
if (IsVector(field.value.type)) {
// Emit a length helper
GenDocComment(code_ptr);
- code += ConvertCase(field.name, Case::kLowerCamel);
- code += "Length():number {\n" + offset_prefix;
+ code += namer_.Method(field, "Length");
+ code += "():number {\n" + offset_prefix;
code +=
GenBBAccess() + ".__vector_len(this.bb_pos + offset) : 0;\n}\n\n";
@@ -1549,9 +1562,9 @@
if (IsScalar(vectorType.base_type) && !IsLong(vectorType.base_type)) {
GenDocComment(code_ptr);
- code += ConvertCase(field.name, Case::kLowerCamel);
- code += "Array():" + GenType(vectorType) + "Array|null {\n" +
- offset_prefix;
+ code += namer_.Method(field, "Array");
+ code +=
+ "():" + GenType(vectorType) + "Array|null {\n" + offset_prefix;
code += "new " + GenType(vectorType) + "Array(" + GenBBAccess() +
".bytes().buffer, " + GenBBAccess() +
@@ -1610,7 +1623,7 @@
// Generate the field insertion method
GenDocComment(code_ptr);
- code += "static add" + ConvertCase(field.name, Case::kUpperCamel);
+ code += "static " + namer_.Method("add", field);
code += "(builder:flatbuffers.Builder, " + argname + ":" +
GetArgType(imports, struct_def, field, false) + ") {\n";
code += " builder.addField" + GenWriteMethod(field.value.type) + "(";
@@ -1641,8 +1654,8 @@
GenDocComment(code_ptr);
const std::string sig_begin =
- "static create" + ConvertCase(field.name, Case::kUpperCamel) +
- "Vector(builder:flatbuffers.Builder, data:";
+ "static " + namer_.Method("create", field, "Vector") +
+ "(builder:flatbuffers.Builder, data:";
const std::string sig_end = "):flatbuffers.Offset";
std::string type =
GenTypeName(imports, struct_def, vector_type, true) + "[]";
@@ -1679,8 +1692,9 @@
// after
GenDocComment(code_ptr);
- code += "static start" + ConvertCase(field.name, Case::kUpperCamel);
- code += "Vector(builder:flatbuffers.Builder, numElems:number) {\n";
+ code += "static ";
+ code += namer_.Method("start", field, "Vector");
+ code += "(builder:flatbuffers.Builder, numElems:number) {\n";
code += " builder.startVector(" + NumToString(elem_size);
code += ", numElems, " + NumToString(alignment) + ");\n";
code += "}\n\n";
@@ -1723,8 +1737,8 @@
}
code += "):flatbuffers.Offset {\n";
- code += " " + object_name + ".start" +
- GetPrefixedName(struct_def) + "(builder);\n";
+ code += " " + object_name + ".start" + GetPrefixedName(struct_def) +
+ "(builder);\n";
std::string methodPrefix = object_name;
for (auto it = struct_def.fields.vec.begin();
@@ -1738,8 +1752,7 @@
code += " if (" + arg_name + " !== null)\n ";
}
- code += " " + methodPrefix + ".add" +
- ConvertCase(field.name, Case::kUpperCamel) + "(";
+ code += " " + methodPrefix + "." + namer_.Method("add", field) + "(";
code += "builder, " + arg_name + ");\n";
}
@@ -1757,10 +1770,9 @@
code += "}\n";
code += "\n";
- code += "static deserialize(buffer: Uint8Array):" + EscapeKeyword(name) +
- " {\n";
- code += " return " +
- EscapeKeyword(AddImport(imports, struct_def, struct_def)) +
+ code += "static deserialize(buffer: Uint8Array):" +
+ namer_.EscapeKeyword(name) + " {\n";
+ code += " return " + AddImport(imports, struct_def, struct_def).name +
".getRootAs" + name + "(new flatbuffers.ByteBuffer(buffer))\n";
code += "}\n";
}
@@ -1788,12 +1800,8 @@
}
std::string GetArgName(const FieldDef &field) {
- auto argname = ConvertCase(field.name, Case::kLowerCamel);
- if (!IsScalar(field.value.type.base_type)) {
- argname += "Offset";
- } else {
- argname = EscapeKeyword(argname);
- }
+ auto argname = namer_.Variable(field);
+ if (!IsScalar(field.value.type.base_type)) { argname += "Offset"; }
return argname;
}