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_dart.cpp b/src/idl_gen_dart.cpp
index ff2c1a5..0bf230d 100644
--- a/src/idl_gen_dart.cpp
+++ b/src/idl_gen_dart.cpp
@@ -21,26 +21,57 @@
 #include "flatbuffers/flatbuffers.h"
 #include "flatbuffers/idl.h"
 #include "flatbuffers/util.h"
+#include "idl_namer.h"
 
 namespace flatbuffers {
 
 namespace dart {
 
+namespace {
+
+static 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" };
+}
+
+static std::set<std::string> 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",
+  };
+}
+} // namespace
+
 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 +81,16 @@
 
   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 +108,23 @@
       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 +138,15 @@
     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<std::string>(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 +156,50 @@
 
   // Generate a documentation comment, if available.
   static void GenDocComment(const std::vector<std::string> &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<std::string>(), 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 +217,52 @@
 
     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<int, " + name + "> values = {\n";
+    code += "  static const Map<int, " + enum_type + "> 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 => 1;\n\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,12 +278,30 @@
       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";
     }
   }
 
+  static std::string EnumSize(const Type &type) {
+    switch (type.base_type) {
+      case BASE_TYPE_BOOL:
+      case BASE_TYPE_CHAR:
+      case BASE_TYPE_UTYPE:
+      case BASE_TYPE_UCHAR: return "1";
+      case BASE_TYPE_SHORT:
+      case BASE_TYPE_USHORT: return "2";
+      case BASE_TYPE_INT:
+      case BASE_TYPE_UINT:
+      case BASE_TYPE_FLOAT: return "4";
+      case BASE_TYPE_LONG:
+      case BASE_TYPE_ULONG:
+      case BASE_TYPE_DOUBLE: return "8";
+      default: return "1";
+    }
+  }
+
   std::string GenReaderTypeName(const Type &type, Namespace *current_namespace,
                                 const FieldDef &def,
                                 bool parent_is_vector = false, bool lazy = true,
@@ -378,11 +341,11 @@
                               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);
       }
     }
 
@@ -400,8 +363,9 @@
       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,
@@ -420,21 +384,19 @@
     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;
     }
@@ -442,29 +404,29 @@
 
   // 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<int> bytes) {\n";
+      code += "  factory " + struct_type + "(List<int> bytes) {\n";
       code +=
           "    final rootRef = " + _kFb + ".BufferContext.fromBytes(bytes);\n";
       code += "    return reader.read(rootRef, 0);\n";
@@ -472,7 +434,7 @@
     }
 
     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";
@@ -481,20 +443,20 @@
     std::vector<std::pair<int, FieldDef *>> 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<int>(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";
@@ -506,15 +468,13 @@
       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.
@@ -522,23 +482,23 @@
       const StructDef &struct_def,
       const std::vector<std::pair<int, FieldDef *>> &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";
@@ -549,10 +509,10 @@
         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;
@@ -561,12 +521,12 @@
     }
 
     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;
@@ -581,7 +541,7 @@
          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 + ": ";
 
@@ -612,8 +572,8 @@
       }
     }
 
-    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;
@@ -640,7 +600,7 @@
     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;
@@ -660,39 +620,35 @@
       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<std::pair<int, FieldDef *>> non_deprecated_fields,
-      std::string *code_ptr) {
-    auto &code = *code_ptr;
-
+      const std::vector<std::pair<int, FieldDef *>> &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, " +
@@ -733,7 +689,7 @@
     }
 
     code += "\n";
-    code += GenToString(struct_def.name, non_deprecated_fields);
+    code += GenToString(namer_.Type(struct_def), non_deprecated_fields);
   }
 
   std::string GenToString(
@@ -745,10 +701,15 @@
     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";
@@ -779,11 +740,9 @@
     }
   }
 
-  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) {
@@ -791,7 +750,7 @@
     } else {
       code += ".TableReader<";
     }
-    code += impl_name + "> {\n";
+    code += struct_type + "> {\n";
     code += "  const " + reader_name + "();\n\n";
 
     if (struct_def.fixed) {
@@ -799,27 +758,26 @@
       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<std::pair<int, FieldDef *>> non_deprecated_fields,
-                  std::string *builder_name_ptr, std::string *code_ptr) {
+  void GenBuilder(
+      const StructDef &struct_def,
+      const std::vector<std::pair<int, FieldDef *>> &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";
@@ -827,15 +785,13 @@
 
   void StructBuilderBody(
       const StructDef &struct_def,
-      std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
-      std::string *code_ptr) {
-    auto &code = *code_ptr;
-
+      const std::vector<std::pair<int, FieldDef *>> &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";
@@ -843,25 +799,25 @@
         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";
       }
@@ -872,10 +828,8 @@
 
   void TableBuilderBody(
       const StructDef &struct_def,
-      std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
-      std::string *code_ptr) {
-    auto &code = *code_ptr;
-
+      const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
+      std::string &code) {
     code += "  void begin() {\n";
     code += "    fbBuilder.startTable(" +
             NumToString(struct_def.fields.vec.size()) + ");\n";
@@ -883,28 +837,27 @@
 
     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);
+      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";
       }
@@ -920,21 +873,17 @@
 
   void GenObjectBuilder(
       const StructDef &struct_def,
-      std::vector<std::pair<int, FieldDef *>> 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<std::pair<int, FieldDef *>> &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 + "(";
@@ -943,24 +892,21 @@
       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 {
@@ -1000,11 +946,9 @@
       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 &&
@@ -1013,7 +957,7 @@
         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";
@@ -1072,8 +1016,8 @@
 
     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";
@@ -1082,11 +1026,11 @@
       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";
       }
@@ -1106,34 +1050,35 @@
 
     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
 
@@ -1148,8 +1093,7 @@
   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) {