From 0bceba24db007c26d6f9847812c93c021d10d010 Mon Sep 17 00:00:00 2001 From: Derek Bailey Date: Tue, 15 Mar 2022 21:48:42 -0700 Subject: [PATCH] [Lua] Apply Namer to Lua (#7171) * Apply Namer to Lua bfbs code gen * refactor namer into IdlNamer to keep idl includes separate * remove commented out code * added bfbs_namer * remove Enum case * add to bazel --- CMakeLists.txt | 3 + src/BUILD.bazel | 4 ++ src/bfbs_gen.h | 20 ------ src/bfbs_gen_lua.cpp | 120 ++++++++++++++++++---------------- src/bfbs_namer.h | 43 ++++++++++++ src/idl_gen_go.cpp | 31 ++++----- src/idl_gen_python.cpp | 18 +++--- src/idl_gen_rust.cpp | 10 +-- src/idl_gen_swift.cpp | 110 +++++++++++++++++++++++++------ src/idl_namer.h | 114 ++++++++++++++++++++++++++++++++ src/namer.h | 144 ++++++++++++----------------------------- 11 files changed, 383 insertions(+), 234 deletions(-) create mode 100644 src/bfbs_namer.h create mode 100644 src/idl_namer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bf07fe17..439ad544d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -158,10 +158,13 @@ set(FlatBuffers_Compiler_SRCS src/idl_gen_grpc.cpp src/idl_gen_json_schema.cpp src/idl_gen_swift.cpp + src/idl_namer.h + src/namer.h src/flatc.cpp src/flatc_main.cpp src/bfbs_gen.h src/bfbs_gen_lua.h + src/bfbs_namer.h include/flatbuffers/code_generators.h src/bfbs_gen_lua.cpp src/code_generators.cpp diff --git a/src/BUILD.bazel b/src/BUILD.bazel index d8bbfcd10..4a7651bca 100644 --- a/src/BUILD.bazel +++ b/src/BUILD.bazel @@ -37,7 +37,9 @@ cc_library( "bfbs_gen.h", "bfbs_gen_lua.cpp", "bfbs_gen_lua.h", + "bfbs_namer.h", "flatc.cpp", + "namer.h", ], hdrs = [ "//:flatc_headers", @@ -56,6 +58,7 @@ cc_library( "bfbs_gen.h", "bfbs_gen_lua.cpp", "bfbs_gen_lua.h", + "bfbs_namer.h", "flatc_main.cpp", "idl_gen_cpp.cpp", "idl_gen_csharp.cpp", @@ -73,6 +76,7 @@ cc_library( "idl_gen_swift.cpp", "idl_gen_text.cpp", "idl_gen_ts.cpp", + "idl_namer.h", "namer.h", "util.cpp", ], diff --git a/src/bfbs_gen.h b/src/bfbs_gen.h index 12aafb376..937aca405 100644 --- a/src/bfbs_gen.h +++ b/src/bfbs_gen.h @@ -73,10 +73,6 @@ static bool IsStructOrTable(const reflection::BaseType base_type) { return base_type == reflection::Obj; } -static bool IsScalar(const reflection::BaseType base_type) { - return base_type >= reflection::UType && base_type <= reflection::Double; -} - static bool IsFloatingPoint(const reflection::BaseType base_type) { return base_type == reflection::Float || base_type == reflection::Double; } @@ -93,22 +89,6 @@ static bool IsVector(const reflection::BaseType base_type) { return base_type == reflection::Vector; } -static std::string Denamespace(const flatbuffers::String *name, - std::string &ns) { - const size_t pos = name->str().find_last_of('.'); - if (pos == std::string::npos) { - ns = ""; - return name->str(); - } - ns = name->str().substr(0, pos); - return name->str().substr(pos + 1); -} - -static std::string Denamespace(const flatbuffers::String *name) { - std::string ns; - return Denamespace(name, ns); -} - // A concrete base Flatbuffer Generator that specific language generators can // derive from. class BaseBfbsGenerator : public BfbsGenerator { diff --git a/src/bfbs_gen_lua.cpp b/src/bfbs_gen_lua.cpp index 868bb14ed..586f8ad52 100644 --- a/src/bfbs_gen_lua.cpp +++ b/src/bfbs_gen_lua.cpp @@ -25,9 +25,11 @@ // Ensure no includes to flatc internals. bfbs_gen.h and generator.h are OK. #include "bfbs_gen.h" +#include "bfbs_namer.h" #include "flatbuffers/bfbs_generator.h" // The intermediate representation schema. +#include "flatbuffers/reflection.h" #include "flatbuffers/reflection_generated.h" namespace flatbuffers { @@ -36,6 +38,36 @@ namespace { // To reduce typing namespace r = ::reflection; +std::set LuaKeywords() { + return { "and", "break", "do", "else", "elseif", "end", + "false", "for", "function", "goto", "if", "in", + "local", "nil", "not", "or", "repeat", "return", + "then", "true", "until", "while" }; +} + +Namer::Config LuaDefaultConfig() { + return { /*types=*/Case::kUpperCamel, + /*constants=*/Case::kUnknown, + /*methods=*/Case::kUpperCamel, + /*functions=*/Case::kUpperCamel, + /*fields=*/Case::kUpperCamel, + /*variables=*/Case::kLowerCamel, + /*variants=*/Case::kKeep, + /*enum_variant_seperator=*/"", + /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase, + /*namespaces=*/Case::kKeep, + /*namespace_seperator=*/"__", + /*object_prefix=*/"", + /*object_suffix=*/"", + /*keyword_prefix=*/"", + /*keyword_suffix=*/"_", + /*filenames=*/Case::kKeep, + /*directories=*/Case::kKeep, + /*output_path=*/"", + /*filename_suffix=*/"", + /*filename_extension=*/".lua" }; +} + class LuaBfbsGenerator : public BaseBfbsGenerator { public: explicit LuaBfbsGenerator(const std::string &flatc_version) @@ -44,14 +76,8 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { requires_(), current_obj_(nullptr), current_enum_(nullptr), - flatc_version_(flatc_version) { - static const char *const keywords[] = { - "and", "break", "do", "else", "elseif", "end", "false", "for", - "function", "goto", "if", "in", "local", "nil", "not", "or", - "repeat", "return", "then", "true", "until", "while" - }; - keywords_.insert(std::begin(keywords), std::end(keywords)); - } + flatc_version_(flatc_version), + namer_(LuaDefaultConfig(), LuaKeywords()) {} GeneratorStatus GenerateFromSchema(const r::Schema *schema) FLATBUFFERS_OVERRIDE { @@ -76,14 +102,14 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { std::string ns; const std::string enum_name = - NormalizeName(Denamespace(enum_def->name(), ns)); + namer_.Type(namer_.Denamespace(enum_def, ns)); GenerateDocumentation(enum_def->documentation(), "", code); code += "local " + enum_name + " = {\n"; ForAllEnumValues(enum_def, [&](const reflection::EnumVal *enum_val) { GenerateDocumentation(enum_val->documentation(), " ", code); - code += " " + NormalizeName(enum_val->name()) + " = " + + code += " " + namer_.Variant(enum_val->name()->str()) + " = " + NumToString(enum_val->value()) + ",\n"; }); code += "}\n"; @@ -107,7 +133,7 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { std::string ns; const std::string object_name = - NormalizeName(Denamespace(object->name(), ns)); + namer_.Type(namer_.Denamespace(object, ns)); GenerateDocumentation(object->documentation(), "", code); @@ -149,14 +175,12 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { // Skip writing deprecated fields altogether. if (field->deprecated()) { return; } - const std::string field_name = NormalizeName(field->name()); - const std::string field_name_camel_case = - ConvertCase(field_name, Case::kUpperCamel); + const std::string field_name = namer_.Field(field->name()->str()); const r::BaseType base_type = field->type()->base_type(); // Generate some fixed strings so we don't repeat outselves later. const std::string getter_signature = - "function mt:" + field_name_camel_case + "()\n"; + "function mt:" + field_name + "()\n"; const std::string offset_prefix = "local o = self.view:Offset(" + NumToString(field->offset()) + ")\n"; const std::string offset_prefix_2 = "if o ~= 0 then\n"; @@ -201,7 +225,7 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { } case r::Obj: { if (object->is_struct()) { - code += "function mt:" + field_name_camel_case + "(obj)\n"; + code += "function mt:" + field_name + "(obj)\n"; code += " obj:Init(self.view.bytes, self.view.pos + " + NumToString(field->offset()) + ")\n"; code += " return obj\n"; @@ -252,7 +276,7 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { case r::Vector: { const r::BaseType vector_base_type = field->type()->element(); int32_t element_size = field->type()->element_size(); - code += "function mt:" + field_name_camel_case + "(j)\n"; + code += "function mt:" + field_name + "(j)\n"; code += " " + offset_prefix; code += " " + offset_prefix_2; @@ -297,8 +321,7 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { // generate a helper function to get it as a byte string in // Lua. if (IsSingleByte(vector_base_type)) { - code += "function mt:" + field_name_camel_case + - "AsString(start, stop)\n"; + code += "function mt:" + field_name + "AsString(start, stop)\n"; code += " return self.view:VectorAsString(" + NumToString(field->offset()) + ", start, stop)\n"; code += "end\n"; @@ -307,7 +330,7 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { // We also make a new accessor to query just the length of the // vector. - code += "function mt:" + field_name_camel_case + "Length()\n"; + code += "function mt:" + field_name + "Length()\n"; code += " " + offset_prefix; code += " " + offset_prefix_2; code += " return self.view:VectorLen(o)\n"; @@ -344,21 +367,20 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) { if (field->deprecated()) { return; } - const std::string field_name = NormalizeName(field->name()); + const std::string field_name = namer_.Field(field->name()->str()); + const std::string variable_name = + namer_.Variable(field->name()->str()); - code += "function " + object_name + ".Add" + - ConvertCase(field_name, Case::kUpperCamel) + "(builder, " + - ConvertCase(field_name, Case::kLowerCamel) + ")\n"; + code += "function " + object_name + ".Add" + field_name + + "(builder, " + variable_name + ")\n"; code += " builder:Prepend" + GenerateMethod(field) + "Slot(" + - NumToString(field->id()) + ", " + - ConvertCase(field_name, Case::kLowerCamel) + ", " + + NumToString(field->id()) + ", " + variable_name + ", " + DefaultValue(field) + ")\n"; code += "end\n"; code += "\n"; if (IsVector(field->type()->base_type())) { - code += "function " + object_name + ".Start" + - ConvertCase(field_name, Case::kUpperCamel) + + code += "function " + object_name + ".Start" + field_name + "Vector(builder, numElems)\n"; const int32_t element_size = field->type()->element_size(); @@ -406,11 +428,9 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { if (IsStructOrTable(field->type()->base_type())) { const r::Object *field_object = GetObject(field->type()); signature += GenerateStructBuilderArgs( - field_object, prefix + NormalizeName(field->name()) + "_"); + field_object, prefix + namer_.Variable(field->name()->str()) + "_"); } else { - signature += - ", " + prefix + - ConvertCase(NormalizeName(field->name()), Case::kLowerCamel); + signature += ", " + prefix + namer_.Variable(field->name()->str()); } }); return signature; @@ -432,11 +452,10 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { if (IsStructOrTable(field->type()->base_type())) { const r::Object *field_object = GetObject(field->type()); code += AppendStructBuilderBody( - field_object, prefix + NormalizeName(field->name()) + "_"); + field_object, prefix + namer_.Variable(field->name()->str()) + "_"); } else { code += " builder:Prepend" + GenerateMethod(field) + "(" + prefix + - ConvertCase(NormalizeName(field->name()), Case::kLowerCamel) + - ")\n"; + namer_.Variable(field->name()->str()) + ")\n"; } }); @@ -445,9 +464,7 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { std::string GenerateMethod(const r::Field *field) const { const r::BaseType base_type = field->type()->base_type(); - if (IsScalar(base_type)) { - return ConvertCase(GenerateType(base_type), Case::kUpperCamel); - } + if (IsScalar(base_type)) { return namer_.Type(GenerateType(base_type)); } if (IsStructOrTable(base_type)) { return "Struct"; } return "UOffsetTRelative"; } @@ -460,9 +477,7 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { case r::Vector: return GenerateGetter(type, true); default: return "self.view:Get(flatbuffers.N." + - ConvertCase(GenerateType(type, element_type), - Case::kUpperCamel) + - ", "; + namer_.Type(GenerateType(type, element_type)) + ", "; } } @@ -474,10 +489,8 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { switch (base_type) { case r::String: return "string"; case r::Vector: return GenerateGetter(type, true); - case r::Obj: { - const r::Object *obj = GetObject(type); - return NormalizeName(Denamespace(obj->name())); - }; + case r::Obj: return namer_.Type(namer_.Denamespace(GetObject(type))); + default: return "*flatbuffers.Table"; } } @@ -515,14 +528,6 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { return "0"; } - std::string NormalizeName(const std::string name) const { - return keywords_.find(name) == keywords_.end() ? name : "_" + name; - } - - std::string NormalizeName(const flatbuffers::String *name) const { - return NormalizeName(name->str()); - } - void StartCodeBlock(const reflection::Enum *enum_def) { current_enum_ = enum_def; current_obj_ = nullptr; @@ -544,11 +549,11 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { if (IsStructOrTable(type)) { const r::Object *object = GetObjectByIndex(field->type()->index()); - if (object == current_obj_) { return Denamespace(object->name()); } + if (object == current_obj_) { return namer_.Denamespace(object); } type_name = object->name()->str(); } else { const r::Enum *enum_def = GetEnumByIndex(field->type()->index()); - if (enum_def == current_enum_) { return Denamespace(enum_def->name()); } + if (enum_def == current_enum_) { return namer_.Denamespace(enum_def); } type_name = enum_def->name()->str(); } @@ -600,7 +605,7 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { // Namespaces are '.' deliminted, so replace it with the path separator. std::string path = ns; - if (path.empty()) { + if (ns.empty()) { path = "."; } else { std::replace(path.begin(), path.end(), '.', '/'); @@ -608,7 +613,7 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { // TODO(derekbailey): figure out a save file without depending on util.h EnsureDirExists(path); - const std::string file_name = path + "/" + name + ".lua"; + const std::string file_name = path + "/" + namer_.File(name); SaveFile(file_name.c_str(), code, false); } @@ -617,6 +622,7 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { const r::Object *current_obj_; const r::Enum *current_enum_; const std::string flatc_version_; + const BfbsNamer namer_; }; } // namespace diff --git a/src/bfbs_namer.h b/src/bfbs_namer.h new file mode 100644 index 000000000..2c6e724ab --- /dev/null +++ b/src/bfbs_namer.h @@ -0,0 +1,43 @@ +#ifndef FLATBUFFERS_BFBS_NAMER +#define FLATBUFFERS_BFBS_NAMER + +#include "flatbuffers/reflection.h" +#include "namer.h" + +namespace flatbuffers { + +// Provides Namer capabilities to types defined in the flatbuffers reflection. +class BfbsNamer : public Namer { + public: + explicit BfbsNamer(Config config, std::set keywords) + : Namer(config, std::move(keywords)) {} + + using Namer::Constant; + using Namer::Denamespace; + using Namer::Directories; + using Namer::Field; + using Namer::File; + using Namer::Function; + using Namer::Method; + using Namer::Namespace; + using Namer::NamespacedType; + using Namer::ObjectType; + using Namer::Type; + using Namer::Variable; + using Namer::Variant; + + template + std::string Denamespace(T t, std::string &namespace_prefix, + const char delimiter = '.') const { + return Namer::Denamespace(t->name()->c_str(), namespace_prefix, delimiter); + } + + template + std::string Denamespace(T t, const char delimiter = '.') const { + return Namer::Denamespace(t->name()->c_str(), delimiter); + } +}; + +} // namespace flatbuffers + +#endif // FLATBUFFERS_BFBS_NAMER \ No newline at end of file diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp index 0eebbaf24..0ffa66c76 100644 --- a/src/idl_gen_go.cpp +++ b/src/idl_gen_go.cpp @@ -23,7 +23,7 @@ #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" #include "flatbuffers/util.h" -#include "namer.h" +#include "idl_namer.h" #ifdef _WIN32 # include @@ -82,8 +82,8 @@ class GoGenerator : public BaseGenerator { : BaseGenerator(parser, path, file_name, "" /* not used*/, "" /* not used */, "go"), cur_name_space_(nullptr), - namer_({ GoDefaultConfig().WithFlagOptions(parser.opts, path), - GoKeywords() }) { + namer_(WithFlagOptions(GoDefaultConfig(), parser.opts, path), + GoKeywords()) { std::istringstream iss(go_namespace); std::string component; while (std::getline(iss, component, '.')) { @@ -141,7 +141,7 @@ class GoGenerator : public BaseGenerator { private: Namespace go_namespace_; Namespace *cur_name_space_; - const Namer namer_; + const IdlNamer namer_; struct NamespacePtrLess { bool operator()(const Namespace *a, const Namespace *b) const { @@ -385,9 +385,7 @@ class GoGenerator : public BaseGenerator { code += "\t\treturn "; } code += CastToEnum(field.value.type, getter + "(o + rcv._tab.Pos)"); - if (field.IsScalarOptional()) { - code += "\n\t\treturn &v"; - } + if (field.IsScalarOptional()) { code += "\n\t\treturn &v"; } code += "\n\t}\n"; code += "\treturn " + GenConstant(field) + "\n"; code += "}\n\n"; @@ -709,7 +707,8 @@ class GoGenerator : public BaseGenerator { "rcv._tab.Mutate" + namer_.Method(GenTypeBasic(field.value.type)); GenReceiver(struct_def, code_ptr); code += " Mutate" + namer_.Function(field); - code += "(n " + GenTypeGet(field.value.type) + ") bool {\n\treturn " + setter; + code += + "(n " + GenTypeGet(field.value.type) + ") bool {\n\treturn " + setter; code += "(rcv._tab.Pos+flatbuffers.UOffsetT("; code += NumToString(field.value.offset) + "), "; code += CastToBaseType(field.value.type, "n") + ")\n}\n\n"; @@ -842,9 +841,7 @@ class GoGenerator : public BaseGenerator { field.value.type.enum_def->is_union) continue; code += "\t" + namer_.Field(field) + " "; - if (field.IsScalarOptional()) { - code += "*"; - } + if (field.IsScalarOptional()) { code += "*"; } code += NativeType(field.value.type) + "\n"; } code += "}\n\n"; @@ -1011,9 +1008,7 @@ class GoGenerator : public BaseGenerator { code += "\t" + struct_type + "Add" + field_fn + "(builder, " + prefix + "t." + field_field + ")\n"; } - if (field.IsScalarOptional()) { - code += "\t}\n"; - } + if (field.IsScalarOptional()) { code += "\t}\n"; } } else { if (field.value.type.base_type == BASE_TYPE_STRUCT && field.value.type.struct_def->fixed) { @@ -1247,9 +1242,7 @@ class GoGenerator : public BaseGenerator { std::string TypeName(const FieldDef &field) { std::string prefix; - if (field.IsScalarOptional()) { - prefix = "*"; - } + if (field.IsScalarOptional()) { prefix = "*"; } return prefix + GenTypeGet(field.value.type); } @@ -1274,9 +1267,7 @@ class GoGenerator : public BaseGenerator { } std::string GenConstant(const FieldDef &field) { - if (field.IsScalarOptional()) { - return "nil"; - } + if (field.IsScalarOptional()) { return "nil"; } switch (field.value.type.base_type) { case BASE_TYPE_BOOL: return field.value.constant == "0" ? "false" : "true"; diff --git a/src/idl_gen_python.cpp b/src/idl_gen_python.cpp index b319ed64d..999a0d0a3 100644 --- a/src/idl_gen_python.cpp +++ b/src/idl_gen_python.cpp @@ -26,7 +26,7 @@ #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" #include "flatbuffers/util.h" -#include "namer.h" +#include "idl_namer.h" namespace flatbuffers { namespace python { @@ -74,8 +74,8 @@ class PythonGenerator : public BaseGenerator { : BaseGenerator(parser, path, file_name, "" /* not used */, "" /* not used */, "py"), float_const_gen_("float('nan')", "float('inf')", "float('-inf')"), - namer_({ PythonDefaultConfig().WithFlagOptions(parser.opts, path), - PythonKeywords() }) {} + namer_(WithFlagOptions(PythonDefaultConfig(), parser.opts, path), + PythonKeywords()) {} // Most field accessors need to retrieve and test the field offset first, // this is the prefix code for that. @@ -414,7 +414,7 @@ class PythonGenerator : public BaseGenerator { } std::string NestedFlatbufferType(std::string unqualified_name) const { - StructDef* nested_root = parser_.LookupStruct(unqualified_name); + StructDef *nested_root = parser_.LookupStruct(unqualified_name); std::string qualified_name; if (nested_root == nullptr) { qualified_name = namer_.NamespacedType( @@ -1548,8 +1548,8 @@ class PythonGenerator : public BaseGenerator { const auto variant = namer_.Variant(ev); auto field_type = namer_.ObjectType(*ev.union_type.struct_def); - code += GenIndents(1) + "if unionType == " + union_type + "()." + - variant + ":"; + code += + GenIndents(1) + "if unionType == " + union_type + "()." + variant + ":"; if (parser_.opts.include_dependence_headers) { auto package_reference = GenPackageReference(ev.union_type); code += GenIndents(2) + "import " + package_reference; @@ -1565,8 +1565,8 @@ class PythonGenerator : public BaseGenerator { const auto union_type = namer_.Type(enum_def); const auto variant = namer_.Variant(ev); - code += GenIndents(1) + "if unionType == " + union_type + "()." + - variant + ":"; + code += + GenIndents(1) + "if unionType == " + union_type + "()." + variant + ":"; code += GenIndents(2) + "tab = Table(table.Bytes, table.Pos)"; code += GenIndents(2) + "union = tab.String(table.Pos)"; code += GenIndents(2) + "return union"; @@ -1778,7 +1778,7 @@ class PythonGenerator : public BaseGenerator { private: const SimpleFloatConstantGenerator float_const_gen_; - const Namer namer_; + const IdlNamer namer_; }; } // namespace python diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp index 9d4eac095..52299cd85 100644 --- a/src/idl_gen_rust.cpp +++ b/src/idl_gen_rust.cpp @@ -20,7 +20,7 @@ #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" #include "flatbuffers/util.h" -#include "namer.h" +#include "idl_namer.h" namespace flatbuffers { @@ -280,7 +280,7 @@ bool GenerateRustModuleRootFile(const Parser &parser, // so return true. return true; } - Namer namer(RustDefaultConfig().WithFlagOptions(parser.opts, output_dir), + Namer namer(WithFlagOptions(RustDefaultConfig(), parser.opts, output_dir), RustKeywords()); // We gather the symbols into a tree of namespaces (which are rust mods) and // generate a file that gathers them all. @@ -345,8 +345,8 @@ class RustGenerator : public BaseGenerator { const std::string &file_name) : BaseGenerator(parser, path, file_name, "", "::", "rs"), cur_name_space_(nullptr), - namer_({ RustDefaultConfig().WithFlagOptions(parser.opts, path), - RustKeywords() }) { + namer_(WithFlagOptions(RustDefaultConfig(), parser.opts, path), + RustKeywords()) { // TODO: Namer flag overrides should be in flatc or flatc_main. code_.SetPadding(" "); } @@ -2959,7 +2959,7 @@ class RustGenerator : public BaseGenerator { } private: - Namer namer_; + IdlNamer namer_; }; } // namespace rust diff --git a/src/idl_gen_swift.cpp b/src/idl_gen_swift.cpp index 794a970f5..2ae28d8b4 100644 --- a/src/idl_gen_swift.cpp +++ b/src/idl_gen_swift.cpp @@ -21,7 +21,7 @@ #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" #include "flatbuffers/util.h" -#include "namer.h" +#include "idl_namer.h" namespace flatbuffers { @@ -52,21 +52,88 @@ Namer::Config SwiftDefaultConfig() { std::set SwiftKeywords() { return { - "associatedtype", "class", "deinit", "enum", "extension", "fileprivate", - "func", "import", "init", "inout", "internal", "let", "open", "operator", - "private", "protocol", "public", "rethrows", "static", "struct", - "subscript", "typealias", "var", "break", "case", "continue", "default", - "defer", "do", "else", "fallthrough", "for", "guard", "if", "in", "repeat", - "return", "switch", "where", "while", "Any", "catch", "false", "is", "nil", - "super", "self", "Self", "throw", "throws", "true", "try", "associativity", - "convenience", "dynamic", "didSet", "final", "get", "infix", "indirect", - "lazy", "left", "mutating", "none", "nonmutating", "optional", "override", - "postfix", "precedence", "prefix", "Protocol", "required", "right", "set", - "Type", "unowned", "weak", "willSet", "Void", + "associatedtype", + "class", + "deinit", + "enum", + "extension", + "fileprivate", + "func", + "import", + "init", + "inout", + "internal", + "let", + "open", + "operator", + "private", + "protocol", + "public", + "rethrows", + "static", + "struct", + "subscript", + "typealias", + "var", + "break", + "case", + "continue", + "default", + "defer", + "do", + "else", + "fallthrough", + "for", + "guard", + "if", + "in", + "repeat", + "return", + "switch", + "where", + "while", + "Any", + "catch", + "false", + "is", + "nil", + "super", + "self", + "Self", + "throw", + "throws", + "true", + "try", + "associativity", + "convenience", + "dynamic", + "didSet", + "final", + "get", + "infix", + "indirect", + "lazy", + "left", + "mutating", + "none", + "nonmutating", + "optional", + "override", + "postfix", + "precedence", + "prefix", + "Protocol", + "required", + "right", + "set", + "Type", + "unowned", + "weak", + "willSet", + "Void", }; } - inline std::string GenIndirect(const std::string &reading) { return "{{ACCESS}}.indirect(" + reading + ")"; } @@ -87,7 +154,7 @@ class SwiftGenerator : public BaseGenerator { SwiftGenerator(const Parser &parser, const std::string &path, const std::string &file_name) : BaseGenerator(parser, path, file_name, "", "_", "swift"), - namer_(SwiftDefaultConfig().WithFlagOptions(parser.opts, path), + namer_(WithFlagOptions(SwiftDefaultConfig(), parser.opts, path), SwiftKeywords()) { namespace_depth = 0; code_.SetPadding(" "); @@ -187,7 +254,8 @@ class SwiftGenerator : public BaseGenerator { : is_bool ? ("0" == field.value.constant ? "false" : "true") : field.value.constant; - main_constructor.push_back("_" + field_var + " = " + field_var + accessing_value); + main_constructor.push_back("_" + field_var + " = " + field_var + + accessing_value); base_constructor.push_back("_" + field_var + " = " + base_value); if (field.padding) { GenPadding(field, &padding_id); } @@ -359,8 +427,8 @@ class SwiftGenerator : public BaseGenerator { code += ", "; continue; } - code += - nameprefix + field_var + ": " + obj_api_named + object_name + "." + field_field; + code += nameprefix + field_var + ": " + obj_api_named + object_name + + "." + field_field; code += ", "; } } @@ -1144,8 +1212,10 @@ class SwiftGenerator : public BaseGenerator { code_ += "case {{KEY}} = {{VALUE}}"; } code_ += ""; - AddMinOrMaxEnumValue(namer_.LegacySwiftVariant(*enum_def.MaxValue()), "max"); - AddMinOrMaxEnumValue(namer_.LegacySwiftVariant(*enum_def.MinValue()), "min"); + AddMinOrMaxEnumValue(namer_.LegacySwiftVariant(*enum_def.MaxValue()), + "max"); + AddMinOrMaxEnumValue(namer_.LegacySwiftVariant(*enum_def.MinValue()), + "min"); Outdent(); code_ += "}\n"; if (parser_.opts.gen_json_coders) EnumEncoder(enum_def); @@ -1838,7 +1908,7 @@ class SwiftGenerator : public BaseGenerator { std::string Mutable() const { return "_Mutable"; } - Namer namer_; + IdlNamer namer_; }; } // namespace swift bool GenerateSwift(const Parser &parser, const std::string &path, diff --git a/src/idl_namer.h b/src/idl_namer.h new file mode 100644 index 000000000..bfe57aa00 --- /dev/null +++ b/src/idl_namer.h @@ -0,0 +1,114 @@ +#ifndef FLATBUFFERS_IDL_NAMER +#define FLATBUFFERS_IDL_NAMER + +#include "flatbuffers/idl.h" +#include "namer.h" + +namespace flatbuffers { + +// Provides Namer capabilities to types defined in the flatbuffers IDL. +class IdlNamer : public Namer { + public: + explicit IdlNamer(Config config, std::set keywords) + : Namer(config, std::move(keywords)) {} + + using Namer::Constant; + using Namer::Directories; + using Namer::Field; + using Namer::File; + using Namer::Function; + using Namer::Method; + using Namer::Namespace; + using Namer::NamespacedType; + using Namer::ObjectType; + using Namer::Type; + using Namer::Variable; + using Namer::Variant; + + // Types are always structs or enums so we can only expose these two + // overloads. + std::string Type(const StructDef &d) const { return Type(d.name); } + std::string Type(const EnumDef &d) const { return Type(d.name); } + + std::string Function(const Definition &s) const { return Function(s.name); } + + std::string Field(const FieldDef &s) const { return Field(s.name); } + + std::string Variable(const FieldDef &s) const { return Variable(s.name); } + + std::string Variable(const StructDef &s) const { return Variable(s.name); } + + std::string Variant(const EnumVal &s) const { return Variant(s.name); } + + std::string EnumVariant(const EnumDef &e, const EnumVal &v) const { + return Type(e) + config_.enum_variant_seperator + Variant(v); + } + + std::string ObjectType(const StructDef &d) const { + return ObjectType(d.name); + } + std::string ObjectType(const EnumDef &d) const { return ObjectType(d.name); } + + std::string Namespace(const struct Namespace &ns) const { + return Namespace(ns.components); + } + + std::string NamespacedType(const Definition &def) const { + return NamespacedString(def.defined_namespace, Type(def.name)); + } + + std::string NamespacedObjectType(const Definition &def) const { + return NamespacedString(def.defined_namespace, ObjectType(def.name)); + } + + std::string Directories(const struct Namespace &ns, + SkipDir skips = SkipDir::None) const { + return Directories(ns.components, skips); + } + + // Legacy fields do not really follow the usual config and should be + // considered for deprecation. + + std::string LegacyRustNativeVariant(const EnumVal &v) const { + return ConvertCase(EscapeKeyword(v.name), Case::kUpperCamel); + } + + std::string LegacyRustFieldOffsetName(const FieldDef &field) const { + return "VT_" + ConvertCase(EscapeKeyword(field.name), Case::kAllUpper); + } + + // TODO(caspern): What's up with this case style? + std::string LegacySwiftVariant(const EnumVal &ev) const { + auto name = ev.name; + if (isupper(name.front())) { + std::transform(name.begin(), name.end(), name.begin(), CharToLower); + } + return EscapeKeyword(ConvertCase(name, Case::kLowerCamel)); + } + + private: + std::string NamespacedString(const struct Namespace *ns, + const std::string &str) const { + std::string ret; + if (ns != nullptr) { ret += Namespace(ns->components); } + if (!ret.empty()) ret += config_.namespace_seperator; + return ret + str; + } +}; + +// This is a temporary helper function for code generators to call until all +// flag-overriding logic into flatc.cpp +inline Namer::Config WithFlagOptions(const Namer::Config &input, + const IDLOptions &opts, + const std::string &path) { + Namer::Config result = input; + result.object_prefix = opts.object_prefix; + result.object_suffix = opts.object_suffix; + result.output_path = path; + result.filename_suffix = opts.filename_suffix; + return result; +} + +} // namespace flatbuffers + +#endif // FLATBUFFERS_IDL_NAMER \ No newline at end of file diff --git a/src/namer.h b/src/namer.h index 6cf97846d..95f85373e 100644 --- a/src/namer.h +++ b/src/namer.h @@ -1,7 +1,6 @@ #ifndef FLATBUFFERS_NAMER #define FLATBUFFERS_NAMER -#include "flatbuffers/idl.h" #include "flatbuffers/util.h" namespace flatbuffers { @@ -105,72 +104,35 @@ class Namer { std::string filename_suffix; // Extension for generated files, e.g. ".cpp" or ".rs". std::string filename_extension; - - // This is a temporary helper function for code generators to call until all - // code generators are using `Namer`. After that point, we can centralize - // flag-overriding logic into flatc.cpp - Config WithFlagOptions(const IDLOptions &opts, - const std::string &path) const { - Config result = *this; - result.object_prefix = opts.object_prefix; - result.object_suffix = opts.object_suffix; - result.output_path = path; - result.filename_suffix = opts.filename_suffix; - return result; - } }; Namer(Config config, std::set keywords) : config_(config), keywords_(std::move(keywords)) {} - // Types are always structs or enums so we can only expose these two - // overloads. - std::string Type(const StructDef &d) const { return Type(d.name); } - std::string Type(const EnumDef &d) const { return Type(d.name); } - template std::string Method(const T &s) const { return Method(s.name); } - std::string Method(const std::string &s) const { + virtual std::string Method(const std::string &s) const { return Format(s, config_.methods); } - std::string Constant(const std::string &s) const { + virtual std::string Constant(const std::string &s) const { return Format(s, config_.constants); } - std::string Function(const std::string &s) const { + virtual std::string Function(const std::string &s) const { return Format(s, config_.functions); } - std::string Function(const Definition &s) const { return Function(s.name); } - - std::string Field(const FieldDef &s) const { return Field(s.name); } - - std::string Variable(const FieldDef &s) const { return Variable(s.name); } - - std::string Variable(const StructDef &s) const { return Variable(s.name); } - - std::string Variable(const std::string &s) const { + virtual std::string Variable(const std::string &s) const { return Format(s, config_.variables); } - std::string Variant(const EnumVal &s) const { return Variant(s.name); } - - std::string EnumVariant(const EnumDef &e, const EnumVal &v) const { - return Type(e) + config_.enum_variant_seperator + Variant(v); - } - - std::string ObjectType(const StructDef &d) const { - return ObjectType(d.name); - } - std::string ObjectType(const EnumDef &d) const { return ObjectType(d.name); } - - std::string Namespace(const std::string &s) const { + virtual std::string Namespace(const std::string &s) const { return Format(s, config_.namespaces); } - std::string Namespace(const std::vector &ns) const { + virtual std::string Namespace(const std::vector &ns) const { std::string result; for (auto it = ns.begin(); it != ns.end(); it++) { if (it != ns.begin()) result += config_.namespace_seperator; @@ -179,27 +141,15 @@ class Namer { return result; } - std::string Namespace(const struct Namespace &ns) const { - return Namespace(ns.components); - } - - std::string NamespacedType(const Definition &def) const { - return NamespacedString(def.defined_namespace, Type(def.name)); - } - - std::string NamespacedType(const std::vector &ns, - const std::string &s) const { + virtual std::string NamespacedType(const std::vector &ns, + const std::string &s) const { return (ns.empty() ? "" : (Namespace(ns) + config_.namespace_seperator)) + Type(s); } - std::string NamespacedObjectType(const Definition &def) const { - return NamespacedString(def.defined_namespace, ObjectType(def.name)); - } - // Returns `filename` with the right casing, suffix, and extension. - std::string File(const std::string &filename, - SkipFile skips = SkipFile::None) const { + virtual std::string File(const std::string &filename, + SkipFile skips = SkipFile::None) const { const bool skip_suffix = (skips & SkipFile::Suffix) != SkipFile::None; const bool skip_ext = (skips & SkipFile::Extension) != SkipFile::None; return ConvertCase(filename, config_.filenames, Case::kUpperCamel) + @@ -215,8 +165,8 @@ class Namer { // right seperator. Output path prefixing and the trailing separator may be // skiped using `skips`. // Callers may want to use `EnsureDirExists` with the result. - std::string Directories(const std::vector &directories, - SkipDir skips = SkipDir::None) const { + virtual std::string Directories(const std::vector &directories, + SkipDir skips = SkipDir::None) const { const bool skip_output_path = (skips & SkipDir::OutputPath) != SkipDir::None; const bool skip_trailing_seperator = @@ -230,12 +180,7 @@ class Namer { return result; } - std::string Directories(const struct Namespace &ns, - SkipDir skips = SkipDir::None) const { - return Directories(ns.components, skips); - } - - std::string EscapeKeyword(const std::string &name) const { + virtual std::string EscapeKeyword(const std::string &name) const { if (keywords_.find(name) == keywords_.end()) { return name; } else { @@ -243,59 +188,52 @@ class Namer { } } - // Legacy fields do not really follow the usual config and should be - // considered for deprecation. - - std::string LegacyRustNativeVariant(const EnumVal &v) const { - return ConvertCase(EscapeKeyword(v.name), Case::kUpperCamel); - } - - std::string LegacyRustFieldOffsetName(const FieldDef& field) const { - - return "VT_" + ConvertCase(EscapeKeyword(field.name), Case::kAllUpper); - } - - // TODO(caspern): What's up with this case style? - std::string LegacySwiftVariant(const EnumVal &ev) const { - auto name = ev.name; - if (isupper(name.front())) { - std::transform(name.begin(), name.end(), name.begin(), CharToLower); - } - return EscapeKeyword(ConvertCase(name, Case::kLowerCamel)); - } - - private: - std::string Type(const std::string &s) const { + virtual std::string Type(const std::string &s) const { return Format(s, config_.types); } - std::string ObjectType(const std::string &s) const { + virtual std::string ObjectType(const std::string &s) const { return config_.object_prefix + Type(s) + config_.object_suffix; } - std::string Field(const std::string &s) const { + virtual std::string Field(const std::string &s) const { return Format(s, config_.fields); } - std::string Variant(const std::string &s) const { + virtual std::string Variant(const std::string &s) const { return Format(s, config_.variants); } - std::string NamespacedString(const struct Namespace *ns, - const std::string &str) const { - std::string ret; - if (ns != nullptr) { ret += Namespace(ns->components); } - if (!ret.empty()) ret += config_.namespace_seperator; - return ret + str; - } - - std::string Format(const std::string &s, Case casing) const { + virtual std::string Format(const std::string &s, Case casing) const { if (config_.escape_keywords == Config::Escape::BeforeConvertingCase) { return ConvertCase(EscapeKeyword(s), casing, Case::kLowerCamel); } else { return EscapeKeyword(ConvertCase(s, casing, Case::kLowerCamel)); } } + + // Denamespaces a string (e.g. The.Quick.Brown.Fox) by returning the last part + // after the `delimiter` (Fox) and placing the rest in `namespace_prefix` + // (The.Quick.Brown). + virtual std::string Denamespace(const std::string &s, + std::string &namespace_prefix, + const char delimiter = '.') const { + const size_t pos = s.find_last_of(delimiter); + if (pos == std::string::npos) { + namespace_prefix = ""; + return s; + } + namespace_prefix = s.substr(0, pos); + return s.substr(pos + 1); + } + + // Same as above, but disregards the prefix. + virtual std::string Denamespace(const std::string &s, + const char delimiter = '.') const { + std::string prefix; + return Denamespace(s, prefix, delimiter); + } + const Config config_; const std::set keywords_; };