From a4cb1599d8f7386d673d2594ab844d6b3b7cd52d Mon Sep 17 00:00:00 2001 From: Casper Date: Mon, 28 Mar 2022 18:07:09 -0400 Subject: [PATCH] Namerdart (#7187) * Apply Namer to Dart. - Also refactor idl_gen_dart a bit - to use more const and references - out parameters should be the last argument * Add keyword test * minor fixes * fix merge * extra 's' * move dart keyord into dart dir * Address comments * Use $ for escaping keywords * Outparameters for namespace_map * Escape dollar in toString * Escape dollar in toString2 * Use UpperCamelCase for types and variants * try to fix ToString * namer Type fixes * Remove path prefixing in imports * gen code Co-authored-by: Casper Neo --- dart/test/flat_buffers_test.dart | 1 + .../keyword_test_keyword_test_generated.dart | 280 +++++++++ include/flatbuffers/util.h | 2 + scripts/generate_code.py | 1 + src/idl_gen_dart.cpp | 535 ++++++++---------- src/util.cpp | 22 + tests/KeywordTest/KeywordsInTable.cs | 18 +- tests/keyword_test.fbs | 1 + .../keywords_in_table_generated.rs | 20 + tests/monster_extra_my_game_generated.dart | 4 +- ...onster_test_my_game.example_generated.dart | 40 +- tests/test.cpp | 8 + 12 files changed, 600 insertions(+), 332 deletions(-) create mode 100644 dart/test/keyword_test_keyword_test_generated.dart diff --git a/dart/test/flat_buffers_test.dart b/dart/test/flat_buffers_test.dart index 04875a0bc..792073660 100644 --- a/dart/test/flat_buffers_test.dart +++ b/dart/test/flat_buffers_test.dart @@ -14,6 +14,7 @@ import 'package:test_reflective_loader/test_reflective_loader.dart'; import './monster_test_my_game.example_generated.dart' as example; import './monster_test_my_game.example2_generated.dart' as example2; import './list_of_enums_generated.dart' as example3; +import './keyword_test_keyword_test_generated.dart' as keyword_test; main() { defineReflectiveSuite(() { diff --git a/dart/test/keyword_test_keyword_test_generated.dart b/dart/test/keyword_test_keyword_test_generated.dart new file mode 100644 index 000000000..6cfc2337c --- /dev/null +++ b/dart/test/keyword_test_keyword_test_generated.dart @@ -0,0 +1,280 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable + +library keyword_test; + +import 'dart:typed_data' show Uint8List; +import 'package:flat_buffers/flat_buffers.dart' as fb; + + +class Abc { + final int value; + const Abc._(this.value); + + factory Abc.fromValue(int value) { + final result = values[value]; + if (result == null) { + throw StateError('Invalid value $value for bit flag enum Abc'); + } + return result; + } + + static Abc? _createOrNull(int? value) => + value == null ? null : Abc.fromValue(value); + + static const int minValue = 0; + static const int maxValue = 2; + static bool containsValue(int value) => values.containsKey(value); + + static const Abc $void = Abc._(0); + static const Abc where = Abc._(1); + static const Abc stackalloc = Abc._(2); + static const Map values = { + 0: $void, + 1: where, + 2: stackalloc}; + + static const fb.Reader reader = _AbcReader(); + + @override + String toString() { + return 'Abc{value: $value}'; + } +} + +class _AbcReader extends fb.Reader { + const _AbcReader(); + + @override + int get size => 4; + + @override + Abc read(fb.BufferContext bc, int offset) => + Abc.fromValue(const fb.Int32Reader().read(bc, offset)); +} + +class Public { + final int value; + const Public._(this.value); + + factory Public.fromValue(int value) { + final result = values[value]; + if (result == null) { + throw StateError('Invalid value $value for bit flag enum Public'); + } + return result; + } + + static Public? _createOrNull(int? value) => + value == null ? null : Public.fromValue(value); + + static const int minValue = 0; + static const int maxValue = 0; + static bool containsValue(int value) => values.containsKey(value); + + static const Public NONE = Public._(0); + static const Map values = { + 0: NONE}; + + static const fb.Reader reader = _PublicReader(); + + @override + String toString() { + return 'Public{value: $value}'; + } +} + +class _PublicReader extends fb.Reader { + const _PublicReader(); + + @override + int get size => 4; + + @override + Public read(fb.BufferContext bc, int offset) => + Public.fromValue(const fb.Int32Reader().read(bc, offset)); +} + +class KeywordsInUnionTypeId { + final int value; + const KeywordsInUnionTypeId._(this.value); + + factory KeywordsInUnionTypeId.fromValue(int value) { + final result = values[value]; + if (result == null) { + throw StateError('Invalid value $value for bit flag enum KeywordsInUnionTypeId'); + } + return result; + } + + static KeywordsInUnionTypeId? _createOrNull(int? value) => + value == null ? null : KeywordsInUnionTypeId.fromValue(value); + + static const int minValue = 0; + static const int maxValue = 2; + static bool containsValue(int value) => values.containsKey(value); + + static const KeywordsInUnionTypeId NONE = KeywordsInUnionTypeId._(0); + static const KeywordsInUnionTypeId $static = KeywordsInUnionTypeId._(1); + static const KeywordsInUnionTypeId internal = KeywordsInUnionTypeId._(2); + static const Map values = { + 0: NONE, + 1: $static, + 2: internal}; + + static const fb.Reader reader = _KeywordsInUnionTypeIdReader(); + + @override + String toString() { + return 'KeywordsInUnionTypeId{value: $value}'; + } +} + +class _KeywordsInUnionTypeIdReader extends fb.Reader { + const _KeywordsInUnionTypeIdReader(); + + @override + int get size => 1; + + @override + KeywordsInUnionTypeId read(fb.BufferContext bc, int offset) => + KeywordsInUnionTypeId.fromValue(const fb.Uint8Reader().read(bc, offset)); +} + +class KeywordsInTable { + KeywordsInTable._(this._bc, this._bcOffset); + factory KeywordsInTable(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _KeywordsInTableReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + Abc get $is => Abc.fromValue(const fb.Int32Reader().vTableGet(_bc, _bcOffset, 4, 0)); + Public get private => Public.fromValue(const fb.Int32Reader().vTableGet(_bc, _bcOffset, 6, 0)); + int get type => const fb.Int32Reader().vTableGet(_bc, _bcOffset, 8, 0); + bool get $default => const fb.BoolReader().vTableGet(_bc, _bcOffset, 10, false); + + @override + String toString() { + return 'KeywordsInTable{\$is: ${$is}, private: ${private}, type: ${type}, \$default: ${$default}}'; + } + + KeywordsInTableT unpack() => KeywordsInTableT( + $is: $is, + private: private, + type: type, + $default: $default); + + static int pack(fb.Builder fbBuilder, KeywordsInTableT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class KeywordsInTableT implements fb.Packable { + Abc $is; + Public private; + int type; + bool $default; + + KeywordsInTableT({ + this.$is = Abc.$void, + this.private = Public.NONE, + this.type = 0, + this.$default = false}); + + @override + int pack(fb.Builder fbBuilder) { + fbBuilder.startTable(4); + fbBuilder.addInt32(0, $is.value); + fbBuilder.addInt32(1, private.value); + fbBuilder.addInt32(2, type); + fbBuilder.addBool(3, $default); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'KeywordsInTableT{\$is: ${$is}, private: ${private}, type: ${type}, \$default: ${$default}}'; + } +} + +class _KeywordsInTableReader extends fb.TableReader { + const _KeywordsInTableReader(); + + @override + KeywordsInTable createObject(fb.BufferContext bc, int offset) => + KeywordsInTable._(bc, offset); +} + +class KeywordsInTableBuilder { + KeywordsInTableBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(4); + } + + int addIs(Abc? $is) { + fbBuilder.addInt32(0, $is?.value); + return fbBuilder.offset; + } + int addPrivate(Public? private) { + fbBuilder.addInt32(1, private?.value); + return fbBuilder.offset; + } + int addType(int? type) { + fbBuilder.addInt32(2, type); + return fbBuilder.offset; + } + int addDefault(bool? $default) { + fbBuilder.addBool(3, $default); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class KeywordsInTableObjectBuilder extends fb.ObjectBuilder { + final Abc? _$is; + final Public? _private; + final int? _type; + final bool? _$default; + + KeywordsInTableObjectBuilder({ + Abc? $is, + Public? private, + int? type, + bool? $default, + }) + : _$is = $is, + _private = private, + _type = type, + _$default = $default; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + fbBuilder.startTable(4); + fbBuilder.addInt32(0, _$is?.value); + fbBuilder.addInt32(1, _private?.value); + fbBuilder.addInt32(2, _type); + fbBuilder.addBool(3, _$default); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} diff --git a/include/flatbuffers/util.h b/include/flatbuffers/util.h index 2e0ce737b..40cfaacea 100644 --- a/include/flatbuffers/util.h +++ b/include/flatbuffers/util.h @@ -703,6 +703,8 @@ enum class Case { kDasher = 7, // THEQuiCKBr_ownFox (or whatever you want, we won't change it) kKeep = 8, + // the_quick_brown_fox123 (as opposed to the_quick_brown_fox_123) + kSnake2 = 9, }; // Convert the `input` string of case `input_case` to the specified `output_case`. diff --git a/scripts/generate_code.py b/scripts/generate_code.py index fcf87cdcc..2cc7715a9 100755 --- a/scripts/generate_code.py +++ b/scripts/generate_code.py @@ -363,6 +363,7 @@ flatc( prefix="nested_namespace_test", schema=glob(tests_path, "nested_namespace_test/nested_namespace_test*.fbs"), ) +flatc(BASE_OPTS + DART_OPTS, prefix="../dart/test/", schema="keyword_test.fbs") # Swift Tests swift_prefix = "FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests" diff --git a/src/idl_gen_dart.cpp b/src/idl_gen_dart.cpp index 3b8660bfd..dcf52228c 100644 --- a/src/idl_gen_dart.cpp +++ b/src/idl_gen_dart.cpp @@ -21,26 +21,54 @@ #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" #include "flatbuffers/util.h" +#include "idl_namer.h" namespace flatbuffers { namespace dart { +Namer::Config DartDefaultConfig() { + return { /*types=*/Case::kUpperCamel, + /*constants=*/Case::kScreamingSnake, + /*methods=*/Case::kLowerCamel, + /*functions=*/Case::kUnknown, // unused. + /*fields=*/Case::kLowerCamel, + /*variables=*/Case::kLowerCamel, + /*variants=*/Case::kKeep, + /*enum_variant_seperator=*/".", + /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase, + /*namespaces=*/Case::kSnake2, + /*namespace_seperator=*/".", + /*object_prefix=*/"", + /*object_suffix=*/"T", + /*keyword_prefix=*/"$", + /*keyword_suffix=*/"", + /*filenames=*/Case::kKeep, + /*directories=*/Case::kKeep, + /*output_path=*/"", + /*filename_suffix=*/"_generated", + /*filename_extension=*/".dart" }; +} + +std::set DartKeywords() { + // see https://www.dartlang.org/guides/language/language-tour#keywords + // yield*, async*, and sync* shouldn't be proble + return { + "abstract", "else", "import", "show", "as", "enum", + "in", "static", "assert", "export", "interface", "super", + "async", "extends", "is", "switch", "await", "extension", + "late", "sync", "break", "external", "library", "this", + "case", "factory", "mixin", "throw", "catch", "false", + "new", "true", "class", "final", "null", "try", + "const", "finally", "on", "typedef", "continue", "for", + "operator", "var", "covariant", "Function", "part", "void", + "default", "get", "required", "while", "deferred", "hide", + "rethrow", "with", "do", "if", "return", "yield", + "dynamic", "implements", "set", + }; +} + const std::string _kFb = "fb"; -// see https://www.dartlang.org/guides/language/language-tour#keywords -// yeild*, async*, and sync* shouldn't be problems anyway but keeping them in -static const char *keywords[] = { - "abstract", "deferred", "if", "super", "as", "do", - "implements", "switch", "assert", "dynamic", "import", "sync*", - "async", "else", "in", "this", "async*", "enum", - "is", "throw", "await", "export", "library", "true", - "break", "external", "new", "try", "case", "extends", - "null", "typedef", "catch", "factory", "operator", "var", - "class", "false", "part", "void", "const", "final", - "rethrow", "while", "continue", "finally", "return", "with", - "covariant", "for", "set", "yield", "default", "get", - "static", "yield*" -}; // Iterate through all definitions we haven't generate code for (enums, structs, // and tables) and output them to a single file. @@ -50,14 +78,16 @@ class DartGenerator : public BaseGenerator { DartGenerator(const Parser &parser, const std::string &path, const std::string &file_name) - : BaseGenerator(parser, path, file_name, "", ".", "dart") {} + : BaseGenerator(parser, path, file_name, "", ".", "dart"), + namer_(WithFlagOptions(DartDefaultConfig(), parser.opts, path), + DartKeywords()) {} // Iterate through all definitions we haven't generate code for (enums, // structs, and tables) and output them to a single file. bool generate() { std::string code; namespace_code_map namespace_code; - GenerateEnums(&namespace_code); - GenerateStructs(&namespace_code); + GenerateEnums(namespace_code); + GenerateStructs(namespace_code); for (auto kv = namespace_code.begin(); kv != namespace_code.end(); ++kv) { code.clear(); @@ -75,31 +105,23 @@ class DartGenerator : public BaseGenerator { for (auto kv2 = namespace_code.begin(); kv2 != namespace_code.end(); ++kv2) { if (kv2->first != kv->first) { - code += - "import '" + - GeneratedFileName( - "./", - file_name_ + (!kv2->first.empty() ? "_" + kv2->first : ""), - parser_.opts) + - "' as " + ImportAliasName(kv2->first) + ";\n"; + code += "import './" + Filename(kv2->first, /*path=*/false) + + "' as " + ImportAliasName(kv2->first) + ";\n"; } } code += "\n"; code += kv->second; - if (!SaveFile( - GeneratedFileName( - path_, - file_name_ + (!kv->first.empty() ? "_" + kv->first : ""), - parser_.opts) - .c_str(), - code, false)) { - return false; - } + if (!SaveFile(Filename(kv->first).c_str(), code, false)) { return false; } } return true; } + std::string Filename(const std::string &suffix, bool path = true) const { + return (path ? path_ : "") + + namer_.File(file_name_ + (suffix.empty() ? "" : "_" + suffix)); + } + private: static std::string ImportAliasName(const std::string &ns) { std::string ret; @@ -113,64 +135,15 @@ class DartGenerator : public BaseGenerator { return ret; } - static std::string BuildNamespaceName(const Namespace &ns) { - if (ns.components.empty()) { return ""; } - std::stringstream sstream; - std::copy(ns.components.begin(), ns.components.end() - 1, - std::ostream_iterator(sstream, ".")); - - auto ret = sstream.str() + ns.components.back(); - for (size_t i = 0; i < ret.size(); i++) { - auto lower = CharToLower(ret[i]); - if (lower != ret[i]) { - ret[i] = lower; - if (i != 0 && ret[i - 1] != '.') { - ret.insert(i, "_"); - i++; - } - } - } - // std::transform(ret.begin(), ret.end(), ret.begin(), CharToLower); - return ret; - } - - void GenIncludeDependencies(std::string *code, - const std::string &the_namespace) { - for (auto it = parser_.included_files_.begin(); - it != parser_.included_files_.end(); ++it) { - if (it->second.empty()) continue; - - auto noext = flatbuffers::StripExtension(it->second); - auto basename = flatbuffers::StripPath(noext); - - *code += - "import '" + - GeneratedFileName( - "", basename + (the_namespace == "" ? "" : "_" + the_namespace), - parser_.opts) + - "';\n"; - } - } - - static std::string EscapeKeyword(const std::string &name) { - for (size_t i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) { - if (name == keywords[i]) { - return ConvertCase(name + "_", Case::kLowerCamel); - } - } - - return ConvertCase(name, Case::kLowerCamel); - } - - void GenerateEnums(namespace_code_map *namespace_code) { + void GenerateEnums(namespace_code_map &namespace_code) { for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); ++it) { auto &enum_def = **it; - GenEnum(enum_def, namespace_code); // enum_code_ptr); + GenEnum(enum_def, namespace_code); } } - void GenerateStructs(namespace_code_map *namespace_code) { + void GenerateStructs(namespace_code_map &namespace_code) { for (auto it = parser_.structs_.vec.begin(); it != parser_.structs_.vec.end(); ++it) { auto &struct_def = **it; @@ -180,80 +153,50 @@ class DartGenerator : public BaseGenerator { // Generate a documentation comment, if available. static void GenDocComment(const std::vector &dc, - std::string *code_ptr, - const std::string &extra_lines, - const char *indent = nullptr) { - if (dc.empty() && extra_lines.empty()) { - // Don't output empty comment blocks with 0 lines of comment content. - return; - } - - auto &code = *code_ptr; - + const char *indent, std::string &code) { for (auto it = dc.begin(); it != dc.end(); ++it) { if (indent) code += indent; code += "/// " + *it + "\n"; } - if (!extra_lines.empty()) { - if (!dc.empty()) { - if (indent) code += indent; - code += "///\n"; - } - if (indent) code += indent; - std::string::size_type start = 0; - for (;;) { - auto end = extra_lines.find('\n', start); - if (end != std::string::npos) { - code += "/// " + extra_lines.substr(start, end - start) + "\n"; - start = end + 1; - } else { - code += "/// " + extra_lines.substr(start) + "\n"; - break; - } - } - } - } - - static void GenDocComment(std::string *code_ptr, - const std::string &extra_lines) { - GenDocComment(std::vector(), code_ptr, extra_lines); } // Generate an enum declaration and an enum string lookup table. - void GenEnum(EnumDef &enum_def, namespace_code_map *namespace_code) { + void GenEnum(EnumDef &enum_def, namespace_code_map &namespace_code) { if (enum_def.generated) return; - auto ns = BuildNamespaceName(*enum_def.defined_namespace); - std::string code; - GenDocComment(enum_def.doc_comment, &code, ""); + std::string &code = + namespace_code[namer_.Namespace(*enum_def.defined_namespace)]; + GenDocComment(enum_def.doc_comment, "", code); - auto name = enum_def.is_union ? enum_def.name + "TypeId" : enum_def.name; + const std::string enum_type = + namer_.Type(enum_def) + (enum_def.is_union ? "TypeId" : ""); 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 += "class " + enum_type + " {\n"; code += " final int value;\n"; - code += " const " + name + "._(this.value);\n\n"; - code += " factory " + name + ".fromValue(int value) {\n"; + code += " const " + enum_type + "._(this.value);\n\n"; + code += " factory " + enum_type + ".fromValue(int value) {\n"; code += " final result = values[value];\n"; code += " if (result == null) {\n"; if (permit_zero) { code += " if (value == 0) {\n"; - code += " return " + name + "._(0);\n"; + code += " return " + enum_type + "._(0);\n"; code += " } else {\n"; } code += " throw StateError('Invalid value $value for bit flag enum "; - code += name + "');\n"; + code += enum_type + "');\n"; if (permit_zero) { code += " }\n"; } code += " }\n"; code += " return result;\n"; code += " }\n\n"; - code += " static " + name + "? _createOrNull(int? value) => \n"; - code += " value == null ? null : " + name + ".fromValue(value);\n\n"; + code += " static " + enum_type + "? _createOrNull(int? value) => \n"; + code += + " value == null ? null : " + enum_type + ".fromValue(value);\n\n"; // this is meaningless for bit_flags // however, note that unlike "regular" dart enums this enum can still have @@ -271,53 +214,52 @@ class DartGenerator : public BaseGenerator { for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { auto &ev = **it; + const auto enum_var = namer_.Variant(ev); if (!ev.doc_comment.empty()) { if (it != enum_def.Vals().begin()) { code += '\n'; } - GenDocComment(ev.doc_comment, &code, "", " "); + GenDocComment(ev.doc_comment, " ", code); } - code += " static const " + name + " " + ev.name + " = " + name + "._(" + - enum_def.ToString(ev) + ");\n"; + code += " static const " + enum_type + " " + enum_var + " = " + + enum_type + "._(" + enum_def.ToString(ev) + ");\n"; } - code += " static const Map values = {\n"; + code += " static const Map values = {\n"; for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { auto &ev = **it; + const auto enum_var = namer_.Variant(ev); if (it != enum_def.Vals().begin()) code += ",\n"; - code += " " + enum_def.ToString(ev) + ": " + ev.name; + code += " " + enum_def.ToString(ev) + ": " + enum_var; } code += "};\n\n"; - code += " static const " + _kFb + ".Reader<" + name + "> reader = _" + - name + "Reader();\n\n"; + code += " static const " + _kFb + ".Reader<" + enum_type + "> reader = _" + + enum_type + "Reader();\n\n"; code += " @override\n"; code += " String toString() {\n"; - code += " return '" + name + "{value: $value}';\n"; + code += " return '" + enum_type + "{value: $value}';\n"; code += " }\n"; code += "}\n\n"; - GenEnumReader(enum_def, name, &code); - (*namespace_code)[ns] += code; + GenEnumReader(enum_def, enum_type, code); } - void GenEnumReader(EnumDef &enum_def, const std::string &name, - std::string *code_ptr) { - auto &code = *code_ptr; - - code += "class _" + name + "Reader extends " + _kFb + ".Reader<" + name + - "> {\n"; - code += " const _" + name + "Reader();\n\n"; + void GenEnumReader(EnumDef &enum_def, const std::string &enum_type, + std::string &code) { + code += "class _" + enum_type + "Reader extends " + _kFb + ".Reader<" + + enum_type + "> {\n"; + code += " const _" + enum_type + "Reader();\n\n"; code += " @override\n"; code += " int get size => " + EnumSize(enum_def.underlying_type) + ";\n\n"; code += " @override\n"; - code += - " " + name + " read(" + _kFb + ".BufferContext bc, int offset) =>\n"; - code += " " + name + ".fromValue(const " + _kFb + "." + + code += " " + enum_type + " read(" + _kFb + + ".BufferContext bc, int offset) =>\n"; + code += " " + enum_type + ".fromValue(const " + _kFb + "." + GenType(enum_def.underlying_type) + "Reader().read(bc, offset));\n"; code += "}\n\n"; } - static std::string GenType(const Type &type) { + std::string GenType(const Type &type) { switch (type.base_type) { case BASE_TYPE_BOOL: return "Bool"; case BASE_TYPE_CHAR: return "Int8"; @@ -333,8 +275,8 @@ class DartGenerator : public BaseGenerator { case BASE_TYPE_DOUBLE: return "Float64"; case BASE_TYPE_STRING: return "String"; case BASE_TYPE_VECTOR: return GenType(type.VectorType()); - case BASE_TYPE_STRUCT: return type.struct_def->name; - case BASE_TYPE_UNION: return type.enum_def->name + "TypeId"; + case BASE_TYPE_STRUCT: return namer_.Type(*type.struct_def); + case BASE_TYPE_UNION: return namer_.Type(*type.enum_def) + "TypeId"; default: return "Table"; } } @@ -396,11 +338,11 @@ class DartGenerator : public BaseGenerator { std::string struct_type_suffix = "") { if (type.enum_def) { if (type.enum_def->is_union && type.base_type != BASE_TYPE_UNION) { - return type.enum_def->name + "TypeId"; + return namer_.Type(*type.enum_def) + "TypeId"; } else if (type.enum_def->is_union) { return "dynamic"; } else if (type.base_type != BASE_TYPE_VECTOR) { - return type.enum_def->name; + return namer_.Type(*type.enum_def); } } @@ -418,8 +360,9 @@ class DartGenerator : public BaseGenerator { case BASE_TYPE_DOUBLE: return "double"; case BASE_TYPE_STRING: return "String"; case BASE_TYPE_STRUCT: - return MaybeWrapNamespace(type.struct_def->name + struct_type_suffix, - current_namespace, def); + return MaybeWrapNamespace( + namer_.Type(*type.struct_def) + struct_type_suffix, + current_namespace, def); case BASE_TYPE_VECTOR: return "List<" + GenDartTypeName(type.VectorType(), current_namespace, def, @@ -438,21 +381,19 @@ class DartGenerator : public BaseGenerator { return typeName; } - static const std::string MaybeWrapNamespace(const std::string &type_name, - Namespace *current_ns, - const FieldDef &field) { - auto curr_ns_str = BuildNamespaceName(*current_ns); - std::string field_ns_str = ""; - if (field.value.type.struct_def) { - field_ns_str += - BuildNamespaceName(*field.value.type.struct_def->defined_namespace); - } else if (field.value.type.enum_def) { - field_ns_str += - BuildNamespaceName(*field.value.type.enum_def->defined_namespace); - } + std::string MaybeWrapNamespace(const std::string &type_name, + Namespace *current_ns, + const FieldDef &field) const { + const std::string current_namespace = namer_.Namespace(*current_ns); + const std::string field_namespace = + field.value.type.struct_def + ? namer_.Namespace(*field.value.type.struct_def->defined_namespace) + : field.value.type.enum_def + ? namer_.Namespace(*field.value.type.enum_def->defined_namespace) + : ""; - if (field_ns_str != "" && field_ns_str != curr_ns_str) { - return ImportAliasName(field_ns_str) + "." + type_name; + if (field_namespace != "" && field_namespace != current_namespace) { + return ImportAliasName(field_namespace) + "." + type_name; } else { return type_name; } @@ -460,29 +401,29 @@ class DartGenerator : public BaseGenerator { // Generate an accessor struct with constructor for a flatbuffers struct. void GenStruct(const StructDef &struct_def, - namespace_code_map *namespace_code) { + namespace_code_map &namespace_code) { if (struct_def.generated) return; - auto object_namespace = BuildNamespaceName(*struct_def.defined_namespace); - std::string code; + std::string &code = + namespace_code[namer_.Namespace(*struct_def.defined_namespace)]; - const auto &object_name = struct_def.name; + const auto &struct_type = namer_.Type(struct_def); // Emit constructor - GenDocComment(struct_def.doc_comment, &code, ""); + GenDocComment(struct_def.doc_comment, "", code); - auto reader_name = "_" + object_name + "Reader"; - auto builder_name = object_name + "Builder"; - auto object_builder_name = object_name + "ObjectBuilder"; + auto reader_name = "_" + struct_type + "Reader"; + auto builder_name = struct_type + "Builder"; + auto object_builder_name = struct_type + "ObjectBuilder"; std::string reader_code, builder_code; - code += "class " + object_name + " {\n"; + code += "class " + struct_type + " {\n"; - code += " " + object_name + "._(this._bc, this._bcOffset);\n"; + code += " " + struct_type + "._(this._bc, this._bcOffset);\n"; if (!struct_def.fixed) { - code += " factory " + object_name + "(List bytes) {\n"; + code += " factory " + struct_type + "(List bytes) {\n"; code += " final rootRef = " + _kFb + ".BufferContext.fromBytes(bytes);\n"; code += " return reader.read(rootRef, 0);\n"; @@ -490,7 +431,7 @@ class DartGenerator : public BaseGenerator { } code += "\n"; - code += " static const " + _kFb + ".Reader<" + object_name + + code += " static const " + _kFb + ".Reader<" + struct_type + "> reader = " + reader_name + "();\n\n"; code += " final " + _kFb + ".BufferContext _bc;\n"; @@ -499,20 +440,20 @@ class DartGenerator : public BaseGenerator { std::vector> non_deprecated_fields; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { - auto &field = **it; + FieldDef &field = **it; if (field.deprecated) continue; auto offset = static_cast(it - struct_def.fields.vec.begin()); non_deprecated_fields.push_back(std::make_pair(offset, &field)); } - GenImplementationGetters(struct_def, non_deprecated_fields, &code); + GenImplementationGetters(struct_def, non_deprecated_fields, code); if (parser_.opts.generate_object_based_api) { code += "\n" + GenStructObjectAPIUnpack(struct_def, non_deprecated_fields); - code += "\n static int pack(fb.Builder fbBuilder, " + struct_def.name + - "T? object) {\n"; + code += "\n static int pack(fb.Builder fbBuilder, " + + namer_.ObjectType(struct_def) + "? object) {\n"; code += " if (object == null) return 0;\n"; code += " return object.pack(fbBuilder);\n"; code += " }\n"; @@ -524,15 +465,13 @@ class DartGenerator : public BaseGenerator { code += GenStructObjectAPI(struct_def, non_deprecated_fields); } - GenReader(struct_def, &reader_name, &reader_code); - GenBuilder(struct_def, non_deprecated_fields, &builder_name, &builder_code); - GenObjectBuilder(struct_def, non_deprecated_fields, &object_builder_name, - &builder_code); + GenReader(struct_def, reader_name, reader_code); + GenBuilder(struct_def, non_deprecated_fields, builder_name, builder_code); + GenObjectBuilder(struct_def, non_deprecated_fields, object_builder_name, + builder_code); code += reader_code; code += builder_code; - - (*namespace_code)[object_namespace] += code; } // Generate an accessor struct with constructor for a flatbuffers struct. @@ -540,23 +479,23 @@ class DartGenerator : public BaseGenerator { const StructDef &struct_def, const std::vector> &non_deprecated_fields) { std::string code; - GenDocComment(struct_def.doc_comment, &code, ""); + GenDocComment(struct_def.doc_comment, "", code); - std::string class_name = struct_def.name + "T"; - code += "class " + class_name + " implements " + _kFb + ".Packable {\n"; + std::string object_type = namer_.ObjectType(struct_def); + code += "class " + object_type + " implements " + _kFb + ".Packable {\n"; std::string constructor_args; for (auto it = non_deprecated_fields.begin(); it != non_deprecated_fields.end(); ++it) { const FieldDef &field = *it->second; - std::string field_name = ConvertCase(field.name, Case::kLowerCamel); - std::string defaultValue = getDefaultValue(field.value); - std::string type_name = + const std::string field_name = namer_.Field(field); + const std::string defaultValue = getDefaultValue(field.value); + const std::string type_name = GenDartTypeName(field.value.type, struct_def.defined_namespace, field, defaultValue.empty() && !struct_def.fixed, "T"); - GenDocComment(field.doc_comment, &code, "", " "); + GenDocComment(field.doc_comment, " ", code); code += " " + type_name + " " + field_name + ";\n"; if (!constructor_args.empty()) constructor_args += ",\n"; @@ -567,10 +506,10 @@ class DartGenerator : public BaseGenerator { if (IsEnum(field.value.type)) { auto &enum_def = *field.value.type.enum_def; if (auto val = enum_def.FindByValue(defaultValue)) { - constructor_args += " = " + enum_def.name + "." + val->name; + constructor_args += " = " + namer_.EnumVariant(enum_def, *val); } else { - constructor_args += - " = const " + enum_def.name + "._(" + defaultValue + ")"; + constructor_args += " = const " + namer_.Type(enum_def) + "._(" + + defaultValue + ")"; } } else { constructor_args += " = " + defaultValue; @@ -579,12 +518,12 @@ class DartGenerator : public BaseGenerator { } if (!constructor_args.empty()) { - code += "\n " + class_name + "({\n" + constructor_args + "});\n\n"; + code += "\n " + object_type + "({\n" + constructor_args + "});\n\n"; } code += GenStructObjectAPIPack(struct_def, non_deprecated_fields); code += "\n"; - code += GenToString(class_name, non_deprecated_fields); + code += GenToString(object_type, non_deprecated_fields); code += "}\n\n"; return code; @@ -599,7 +538,7 @@ class DartGenerator : public BaseGenerator { it != non_deprecated_fields.end(); ++it) { const FieldDef &field = *it->second; - std::string field_name = ConvertCase(field.name, Case::kLowerCamel); + const std::string field_name = namer_.Field(field); if (!constructor_args.empty()) constructor_args += ",\n"; constructor_args += " " + field_name + ": "; @@ -630,8 +569,8 @@ class DartGenerator : public BaseGenerator { } } - std::string class_name = struct_def.name + "T"; - std::string code = " " + class_name + " unpack() => " + class_name + "("; + const std::string object_type = namer_.ObjectType(struct_def); + std::string code = " " + object_type + " unpack() => " + object_type + "("; if (!constructor_args.empty()) code += "\n" + constructor_args; code += ");\n"; return code; @@ -658,7 +597,7 @@ class DartGenerator : public BaseGenerator { if (std::equal(root_namespace->components.begin(), root_namespace->components.end(), qualified_name_parts.begin())) { - return type.struct_def->name; + return namer_.Type(*type.struct_def); } std::string ns; @@ -678,39 +617,35 @@ class DartGenerator : public BaseGenerator { if (it != qualified_name_parts.end() - 1) { ns += "_"; } } - return ns + "." + type.struct_def->name; + return ns + "." + namer_.Type(*type.struct_def); } void GenImplementationGetters( const StructDef &struct_def, - std::vector> non_deprecated_fields, - std::string *code_ptr) { - auto &code = *code_ptr; - + const std::vector> &non_deprecated_fields, + std::string &code) { for (auto it = non_deprecated_fields.begin(); it != non_deprecated_fields.end(); ++it) { - auto pair = *it; - auto &field = *pair.second; + const FieldDef &field = *it->second; - std::string field_name = ConvertCase(field.name, Case::kLowerCamel); - std::string defaultValue = getDefaultValue(field.value); - bool isNullable = defaultValue.empty() && !struct_def.fixed; - std::string type_name = + const std::string field_name = namer_.Field(field); + const std::string defaultValue = getDefaultValue(field.value); + const bool isNullable = defaultValue.empty() && !struct_def.fixed; + const std::string type_name = GenDartTypeName(field.value.type, struct_def.defined_namespace, field, isNullable, ""); - GenDocComment(field.doc_comment, &code, "", " "); + GenDocComment(field.doc_comment, " ", code); code += " " + type_name + " get " + field_name; if (field.value.type.base_type == BASE_TYPE_UNION) { code += " {\n"; code += " switch (" + field_name + "Type?.value) {\n"; - auto &enum_def = *field.value.type.enum_def; + const auto &enum_def = *field.value.type.enum_def; for (auto en_it = enum_def.Vals().begin() + 1; en_it != enum_def.Vals().end(); ++en_it) { - auto &ev = **en_it; - - auto enum_name = NamespaceAliasFromUnionType( + const auto &ev = **en_it; + const auto enum_name = NamespaceAliasFromUnionType( enum_def.defined_namespace, ev.union_type); code += " case " + enum_def.ToString(ev) + ": return " + enum_name + ".reader.vTableGetNullable(_bc, _bcOffset, " + @@ -751,7 +686,7 @@ class DartGenerator : public BaseGenerator { } code += "\n"; - code += GenToString(struct_def.name, non_deprecated_fields); + code += GenToString(namer_.Type(struct_def), non_deprecated_fields); } std::string GenToString( @@ -763,10 +698,15 @@ class DartGenerator : public BaseGenerator { code += " return '" + object_name + "{"; for (auto it = non_deprecated_fields.begin(); it != non_deprecated_fields.end(); ++it) { - auto pair = *it; - auto &field = *pair.second; - code += ConvertCase(field.name, Case::kLowerCamel) + ": $" + - ConvertCase(field.name, Case::kLowerCamel); + const std::string field = namer_.Field(*it->second); + // We need to escape the fact that some fields have $ in the name which is + // also used in symbol/string substitution. + std::string escaped_field; + for (size_t i = 0; i < field.size(); i++) { + if (field[i] == '$') escaped_field.push_back('\\'); + escaped_field.push_back(field[i]); + } + code += escaped_field + ": ${" + field + "}"; if (it != non_deprecated_fields.end() - 1) { code += ", "; } } code += "}';\n"; @@ -797,11 +737,9 @@ class DartGenerator : public BaseGenerator { } } - void GenReader(const StructDef &struct_def, std::string *reader_name_ptr, - std::string *code_ptr) { - auto &code = *code_ptr; - auto &reader_name = *reader_name_ptr; - auto &impl_name = struct_def.name; + void GenReader(const StructDef &struct_def, const std::string &reader_name, + std::string &code) { + const auto struct_type = namer_.Type(struct_def); code += "class " + reader_name + " extends " + _kFb; if (struct_def.fixed) { @@ -809,7 +747,7 @@ class DartGenerator : public BaseGenerator { } else { code += ".TableReader<"; } - code += impl_name + "> {\n"; + code += struct_type + "> {\n"; code += " const " + reader_name + "();\n\n"; if (struct_def.fixed) { @@ -817,27 +755,26 @@ class DartGenerator : public BaseGenerator { code += " int get size => " + NumToString(struct_def.bytesize) + ";\n\n"; } code += " @override\n"; - code += " " + impl_name + + code += " " + struct_type + " createObject(fb.BufferContext bc, int offset) => \n " + - impl_name + "._(bc, offset);\n"; + struct_type + "._(bc, offset);\n"; code += "}\n\n"; } - void GenBuilder(const StructDef &struct_def, - std::vector> non_deprecated_fields, - std::string *builder_name_ptr, std::string *code_ptr) { + void GenBuilder( + const StructDef &struct_def, + const std::vector> &non_deprecated_fields, + const std::string &builder_name, std::string &code) { if (non_deprecated_fields.size() == 0) { return; } - auto &code = *code_ptr; - auto &builder_name = *builder_name_ptr; code += "class " + builder_name + " {\n"; code += " " + builder_name + "(this.fbBuilder);\n\n"; code += " final " + _kFb + ".Builder fbBuilder;\n\n"; if (struct_def.fixed) { - StructBuilderBody(struct_def, non_deprecated_fields, code_ptr); + StructBuilderBody(struct_def, non_deprecated_fields, code); } else { - TableBuilderBody(struct_def, non_deprecated_fields, code_ptr); + TableBuilderBody(struct_def, non_deprecated_fields, code); } code += "}\n\n"; @@ -845,15 +782,13 @@ class DartGenerator : public BaseGenerator { void StructBuilderBody( const StructDef &struct_def, - std::vector> non_deprecated_fields, - std::string *code_ptr) { - auto &code = *code_ptr; - + const std::vector> &non_deprecated_fields, + std::string &code) { code += " int finish("; for (auto it = non_deprecated_fields.begin(); it != non_deprecated_fields.end(); ++it) { - auto pair = *it; - auto &field = *pair.second; + const FieldDef &field = *it->second; + const std::string field_name = namer_.Field(field); if (IsStruct(field.value.type)) { code += "fb.StructBuilder"; @@ -861,25 +796,25 @@ class DartGenerator : public BaseGenerator { code += GenDartTypeName(field.value.type, struct_def.defined_namespace, field); } - code += " " + field.name; + code += " " + field_name; if (it != non_deprecated_fields.end() - 1) { code += ", "; } } code += ") {\n"; for (auto it = non_deprecated_fields.rbegin(); it != non_deprecated_fields.rend(); ++it) { - auto pair = *it; - auto &field = *pair.second; + const FieldDef &field = *it->second; + const std::string field_name = namer_.Field(field); if (field.padding) { code += " fbBuilder.pad(" + NumToString(field.padding) + ");\n"; } if (IsStruct(field.value.type)) { - code += " " + field.name + "();\n"; + code += " " + field_name + "();\n"; } else { code += " fbBuilder.put" + GenType(field.value.type) + "("; - code += field.name; + code += field_name; if (field.value.type.enum_def) { code += ".value"; } code += ");\n"; } @@ -890,10 +825,8 @@ class DartGenerator : public BaseGenerator { void TableBuilderBody( const StructDef &struct_def, - std::vector> non_deprecated_fields, - std::string *code_ptr) { - auto &code = *code_ptr; - + const std::vector> &non_deprecated_fields, + std::string &code) { code += " void begin() {\n"; code += " fbBuilder.startTable(" + NumToString(struct_def.fields.vec.size()) + ");\n"; @@ -901,28 +834,27 @@ class DartGenerator : public BaseGenerator { for (auto it = non_deprecated_fields.begin(); it != non_deprecated_fields.end(); ++it) { - auto pair = *it; - auto &field = *pair.second; - auto offset = pair.first; + const auto &field = *it->second; + const auto offset = it->first; + const std::string add_field = namer_.Method("add_" + field.name); + const std::string field_var = namer_.Variable(field); if (IsScalar(field.value.type.base_type)) { - code += " int add" + ConvertCase(field.name, Case::kUpperCamel) + "("; + code += " int " + add_field + "("; code += GenDartTypeName(field.value.type, struct_def.defined_namespace, field); - code += "? " + ConvertCase(field.name, Case::kLowerCamel) + ") {\n"; + code += "? " + field_var + ") {\n"; code += " fbBuilder.add" + GenType(field.value.type) + "(" + NumToString(offset) + ", "; - code += ConvertCase(field.name, Case::kLowerCamel); + code += field_var; if (field.value.type.enum_def) { code += "?.value"; } code += ");\n"; } else if (IsStruct(field.value.type)) { - code += " int add" + ConvertCase(field.name, Case::kUpperCamel) + - "(int offset) {\n"; + code += " int " + add_field + "(int offset) {\n"; code += " fbBuilder.addStruct(" + NumToString(offset) + ", offset);\n"; } else { - code += " int add" + ConvertCase(field.name, Case::kUpperCamel) + - "Offset(int? offset) {\n"; + code += " int " + add_field + "Offset(int? offset) {\n"; code += " fbBuilder.addOffset(" + NumToString(offset) + ", offset);\n"; } @@ -938,21 +870,17 @@ class DartGenerator : public BaseGenerator { void GenObjectBuilder( const StructDef &struct_def, - std::vector> non_deprecated_fields, - std::string *builder_name_ptr, std::string *code_ptr) { - auto &code = *code_ptr; - auto &builder_name = *builder_name_ptr; - + const std::vector> &non_deprecated_fields, + const std::string &builder_name, std::string &code) { code += "class " + builder_name + " extends " + _kFb + ".ObjectBuilder {\n"; for (auto it = non_deprecated_fields.begin(); it != non_deprecated_fields.end(); ++it) { - auto pair = *it; - auto &field = *pair.second; + const FieldDef &field = *it->second; code += " final " + GenDartTypeName(field.value.type, struct_def.defined_namespace, field, !struct_def.fixed, "ObjectBuilder") + - " _" + ConvertCase(field.name, Case::kLowerCamel) + ";\n"; + " _" + namer_.Variable(field) + ";\n"; } code += "\n"; code += " " + builder_name + "("; @@ -961,24 +889,21 @@ class DartGenerator : public BaseGenerator { code += "{\n"; for (auto it = non_deprecated_fields.begin(); it != non_deprecated_fields.end(); ++it) { - auto pair = *it; - auto &field = *pair.second; + const FieldDef &field = *it->second; code += " "; code += (struct_def.fixed ? "required " : "") + GenDartTypeName(field.value.type, struct_def.defined_namespace, field, !struct_def.fixed, "ObjectBuilder") + - " " + ConvertCase(field.name, Case::kLowerCamel) + ",\n"; + " " + namer_.Variable(field) + ",\n"; } code += " })\n"; code += " : "; for (auto it = non_deprecated_fields.begin(); it != non_deprecated_fields.end(); ++it) { - auto pair = *it; - auto &field = *pair.second; + const FieldDef &field = *it->second; - code += "_" + ConvertCase(field.name, Case::kLowerCamel) + " = " + - ConvertCase(field.name, Case::kLowerCamel); + code += "_" + namer_.Variable(field) + " = " + namer_.Variable(field); if (it == non_deprecated_fields.end() - 1) { code += ";\n\n"; } else { @@ -1018,11 +943,9 @@ class DartGenerator : public BaseGenerator { if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type)) continue; - std::string offset_name = - ConvertCase(field.name, Case::kLowerCamel) + "Offset"; - std::string field_name = (prependUnderscore ? "_" : "") + - ConvertCase(field.name, Case::kLowerCamel); - + std::string offset_name = namer_.Variable(field) + "Offset"; + std::string field_name = + (prependUnderscore ? "_" : "") + namer_.Variable(field); // custom handling for fixed-sized struct in pack() if (pack && IsVector(field.value.type) && field.value.type.VectorType().base_type == BASE_TYPE_STRUCT && @@ -1031,7 +954,7 @@ class DartGenerator : public BaseGenerator { code += " if (" + field_name + " != null) {\n"; code += " for (var e in " + field_name + "!) { e.pack(fbBuilder); }\n"; - code += " " + ConvertCase(field.name, Case::kLowerCamel) + + code += " " + namer_.Variable(field) + "Offset = fbBuilder.endStructVector(" + field_name + "!.length);\n"; code += " }\n"; @@ -1090,8 +1013,8 @@ class DartGenerator : public BaseGenerator { for (auto it = non_deprecated_fields.rbegin(); it != non_deprecated_fields.rend(); ++it) { - auto pair = *it; - auto &field = *pair.second; + const FieldDef &field = *it->second; + const std::string field_name = namer_.Field(field); if (field.padding) { code += " fbBuilder.pad(" + NumToString(field.padding) + ");\n"; @@ -1100,11 +1023,11 @@ class DartGenerator : public BaseGenerator { if (IsStruct(field.value.type)) { code += " "; if (prependUnderscore) { code += "_"; } - code += field.name + (pack ? ".pack" : ".finish") + "(fbBuilder);\n"; + code += field_name + (pack ? ".pack" : ".finish") + "(fbBuilder);\n"; } else { code += " fbBuilder.put" + GenType(field.value.type) + "("; if (prependUnderscore) { code += "_"; } - code += field.name; + code += field_name; if (field.value.type.enum_def) { code += ".value"; } code += ");\n"; } @@ -1124,34 +1047,35 @@ class DartGenerator : public BaseGenerator { for (auto it = non_deprecated_fields.begin(); it != non_deprecated_fields.end(); ++it) { - auto pair = *it; - auto &field = *pair.second; - auto offset = pair.first; + const FieldDef &field = *it->second; + auto offset = it->first; - std::string field_name = (prependUnderscore ? "_" : "") + - ConvertCase(field.name, Case::kLowerCamel); + std::string field_var = + (prependUnderscore ? "_" : "") + namer_.Variable(field); if (IsScalar(field.value.type.base_type)) { code += " fbBuilder.add" + GenType(field.value.type) + "(" + - NumToString(offset) + ", " + field_name; + NumToString(offset) + ", " + field_var; if (field.value.type.enum_def) { bool isNullable = getDefaultValue(field.value).empty(); code += (isNullable || !pack) ? "?.value" : ".value"; } code += ");\n"; } else if (IsStruct(field.value.type)) { - code += " if (" + field_name + " != null) {\n"; + code += " if (" + field_var + " != null) {\n"; code += " fbBuilder.addStruct(" + NumToString(offset) + ", " + - field_name + (pack ? "!.pack" : "!.finish") + "(fbBuilder));\n"; + field_var + (pack ? "!.pack" : "!.finish") + "(fbBuilder));\n"; code += " }\n"; } else { code += " fbBuilder.addOffset(" + NumToString(offset) + ", " + - ConvertCase(field.name, Case::kLowerCamel) + "Offset);\n"; + namer_.Variable(field) + "Offset);\n"; } } code += " return fbBuilder.endTable();\n"; return code; } + + const IdlNamer namer_; }; } // namespace dart @@ -1166,8 +1090,7 @@ std::string DartMakeRule(const Parser &parser, const std::string &path, auto filebase = flatbuffers::StripPath(flatbuffers::StripExtension(file_name)); dart::DartGenerator generator(parser, path, file_name); - auto make_rule = - generator.GeneratedFileName(path, file_name, parser.opts) + ": "; + auto make_rule = generator.Filename("") + ": "; auto included_files = parser.GetIncludedFilesRecursive(file_name); for (auto it = included_files.begin(); it != included_files.end(); ++it) { diff --git a/src/util.cpp b/src/util.cpp index a1ed6c1d5..a2a5deaf5 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -414,6 +414,27 @@ static std::string ToDasher(const std::string &input) { } // namespace +// Converts foo_bar_123baz_456 to foo_bar123_baz456 +static std::string SnakeToSnake2(const std::string &s) { + if (s.length() <= 1) return s; + std::string result; + result.reserve(s.size()); + for (size_t i = 0; i < s.length() - 1; i++) { + if (s[i] == '_' && isdigit(s[i + 1])) { + continue; // Move the `_` until after the digits. + } + + result.push_back(s[i]); + + if (isdigit(s[i]) && isalpha(s[i + 1]) && islower(s[i + 1])) { + result.push_back('_'); + } + } + result.push_back(s.back()); + + return result; +} + std::string ConvertCase(const std::string &input, Case output_case, Case input_case) { if (output_case == Case::kKeep) return input; @@ -440,6 +461,7 @@ std::string ConvertCase(const std::string &input, Case output_case, case Case::kAllUpper: return ToAll(input, CharToUpper); case Case::kAllLower: return ToAll(input, CharToLower); case Case::kDasher: return ToDasher(input); + case Case::kSnake2: return SnakeToSnake2(input); default: case Case::kUnknown: return input; } diff --git a/tests/KeywordTest/KeywordsInTable.cs b/tests/KeywordTest/KeywordsInTable.cs index 495671bdf..6393d49bf 100644 --- a/tests/KeywordTest/KeywordsInTable.cs +++ b/tests/KeywordTest/KeywordsInTable.cs @@ -25,22 +25,27 @@ public struct KeywordsInTable : IFlatbufferObject public bool MutatePrivate(KeywordTest.@public @private) { int o = __p.__offset(6); if (o != 0) { __p.bb.PutInt(o + __p.bb_pos, (int)@private); return true; } else { return false; } } public int Type { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } } public bool MutateType(int type) { int o = __p.__offset(8); if (o != 0) { __p.bb.PutInt(o + __p.bb_pos, type); return true; } else { return false; } } + public bool Default { get { int o = __p.__offset(10); return o != 0 ? 0!=__p.bb.Get(o + __p.bb_pos) : (bool)false; } } + public bool MutateDefault(bool @default) { int o = __p.__offset(10); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (byte)(@default ? 1 : 0)); return true; } else { return false; } } public static Offset CreateKeywordsInTable(FlatBufferBuilder builder, KeywordTest.ABC @is = KeywordTest.ABC.@void, KeywordTest.@public @private = KeywordTest.@public.NONE, - int type = 0) { - builder.StartTable(3); + int type = 0, + bool @default = false) { + builder.StartTable(4); KeywordsInTable.AddType(builder, type); KeywordsInTable.AddPrivate(builder, @private); KeywordsInTable.AddIs(builder, @is); + KeywordsInTable.AddDefault(builder, @default); return KeywordsInTable.EndKeywordsInTable(builder); } - public static void StartKeywordsInTable(FlatBufferBuilder builder) { builder.StartTable(3); } + public static void StartKeywordsInTable(FlatBufferBuilder builder) { builder.StartTable(4); } public static void AddIs(FlatBufferBuilder builder, KeywordTest.ABC @is) { builder.AddInt(0, (int)@is, 0); } public static void AddPrivate(FlatBufferBuilder builder, KeywordTest.@public @private) { builder.AddInt(1, (int)@private, 0); } public static void AddType(FlatBufferBuilder builder, int type) { builder.AddInt(2, type, 0); } + public static void AddDefault(FlatBufferBuilder builder, bool @default) { builder.AddBool(3, @default, false); } public static Offset EndKeywordsInTable(FlatBufferBuilder builder) { int o = builder.EndTable(); return new Offset(o); @@ -54,6 +59,7 @@ public struct KeywordsInTable : IFlatbufferObject _o.Is = this.Is; _o.Private = this.Private; _o.Type = this.Type; + _o.Default = this.Default; } public static Offset Pack(FlatBufferBuilder builder, KeywordsInTableT _o) { if (_o == null) return default(Offset); @@ -61,7 +67,8 @@ public struct KeywordsInTable : IFlatbufferObject builder, _o.Is, _o.Private, - _o.Type); + _o.Type, + _o.Default); } } @@ -73,11 +80,14 @@ public class KeywordsInTableT public KeywordTest.@public Private { get; set; } [Newtonsoft.Json.JsonProperty("type")] public int Type { get; set; } + [Newtonsoft.Json.JsonProperty("default")] + public bool Default { get; set; } public KeywordsInTableT() { this.Is = KeywordTest.ABC.@void; this.Private = KeywordTest.@public.NONE; this.Type = 0; + this.Default = false; } } diff --git a/tests/keyword_test.fbs b/tests/keyword_test.fbs index 4ca761bfc..77fc42bcc 100644 --- a/tests/keyword_test.fbs +++ b/tests/keyword_test.fbs @@ -8,6 +8,7 @@ table KeywordsInTable { is: ABC = void; private: public; type: int; + default: bool = false; } union KeywordsInUnion { diff --git a/tests/keyword_test/keyword_test/keywords_in_table_generated.rs b/tests/keyword_test/keyword_test/keywords_in_table_generated.rs index 6a16f056c..0790048d3 100644 --- a/tests/keyword_test/keyword_test/keywords_in_table_generated.rs +++ b/tests/keyword_test/keyword_test/keywords_in_table_generated.rs @@ -23,6 +23,7 @@ impl<'a> KeywordsInTable<'a> { pub const VT_IS: flatbuffers::VOffsetT = 4; pub const VT_PRIVATE: flatbuffers::VOffsetT = 6; pub const VT_TYPE_: flatbuffers::VOffsetT = 8; + pub const VT_DEFAULT: flatbuffers::VOffsetT = 10; pub const fn get_fully_qualified_name() -> &'static str { "KeywordTest.KeywordsInTable" @@ -41,6 +42,7 @@ impl<'a> KeywordsInTable<'a> { builder.add_type_(args.type_); builder.add_private(args.private); builder.add_is(args.is); + builder.add_default(args.default); builder.finish() } @@ -48,10 +50,12 @@ impl<'a> KeywordsInTable<'a> { let is = self.is(); let private = self.private(); let type_ = self.type_(); + let default = self.default(); KeywordsInTableT { is, private, type_, + default, } } @@ -67,6 +71,10 @@ impl<'a> KeywordsInTable<'a> { pub fn type_(&self) -> i32 { self._tab.get::(KeywordsInTable::VT_TYPE_, Some(0)).unwrap() } + #[inline] + pub fn default(&self) -> bool { + self._tab.get::(KeywordsInTable::VT_DEFAULT, Some(false)).unwrap() + } } impl flatbuffers::Verifiable for KeywordsInTable<'_> { @@ -79,6 +87,7 @@ impl flatbuffers::Verifiable for KeywordsInTable<'_> { .visit_field::("is", Self::VT_IS, false)? .visit_field::("private", Self::VT_PRIVATE, false)? .visit_field::("type_", Self::VT_TYPE_, false)? + .visit_field::("default", Self::VT_DEFAULT, false)? .finish(); Ok(()) } @@ -87,6 +96,7 @@ pub struct KeywordsInTableArgs { pub is: ABC, pub private: public, pub type_: i32, + pub default: bool, } impl<'a> Default for KeywordsInTableArgs { #[inline] @@ -95,6 +105,7 @@ impl<'a> Default for KeywordsInTableArgs { is: ABC::void, private: public::NONE, type_: 0, + default: false, } } } @@ -117,6 +128,10 @@ impl<'a: 'b, 'b> KeywordsInTableBuilder<'a, 'b> { self.fbb_.push_slot::(KeywordsInTable::VT_TYPE_, type_, 0); } #[inline] + pub fn add_default(&mut self, default: bool) { + self.fbb_.push_slot::(KeywordsInTable::VT_DEFAULT, default, false); + } + #[inline] pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> KeywordsInTableBuilder<'a, 'b> { let start = _fbb.start_table(); KeywordsInTableBuilder { @@ -137,6 +152,7 @@ impl std::fmt::Debug for KeywordsInTable<'_> { ds.field("is", &self.is()); ds.field("private", &self.private()); ds.field("type_", &self.type_()); + ds.field("default", &self.default()); ds.finish() } } @@ -146,6 +162,7 @@ pub struct KeywordsInTableT { pub is: ABC, pub private: public, pub type_: i32, + pub default: bool, } impl Default for KeywordsInTableT { fn default() -> Self { @@ -153,6 +170,7 @@ impl Default for KeywordsInTableT { is: ABC::void, private: public::NONE, type_: 0, + default: false, } } } @@ -164,10 +182,12 @@ impl KeywordsInTableT { let is = self.is; let private = self.private; let type_ = self.type_; + let default = self.default; KeywordsInTable::create(_fbb, &KeywordsInTableArgs{ is, private, type_, + default, }) } } diff --git a/tests/monster_extra_my_game_generated.dart b/tests/monster_extra_my_game_generated.dart index 238ab8f28..26310beb3 100644 --- a/tests/monster_extra_my_game_generated.dart +++ b/tests/monster_extra_my_game_generated.dart @@ -32,7 +32,7 @@ class MonsterExtra { @override String toString() { - return 'MonsterExtra{d0: $d0, d1: $d1, d2: $d2, d3: $d3, f0: $f0, f1: $f1, f2: $f2, f3: $f3, dvec: $dvec, fvec: $fvec}'; + return 'MonsterExtra{d0: ${d0}, d1: ${d1}, d2: ${d2}, d3: ${d3}, f0: ${f0}, f1: ${f1}, f2: ${f2}, f3: ${f3}, dvec: ${dvec}, fvec: ${fvec}}'; } MonsterExtraT unpack() => MonsterExtraT( @@ -99,7 +99,7 @@ class MonsterExtraT implements fb.Packable { @override String toString() { - return 'MonsterExtraT{d0: $d0, d1: $d1, d2: $d2, d3: $d3, f0: $f0, f1: $f1, f2: $f2, f3: $f3, dvec: $dvec, fvec: $fvec}'; + return 'MonsterExtraT{d0: ${d0}, d1: ${d1}, d2: ${d2}, d3: ${d3}, f0: ${f0}, f1: ${f1}, f2: ${f2}, f3: ${f3}, dvec: ${dvec}, fvec: ${fvec}}'; } } diff --git a/tests/monster_test_my_game.example_generated.dart b/tests/monster_test_my_game.example_generated.dart index 7f058b75e..174fe1d8d 100644 --- a/tests/monster_test_my_game.example_generated.dart +++ b/tests/monster_test_my_game.example_generated.dart @@ -316,7 +316,7 @@ class Test { @override String toString() { - return 'Test{a: $a, b: $b}'; + return 'Test{a: ${a}, b: ${b}}'; } TestT unpack() => TestT( @@ -347,7 +347,7 @@ class TestT implements fb.Packable { @override String toString() { - return 'TestT{a: $a, b: $b}'; + return 'TestT{a: ${a}, b: ${b}}'; } } @@ -420,7 +420,7 @@ class TestSimpleTableWithEnum { @override String toString() { - return 'TestSimpleTableWithEnum{color: $color}'; + return 'TestSimpleTableWithEnum{color: ${color}}'; } TestSimpleTableWithEnumT unpack() => TestSimpleTableWithEnumT( @@ -447,7 +447,7 @@ class TestSimpleTableWithEnumT implements fb.Packable { @override String toString() { - return 'TestSimpleTableWithEnumT{color: $color}'; + return 'TestSimpleTableWithEnumT{color: ${color}}'; } } @@ -519,7 +519,7 @@ class Vec3 { @override String toString() { - return 'Vec3{x: $x, y: $y, z: $z, test1: $test1, test2: $test2, test3: $test3}'; + return 'Vec3{x: ${x}, y: ${y}, z: ${z}, test1: ${test1}, test2: ${test2}, test3: ${test3}}'; } Vec3T unpack() => Vec3T( @@ -568,7 +568,7 @@ class Vec3T implements fb.Packable { @override String toString() { - return 'Vec3T{x: $x, y: $y, z: $z, test1: $test1, test2: $test2, test3: $test3}'; + return 'Vec3T{x: ${x}, y: ${y}, z: ${z}, test1: ${test1}, test2: ${test2}, test3: ${test3}}'; } } @@ -662,7 +662,7 @@ class Ability { @override String toString() { - return 'Ability{id: $id, distance: $distance}'; + return 'Ability{id: ${id}, distance: ${distance}}'; } AbilityT unpack() => AbilityT( @@ -692,7 +692,7 @@ class AbilityT implements fb.Packable { @override String toString() { - return 'AbilityT{id: $id, distance: $distance}'; + return 'AbilityT{id: ${id}, distance: ${distance}}'; } } @@ -761,7 +761,7 @@ class StructOfStructs { @override String toString() { - return 'StructOfStructs{a: $a, b: $b, c: $c}'; + return 'StructOfStructs{a: ${a}, b: ${b}, c: ${c}}'; } StructOfStructsT unpack() => StructOfStructsT( @@ -795,7 +795,7 @@ class StructOfStructsT implements fb.Packable { @override String toString() { - return 'StructOfStructsT{a: $a, b: $b, c: $c}'; + return 'StructOfStructsT{a: ${a}, b: ${b}, c: ${c}}'; } } @@ -867,7 +867,7 @@ class StructOfStructsOfStructs { @override String toString() { - return 'StructOfStructsOfStructs{a: $a}'; + return 'StructOfStructsOfStructs{a: ${a}}'; } StructOfStructsOfStructsT unpack() => StructOfStructsOfStructsT( @@ -893,7 +893,7 @@ class StructOfStructsOfStructsT implements fb.Packable { @override String toString() { - return 'StructOfStructsOfStructsT{a: $a}'; + return 'StructOfStructsOfStructsT{a: ${a}}'; } } @@ -961,7 +961,7 @@ class Stat { @override String toString() { - return 'Stat{id: $id, val: $val, count: $count}'; + return 'Stat{id: ${id}, val: ${val}, count: ${count}}'; } StatT unpack() => StatT( @@ -998,7 +998,7 @@ class StatT implements fb.Packable { @override String toString() { - return 'StatT{id: $id, val: $val, count: $count}'; + return 'StatT{id: ${id}, val: ${val}, count: ${count}}'; } } @@ -1087,7 +1087,7 @@ class Referrable { @override String toString() { - return 'Referrable{id: $id}'; + return 'Referrable{id: ${id}}'; } ReferrableT unpack() => ReferrableT( @@ -1114,7 +1114,7 @@ class ReferrableT implements fb.Packable { @override String toString() { - return 'ReferrableT{id: $id}'; + return 'ReferrableT{id: ${id}}'; } } @@ -1261,7 +1261,7 @@ class Monster { @override String toString() { - return 'Monster{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, testType: $testType, test: $test, test4: $test4, testarrayofstring: $testarrayofstring, testarrayoftables: $testarrayoftables, enemy: $enemy, testnestedflatbuffer: $testnestedflatbuffer, testempty: $testempty, testbool: $testbool, testhashs32Fnv1: $testhashs32Fnv1, testhashu32Fnv1: $testhashu32Fnv1, testhashs64Fnv1: $testhashs64Fnv1, testhashu64Fnv1: $testhashu64Fnv1, testhashs32Fnv1a: $testhashs32Fnv1a, testhashu32Fnv1a: $testhashu32Fnv1a, testhashs64Fnv1a: $testhashs64Fnv1a, testhashu64Fnv1a: $testhashu64Fnv1a, testarrayofbools: $testarrayofbools, testf: $testf, testf2: $testf2, testf3: $testf3, testarrayofstring2: $testarrayofstring2, testarrayofsortedstruct: $testarrayofsortedstruct, flex: $flex, test5: $test5, vectorOfLongs: $vectorOfLongs, vectorOfDoubles: $vectorOfDoubles, parentNamespaceTest: $parentNamespaceTest, vectorOfReferrables: $vectorOfReferrables, singleWeakReference: $singleWeakReference, vectorOfWeakReferences: $vectorOfWeakReferences, vectorOfStrongReferrables: $vectorOfStrongReferrables, coOwningReference: $coOwningReference, vectorOfCoOwningReferences: $vectorOfCoOwningReferences, nonOwningReference: $nonOwningReference, vectorOfNonOwningReferences: $vectorOfNonOwningReferences, anyUniqueType: $anyUniqueType, anyUnique: $anyUnique, anyAmbiguousType: $anyAmbiguousType, anyAmbiguous: $anyAmbiguous, vectorOfEnums: $vectorOfEnums, signedEnum: $signedEnum, testrequirednestedflatbuffer: $testrequirednestedflatbuffer, scalarKeySortedTables: $scalarKeySortedTables, nativeInline: $nativeInline, longEnumNonEnumDefault: $longEnumNonEnumDefault, longEnumNormalDefault: $longEnumNormalDefault}'; + return 'Monster{pos: ${pos}, mana: ${mana}, hp: ${hp}, name: ${name}, inventory: ${inventory}, color: ${color}, testType: ${testType}, test: ${test}, test4: ${test4}, testarrayofstring: ${testarrayofstring}, testarrayoftables: ${testarrayoftables}, enemy: ${enemy}, testnestedflatbuffer: ${testnestedflatbuffer}, testempty: ${testempty}, testbool: ${testbool}, testhashs32Fnv1: ${testhashs32Fnv1}, testhashu32Fnv1: ${testhashu32Fnv1}, testhashs64Fnv1: ${testhashs64Fnv1}, testhashu64Fnv1: ${testhashu64Fnv1}, testhashs32Fnv1a: ${testhashs32Fnv1a}, testhashu32Fnv1a: ${testhashu32Fnv1a}, testhashs64Fnv1a: ${testhashs64Fnv1a}, testhashu64Fnv1a: ${testhashu64Fnv1a}, testarrayofbools: ${testarrayofbools}, testf: ${testf}, testf2: ${testf2}, testf3: ${testf3}, testarrayofstring2: ${testarrayofstring2}, testarrayofsortedstruct: ${testarrayofsortedstruct}, flex: ${flex}, test5: ${test5}, vectorOfLongs: ${vectorOfLongs}, vectorOfDoubles: ${vectorOfDoubles}, parentNamespaceTest: ${parentNamespaceTest}, vectorOfReferrables: ${vectorOfReferrables}, singleWeakReference: ${singleWeakReference}, vectorOfWeakReferences: ${vectorOfWeakReferences}, vectorOfStrongReferrables: ${vectorOfStrongReferrables}, coOwningReference: ${coOwningReference}, vectorOfCoOwningReferences: ${vectorOfCoOwningReferences}, nonOwningReference: ${nonOwningReference}, vectorOfNonOwningReferences: ${vectorOfNonOwningReferences}, anyUniqueType: ${anyUniqueType}, anyUnique: ${anyUnique}, anyAmbiguousType: ${anyAmbiguousType}, anyAmbiguous: ${anyAmbiguous}, vectorOfEnums: ${vectorOfEnums}, signedEnum: ${signedEnum}, testrequirednestedflatbuffer: ${testrequirednestedflatbuffer}, scalarKeySortedTables: ${scalarKeySortedTables}, nativeInline: ${nativeInline}, longEnumNonEnumDefault: ${longEnumNonEnumDefault}, longEnumNormalDefault: ${longEnumNormalDefault}}'; } MonsterT unpack() => MonsterT( @@ -1560,7 +1560,7 @@ class MonsterT implements fb.Packable { @override String toString() { - return 'MonsterT{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, testType: $testType, test: $test, test4: $test4, testarrayofstring: $testarrayofstring, testarrayoftables: $testarrayoftables, enemy: $enemy, testnestedflatbuffer: $testnestedflatbuffer, testempty: $testempty, testbool: $testbool, testhashs32Fnv1: $testhashs32Fnv1, testhashu32Fnv1: $testhashu32Fnv1, testhashs64Fnv1: $testhashs64Fnv1, testhashu64Fnv1: $testhashu64Fnv1, testhashs32Fnv1a: $testhashs32Fnv1a, testhashu32Fnv1a: $testhashu32Fnv1a, testhashs64Fnv1a: $testhashs64Fnv1a, testhashu64Fnv1a: $testhashu64Fnv1a, testarrayofbools: $testarrayofbools, testf: $testf, testf2: $testf2, testf3: $testf3, testarrayofstring2: $testarrayofstring2, testarrayofsortedstruct: $testarrayofsortedstruct, flex: $flex, test5: $test5, vectorOfLongs: $vectorOfLongs, vectorOfDoubles: $vectorOfDoubles, parentNamespaceTest: $parentNamespaceTest, vectorOfReferrables: $vectorOfReferrables, singleWeakReference: $singleWeakReference, vectorOfWeakReferences: $vectorOfWeakReferences, vectorOfStrongReferrables: $vectorOfStrongReferrables, coOwningReference: $coOwningReference, vectorOfCoOwningReferences: $vectorOfCoOwningReferences, nonOwningReference: $nonOwningReference, vectorOfNonOwningReferences: $vectorOfNonOwningReferences, anyUniqueType: $anyUniqueType, anyUnique: $anyUnique, anyAmbiguousType: $anyAmbiguousType, anyAmbiguous: $anyAmbiguous, vectorOfEnums: $vectorOfEnums, signedEnum: $signedEnum, testrequirednestedflatbuffer: $testrequirednestedflatbuffer, scalarKeySortedTables: $scalarKeySortedTables, nativeInline: $nativeInline, longEnumNonEnumDefault: $longEnumNonEnumDefault, longEnumNormalDefault: $longEnumNormalDefault}'; + return 'MonsterT{pos: ${pos}, mana: ${mana}, hp: ${hp}, name: ${name}, inventory: ${inventory}, color: ${color}, testType: ${testType}, test: ${test}, test4: ${test4}, testarrayofstring: ${testarrayofstring}, testarrayoftables: ${testarrayoftables}, enemy: ${enemy}, testnestedflatbuffer: ${testnestedflatbuffer}, testempty: ${testempty}, testbool: ${testbool}, testhashs32Fnv1: ${testhashs32Fnv1}, testhashu32Fnv1: ${testhashu32Fnv1}, testhashs64Fnv1: ${testhashs64Fnv1}, testhashu64Fnv1: ${testhashu64Fnv1}, testhashs32Fnv1a: ${testhashs32Fnv1a}, testhashu32Fnv1a: ${testhashu32Fnv1a}, testhashs64Fnv1a: ${testhashs64Fnv1a}, testhashu64Fnv1a: ${testhashu64Fnv1a}, testarrayofbools: ${testarrayofbools}, testf: ${testf}, testf2: ${testf2}, testf3: ${testf3}, testarrayofstring2: ${testarrayofstring2}, testarrayofsortedstruct: ${testarrayofsortedstruct}, flex: ${flex}, test5: ${test5}, vectorOfLongs: ${vectorOfLongs}, vectorOfDoubles: ${vectorOfDoubles}, parentNamespaceTest: ${parentNamespaceTest}, vectorOfReferrables: ${vectorOfReferrables}, singleWeakReference: ${singleWeakReference}, vectorOfWeakReferences: ${vectorOfWeakReferences}, vectorOfStrongReferrables: ${vectorOfStrongReferrables}, coOwningReference: ${coOwningReference}, vectorOfCoOwningReferences: ${vectorOfCoOwningReferences}, nonOwningReference: ${nonOwningReference}, vectorOfNonOwningReferences: ${vectorOfNonOwningReferences}, anyUniqueType: ${anyUniqueType}, anyUnique: ${anyUnique}, anyAmbiguousType: ${anyAmbiguousType}, anyAmbiguous: ${anyAmbiguous}, vectorOfEnums: ${vectorOfEnums}, signedEnum: ${signedEnum}, testrequirednestedflatbuffer: ${testrequirednestedflatbuffer}, scalarKeySortedTables: ${scalarKeySortedTables}, nativeInline: ${nativeInline}, longEnumNonEnumDefault: ${longEnumNonEnumDefault}, longEnumNormalDefault: ${longEnumNormalDefault}}'; } } @@ -2110,7 +2110,7 @@ class TypeAliases { @override String toString() { - return 'TypeAliases{i8: $i8, u8: $u8, i16: $i16, u16: $u16, i32: $i32, u32: $u32, i64: $i64, u64: $u64, f32: $f32, f64: $f64, v8: $v8, vf64: $vf64}'; + return 'TypeAliases{i8: ${i8}, u8: ${u8}, i16: ${i16}, u16: ${u16}, i32: ${i32}, u32: ${u32}, i64: ${i64}, u64: ${u64}, f32: ${f32}, f64: ${f64}, v8: ${v8}, vf64: ${vf64}}'; } TypeAliasesT unpack() => TypeAliasesT( @@ -2185,7 +2185,7 @@ class TypeAliasesT implements fb.Packable { @override String toString() { - return 'TypeAliasesT{i8: $i8, u8: $u8, i16: $i16, u16: $u16, i32: $i32, u32: $u32, i64: $i64, u64: $u64, f32: $f32, f64: $f64, v8: $v8, vf64: $vf64}'; + return 'TypeAliasesT{i8: ${i8}, u8: ${u8}, i16: ${i16}, u16: ${u16}, i32: ${i32}, u32: ${u32}, i64: ${i64}, u64: ${u64}, f32: ${f32}, f64: ${f64}, v8: ${v8}, vf64: ${vf64}}'; } } diff --git a/tests/test.cpp b/tests/test.cpp index 756c0ea53..d4d10d9db 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -1416,6 +1416,8 @@ void UtilConvertCase() { "the_quick_brown_fox" }, { "the_quick_brown_fox", flatbuffers::Case::kKeep, "the_quick_brown_fox" }, + { "the_quick_brown_fox", flatbuffers::Case::kSnake2, + "the_quick_brown_fox" }, // Tests for some snake_cases where the _ is oddly placed or missing. { "single", flatbuffers::Case::kUpperCamel, "Single" }, @@ -1468,6 +1470,12 @@ void UtilConvertCase() { flatbuffers::Case::kSnake, "abctest" }, { flatbuffers::Case::kUpperCamel, "tHe_qUiCk_BrOwN_fOx", flatbuffers::Case::kKeep, "tHe_qUiCk_BrOwN_fOx" }, + { flatbuffers::Case::kLowerCamel, "theQuick12345Fox", + flatbuffers::Case::kSnake, "the_quick_12345fox" }, + { flatbuffers::Case::kLowerCamel, "a12b34c45", + flatbuffers::Case::kSnake, "a_12b_34c_45" }, + { flatbuffers::Case::kLowerCamel, "a12b34c45", + flatbuffers::Case::kSnake2, "a12_b34_c45" }, }; for (auto &test_case : cases) {