[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
This commit is contained in:
Derek Bailey
2022-03-15 21:48:42 -07:00
committed by GitHub
parent b8c77d4041
commit 0bceba24db
11 changed files with 383 additions and 234 deletions

View File

@@ -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

View File

@@ -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",
],

View File

@@ -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 {

View File

@@ -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<std::string> 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

43
src/bfbs_namer.h Normal file
View File

@@ -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<std::string> 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<typename T>
std::string Denamespace(T t, std::string &namespace_prefix,
const char delimiter = '.') const {
return Namer::Denamespace(t->name()->c_str(), namespace_prefix, delimiter);
}
template<typename T>
std::string Denamespace(T t, const char delimiter = '.') const {
return Namer::Denamespace(t->name()->c_str(), delimiter);
}
};
} // namespace flatbuffers
#endif // FLATBUFFERS_BFBS_NAMER

View File

@@ -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 <direct.h>
@@ -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";

View File

@@ -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

View File

@@ -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

View File

@@ -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<std::string> 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,

114
src/idl_namer.h Normal file
View File

@@ -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<std::string> 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

View File

@@ -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<std::string> 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<typename T> 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<std::string> &ns) const {
virtual std::string Namespace(const std::vector<std::string> &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<std::string> &ns,
const std::string &s) const {
virtual std::string NamespacedType(const std::vector<std::string> &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<std::string> &directories,
SkipDir skips = SkipDir::None) const {
virtual std::string Directories(const std::vector<std::string> &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<std::string> keywords_;
};