* Namer for Kotlin

* delete unread cur_name_space_ and apply Namer to filename

Co-authored-by: Casper Neo <cneo@google.com>
This commit is contained in:
Casper
2022-04-26 21:54:49 -04:00
committed by GitHub
parent 750dde7669
commit 385dddc66a
3 changed files with 136 additions and 111 deletions

View File

@@ -23,6 +23,7 @@
#include "flatbuffers/flatbuffers.h" #include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h" #include "flatbuffers/idl.h"
#include "flatbuffers/util.h" #include "flatbuffers/util.h"
#include "idl_namer.h"
namespace flatbuffers { namespace flatbuffers {
@@ -35,23 +36,35 @@ static TypedFloatConstantGenerator KotlinFloatGen("Double.", "Float.", "NaN",
static const CommentConfig comment_config = { "/**", " *", " */" }; static const CommentConfig comment_config = { "/**", " *", " */" };
static const std::string ident_pad = " "; static const std::string ident_pad = " ";
static const char *keywords[] = { std::set<std::string> KotlinKeywords() {
"package", "as", "typealias", "class", "this", "super", return { "package", "as", "typealias", "class", "this", "super",
"val", "var", "fun", "for", "null", "true", "val", "var", "fun", "for", "null", "true",
"false", "is", "in", "throw", "return", "break", "false", "is", "in", "throw", "return", "break",
"continue", "object", "if", "try", "else", "while", "continue", "object", "if", "try", "else", "while",
"do", "when", "interface", "typeof", "Any", "Character" "do", "when", "interface", "typeof", "Any", "Character" };
}; }
// Escape Keywords Namer::Config KotlinDefaultConfig() {
static std::string Esc(const std::string &name) { return { /*types=*/Case::kKeep,
for (size_t i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) { /*constants=*/Case::kKeep,
if (name == keywords[i]) { /*methods=*/Case::kLowerCamel,
return ConvertCase(name + "_", Case::kLowerCamel); /*functions=*/Case::kKeep,
} /*fields=*/Case::kLowerCamel,
} /*variables=*/Case::kLowerCamel,
/*variants=*/Case::kLowerCamel,
return ConvertCase(name, Case::kLowerCamel); /*enum_variant_seperator=*/"", // I.e. Concatenate.
/*escape_keywords=*/Namer::Config::Escape::BeforeConvertingCase,
/*namespaces=*/Case::kKeep,
/*namespace_seperator=*/"__",
/*object_prefix=*/"",
/*object_suffix=*/"T",
/*keyword_prefix=*/"",
/*keyword_suffix=*/"_",
/*filenames=*/Case::kKeep,
/*directories=*/Case::kKeep,
/*output_path=*/"",
/*filename_suffix=*/"",
/*filename_extension=*/".kt" };
} }
class KotlinGenerator : public BaseGenerator { class KotlinGenerator : public BaseGenerator {
@@ -59,18 +72,17 @@ class KotlinGenerator : public BaseGenerator {
KotlinGenerator(const Parser &parser, const std::string &path, KotlinGenerator(const Parser &parser, const std::string &path,
const std::string &file_name) const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", ".", "kt"), : BaseGenerator(parser, path, file_name, "", ".", "kt"),
cur_name_space_(nullptr) {} namer_(WithFlagOptions(KotlinDefaultConfig(), parser.opts, path),
KotlinKeywords()) {}
KotlinGenerator &operator=(const KotlinGenerator &); KotlinGenerator &operator=(const KotlinGenerator &);
bool generate() FLATBUFFERS_OVERRIDE { bool generate() FLATBUFFERS_OVERRIDE {
std::string one_file_code; std::string one_file_code;
cur_name_space_ = parser_.current_namespace_;
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) { ++it) {
CodeWriter enumWriter(ident_pad); CodeWriter enumWriter(ident_pad);
auto &enum_def = **it; auto &enum_def = **it;
if (!parser_.opts.one_file) cur_name_space_ = enum_def.defined_namespace;
GenEnum(enum_def, enumWriter); GenEnum(enum_def, enumWriter);
if (parser_.opts.one_file) { if (parser_.opts.one_file) {
one_file_code += enumWriter.ToString(); one_file_code += enumWriter.ToString();
@@ -85,8 +97,6 @@ class KotlinGenerator : public BaseGenerator {
it != parser_.structs_.vec.end(); ++it) { it != parser_.structs_.vec.end(); ++it) {
CodeWriter structWriter(ident_pad); CodeWriter structWriter(ident_pad);
auto &struct_def = **it; auto &struct_def = **it;
if (!parser_.opts.one_file)
cur_name_space_ = struct_def.defined_namespace;
GenStruct(struct_def, structWriter, parser_.opts); GenStruct(struct_def, structWriter, parser_.opts);
if (parser_.opts.one_file) { if (parser_.opts.one_file) {
one_file_code += structWriter.ToString(); one_file_code += structWriter.ToString();
@@ -124,12 +134,10 @@ class KotlinGenerator : public BaseGenerator {
code += "import com.google.flatbuffers.*\n\n"; code += "import com.google.flatbuffers.*\n\n";
} }
code += classcode; code += classcode;
auto filename = NamespaceDir(ns) + defname + ".kt"; auto filename = namer_.Directories(ns)
return SaveFile(filename.c_str(), code, false); + namer_.File(defname, SkipFile::Suffix);
}
const Namespace *CurrentNameSpace() const FLATBUFFERS_OVERRIDE { return SaveFile(filename.c_str(), code, false);
return cur_name_space_;
} }
static bool IsEnum(const Type &type) { static bool IsEnum(const Type &type) {
@@ -261,7 +269,7 @@ class KotlinGenerator : public BaseGenerator {
GenerateComment(enum_def.doc_comment, writer, &comment_config); GenerateComment(enum_def.doc_comment, writer, &comment_config);
writer += "@Suppress(\"unused\")"; writer += "@Suppress(\"unused\")";
writer += "class " + Esc(enum_def.name) + " private constructor() {"; writer += "class " + namer_.Type(enum_def) + " private constructor() {";
writer.IncrementIdentLevel(); writer.IncrementIdentLevel();
GenerateCompanionObject(writer, [&]() { GenerateCompanionObject(writer, [&]() {
@@ -272,7 +280,7 @@ class KotlinGenerator : public BaseGenerator {
auto field_type = GenTypeBasic(enum_def.underlying_type.base_type); auto field_type = GenTypeBasic(enum_def.underlying_type.base_type);
auto val = enum_def.ToString(ev); auto val = enum_def.ToString(ev);
auto suffix = LiteralSuffix(enum_def.underlying_type.base_type); auto suffix = LiteralSuffix(enum_def.underlying_type.base_type);
writer.SetValue("name", Esc(ev.name)); writer.SetValue("name", namer_.LegacyKotlinVariant(ev));
writer.SetValue("type", field_type); writer.SetValue("type", field_type);
writer.SetValue("val", val + suffix); writer.SetValue("val", val + suffix);
GenerateComment(ev.doc_comment, writer, &comment_config); GenerateComment(ev.doc_comment, writer, &comment_config);
@@ -339,8 +347,8 @@ class KotlinGenerator : public BaseGenerator {
case BASE_TYPE_UTYPE: return bb_var_name + ".get"; case BASE_TYPE_UTYPE: return bb_var_name + ".get";
case BASE_TYPE_BOOL: return "0.toByte() != " + bb_var_name + ".get"; case BASE_TYPE_BOOL: return "0.toByte() != " + bb_var_name + ".get";
default: default:
return bb_var_name + ".get" + return bb_var_name + "." +
ConvertCase(GenTypeBasic(type.base_type), Case::kUpperCamel); namer_.Method("get", GenTypeBasic(type.base_type));
} }
} }
@@ -361,8 +369,7 @@ class KotlinGenerator : public BaseGenerator {
case BASE_TYPE_NONE: case BASE_TYPE_NONE:
case BASE_TYPE_UTYPE: return "bb.put"; case BASE_TYPE_UTYPE: return "bb.put";
default: default:
return "bb.put" + return "bb." + namer_.Method("put", GenTypeBasic(type.base_type));
ConvertCase(GenTypeBasic(type.base_type), Case::kUpperCamel);
} }
} }
return ""; return "";
@@ -385,8 +392,8 @@ class KotlinGenerator : public BaseGenerator {
// Recursively generate arguments for a constructor, to deal with nested // Recursively generate arguments for a constructor, to deal with nested
// structs. // structs.
static void GenStructArgs(const StructDef &struct_def, CodeWriter &writer, void GenStructArgs(const StructDef &struct_def, CodeWriter &writer,
const char *nameprefix) { const char *nameprefix) const {
for (auto it = struct_def.fields.vec.begin(); for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) { it != struct_def.fields.vec.end(); ++it) {
auto &field = **it; auto &field = **it;
@@ -399,7 +406,7 @@ class KotlinGenerator : public BaseGenerator {
(nameprefix + (field.name + "_")).c_str()); (nameprefix + (field.name + "_")).c_str());
} else { } else {
writer += std::string(", ") + nameprefix + "\\"; writer += std::string(", ") + nameprefix + "\\";
writer += ConvertCase(field.name, Case::kUpperCamel) + ": \\"; writer += namer_.Field(field) + ": \\";
writer += GenTypeBasic(field.value.type.base_type) + "\\"; writer += GenTypeBasic(field.value.type.base_type) + "\\";
} }
} }
@@ -408,8 +415,8 @@ class KotlinGenerator : public BaseGenerator {
// Recusively generate struct construction statements of the form: // Recusively generate struct construction statements of the form:
// builder.putType(name); // builder.putType(name);
// and insert manual padding. // and insert manual padding.
static void GenStructBody(const StructDef &struct_def, CodeWriter &writer, void GenStructBody(const StructDef &struct_def, CodeWriter &writer,
const char *nameprefix) { const char *nameprefix) const {
writer.SetValue("align", NumToString(struct_def.minalign)); writer.SetValue("align", NumToString(struct_def.minalign));
writer.SetValue("size", NumToString(struct_def.bytesize)); writer.SetValue("size", NumToString(struct_def.bytesize));
writer += "builder.prep({{align}}, {{size}})"; writer += "builder.prep({{align}}, {{size}})";
@@ -426,8 +433,7 @@ class KotlinGenerator : public BaseGenerator {
(nameprefix + (field.name + "_")).c_str()); (nameprefix + (field.name + "_")).c_str());
} else { } else {
writer.SetValue("type", GenMethod(field.value.type)); writer.SetValue("type", GenMethod(field.value.type));
writer.SetValue("argname", nameprefix + ConvertCase(Esc(field.name), writer.SetValue("argname", nameprefix + namer_.Variable(field));
Case::kLowerCamel));
writer.SetValue("cast", CastToSigned(field.value.type)); writer.SetValue("cast", CastToSigned(field.value.type));
writer += "builder.put{{type}}({{argname}}{{cast}})"; writer += "builder.put{{type}}({{argname}}{{cast}})";
} }
@@ -461,7 +467,7 @@ class KotlinGenerator : public BaseGenerator {
GenerateComment(struct_def.doc_comment, writer, &comment_config); GenerateComment(struct_def.doc_comment, writer, &comment_config);
auto fixed = struct_def.fixed; auto fixed = struct_def.fixed;
writer.SetValue("struct_name", Esc(struct_def.name)); writer.SetValue("struct_name", namer_.Type(struct_def));
writer.SetValue("superclass", fixed ? "Struct" : "Table"); writer.SetValue("superclass", fixed ? "Struct" : "Table");
writer += "@Suppress(\"unused\")"; writer += "@Suppress(\"unused\")";
@@ -477,7 +483,7 @@ class KotlinGenerator : public BaseGenerator {
// Generate assign method // Generate assign method
GenerateFun(writer, "__assign", "_i: Int, _bb: ByteBuffer", GenerateFun(writer, "__assign", "_i: Int, _bb: ByteBuffer",
Esc(struct_def.name), [&]() { namer_.Type(struct_def), [&]() {
writer += "__init(_i, _bb)"; writer += "__init(_i, _bb)";
writer += "return this"; writer += "return this";
}); });
@@ -498,7 +504,7 @@ class KotlinGenerator : public BaseGenerator {
[&]() { writer += "Constants.FLATBUFFERS_2_0_0()"; }, [&]() { writer += "Constants.FLATBUFFERS_2_0_0()"; },
options.gen_jvmstatic); options.gen_jvmstatic);
GenerateGetRootAsAccessors(Esc(struct_def.name), writer, options); GenerateGetRootAsAccessors(namer_.Type(struct_def), writer, options);
GenerateBufferHasIdentifier(struct_def, writer, options); GenerateBufferHasIdentifier(struct_def, writer, options);
GenerateTableCreator(struct_def, writer, options); GenerateTableCreator(struct_def, writer, options);
@@ -550,7 +556,7 @@ class KotlinGenerator : public BaseGenerator {
void GenerateLookupByKey(FieldDef *key_field, StructDef &struct_def, void GenerateLookupByKey(FieldDef *key_field, StructDef &struct_def,
CodeWriter &writer, const IDLOptions options) const { CodeWriter &writer, const IDLOptions options) const {
std::stringstream params; std::stringstream params;
params << "obj: " << Esc(struct_def.name) << "?" params << "obj: " << namer_.Type(struct_def) << "?"
<< ", "; << ", ";
params << "vectorLocation: Int, "; params << "vectorLocation: Int, ";
params << "key: " << GenTypeGet(key_field->value.type) << ", "; params << "key: " << GenTypeGet(key_field->value.type) << ", ";
@@ -558,7 +564,7 @@ class KotlinGenerator : public BaseGenerator {
auto statements = [&]() { auto statements = [&]() {
auto base_type = key_field->value.type.base_type; auto base_type = key_field->value.type.base_type;
writer.SetValue("struct_name", Esc(struct_def.name)); writer.SetValue("struct_name", namer_.Type(struct_def));
if (base_type == BASE_TYPE_STRING) { if (base_type == BASE_TYPE_STRING) {
writer += writer +=
"val byteKey = key." "val byteKey = key."
@@ -604,7 +610,8 @@ class KotlinGenerator : public BaseGenerator {
writer += "return null"; writer += "return null";
}; };
GenerateFun(writer, "__lookup_by_key", params.str(), GenerateFun(writer, "__lookup_by_key", params.str(),
Esc(struct_def.name) + "?", statements, options.gen_jvmstatic); namer_.Type(struct_def) + "?", statements,
options.gen_jvmstatic);
} }
void GenerateFinishSizePrefixed(StructDef &struct_def, void GenerateFinishSizePrefixed(StructDef &struct_def,
@@ -613,7 +620,8 @@ class KotlinGenerator : public BaseGenerator {
const IDLOptions options) const { const IDLOptions options) const {
auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : ""; auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : "";
auto params = "builder: FlatBufferBuilder, offset: Int"; auto params = "builder: FlatBufferBuilder, offset: Int";
auto method_name = "finishSizePrefixed" + Esc(struct_def.name) + "Buffer"; auto method_name =
namer_.LegacyJavaMethod2("finishSizePrefixed", struct_def, "Buffer");
GenerateFunOneLine( GenerateFunOneLine(
writer, method_name, params, "", writer, method_name, params, "",
[&]() { writer += "builder.finishSizePrefixed(offset" + id + ")"; }, [&]() { writer += "builder.finishSizePrefixed(offset" + id + ")"; },
@@ -625,7 +633,8 @@ class KotlinGenerator : public BaseGenerator {
const IDLOptions options) const { const IDLOptions options) const {
auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : ""; auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : "";
auto params = "builder: FlatBufferBuilder, offset: Int"; auto params = "builder: FlatBufferBuilder, offset: Int";
auto method_name = "finish" + Esc(struct_def.name) + "Buffer"; auto method_name =
namer_.LegacyKotlinMethod("finish", struct_def, "Buffer");
GenerateFunOneLine( GenerateFunOneLine(
writer, method_name, params, "", writer, method_name, params, "",
[&]() { writer += "builder.finish(offset" + id + ")"; }, [&]() { writer += "builder.finish(offset" + id + ")"; },
@@ -635,7 +644,7 @@ class KotlinGenerator : public BaseGenerator {
void GenerateEndStructMethod(StructDef &struct_def, CodeWriter &writer, void GenerateEndStructMethod(StructDef &struct_def, CodeWriter &writer,
const IDLOptions options) const { const IDLOptions options) const {
// Generate end{{TableName}}(builder: FlatBufferBuilder) method // Generate end{{TableName}}(builder: FlatBufferBuilder) method
auto name = "end" + Esc(struct_def.name); auto name = namer_.LegacyJavaMethod2("end", struct_def, "");
auto params = "builder: FlatBufferBuilder"; auto params = "builder: FlatBufferBuilder";
auto returns = "Int"; auto returns = "Int";
auto field_vec = struct_def.fields.vec; auto field_vec = struct_def.fields.vec;
@@ -661,8 +670,7 @@ class KotlinGenerator : public BaseGenerator {
void GenerateCreateVectorField(FieldDef &field, CodeWriter &writer, void GenerateCreateVectorField(FieldDef &field, CodeWriter &writer,
const IDLOptions options) const { const IDLOptions options) const {
auto vector_type = field.value.type.VectorType(); auto vector_type = field.value.type.VectorType();
auto method_name = auto method_name = namer_.Method("create", field, "vector");
"create" + ConvertCase(Esc(field.name), Case::kUpperCamel) + "Vector";
auto params = "builder: FlatBufferBuilder, data: " + auto params = "builder: FlatBufferBuilder, data: " +
GenTypeBasic(vector_type.base_type) + "Array"; GenTypeBasic(vector_type.base_type) + "Array";
writer.SetValue("size", NumToString(InlineSize(vector_type))); writer.SetValue("size", NumToString(InlineSize(vector_type)));
@@ -694,9 +702,7 @@ class KotlinGenerator : public BaseGenerator {
writer.SetValue("align", NumToString(InlineAlignment(vector_type))); writer.SetValue("align", NumToString(InlineAlignment(vector_type)));
GenerateFunOneLine( GenerateFunOneLine(
writer, writer, namer_.Method("start", field, "Vector"), params, "",
"start" + ConvertCase(Esc(field.name) + "Vector", Case::kUpperCamel),
params, "",
[&]() { [&]() {
writer += "builder.startVector({{size}}, numElems, {{align}})"; writer += "builder.startVector({{size}}, numElems, {{align}})";
}, },
@@ -706,35 +712,35 @@ class KotlinGenerator : public BaseGenerator {
void GenerateAddField(std::string field_pos, FieldDef &field, void GenerateAddField(std::string field_pos, FieldDef &field,
CodeWriter &writer, const IDLOptions options) const { CodeWriter &writer, const IDLOptions options) const {
auto field_type = GenTypeBasic(field.value.type.base_type); auto field_type = GenTypeBasic(field.value.type.base_type);
auto secondArg = auto secondArg = namer_.Variable(field.name) + ": " + field_type;
ConvertCase(Esc(field.name), Case::kLowerCamel) + ": " + field_type;
auto content = [&]() { auto content = [&]() {
auto method = GenMethod(field.value.type); auto method = GenMethod(field.value.type);
writer.SetValue("field_name", writer.SetValue("field_name", namer_.Field(field));
ConvertCase(Esc(field.name), Case::kLowerCamel)); writer.SetValue("method_name", method);
writer.SetValue("method_name", method); writer.SetValue("pos", field_pos);
writer.SetValue("pos", field_pos); writer.SetValue("default", GenFBBDefaultValue(field));
writer.SetValue("default", GenFBBDefaultValue(field)); writer.SetValue("cast", GenFBBValueCast(field));
writer.SetValue("cast", GenFBBValueCast(field)); if (field.key) {
if (field.key) { // field has key attribute, so always need to exist
// field has key attribute, so always need to exist // even if its value is equal to default.
// even if its value is equal to default. // Generated code will bypass default checking
// Generated code will bypass default checking // resulting in { builder.addShort(name); slot(id); }
// resulting in { builder.addShort(name); slot(id); } writer += "builder.add{{method_name}}({{field_name}}{{cast}})";
writer += "builder.add{{method_name}}({{field_name}}{{cast}})"; writer += "builder.slot({{pos}})";
writer += "builder.slot({{pos}})"; } else {
} else { writer += "builder.add{{method_name}}({{pos}}, \\";
writer += "builder.add{{method_name}}({{pos}}, \\"; writer += "{{field_name}}{{cast}}, {{default}})";
writer += "{{field_name}}{{cast}}, {{default}})"; }
} };
}; auto signature = namer_.LegacyKotlinMethod("add", field, "");
auto signature = "add" + ConvertCase(Esc(field.name), Case::kUpperCamel);
auto params = "builder: FlatBufferBuilder, " + secondArg; auto params = "builder: FlatBufferBuilder, " + secondArg;
if (field.key) { if (field.key) {
GenerateFun(writer,signature, params, "", content, options.gen_jvmstatic); GenerateFun(writer, signature, params, "", content,
options.gen_jvmstatic);
} else { } else {
GenerateFunOneLine(writer, signature, params, "", content, options.gen_jvmstatic); GenerateFunOneLine(writer, signature, params, "", content,
options.gen_jvmstatic);
} }
} }
@@ -779,7 +785,8 @@ class KotlinGenerator : public BaseGenerator {
void GenerateStartStructMethod(StructDef &struct_def, CodeWriter &code, void GenerateStartStructMethod(StructDef &struct_def, CodeWriter &code,
const IDLOptions options) const { const IDLOptions options) const {
GenerateFunOneLine( GenerateFunOneLine(
code, "start" + Esc(struct_def.name), "builder: FlatBufferBuilder", "", code, namer_.LegacyJavaMethod2("start", struct_def, ""),
"builder: FlatBufferBuilder", "",
[&]() { [&]() {
code += "builder.startTable(" + code += "builder.startTable(" +
NumToString(struct_def.fields.vec.size()) + ")"; NumToString(struct_def.fields.vec.size()) + ")";
@@ -811,13 +818,13 @@ class KotlinGenerator : public BaseGenerator {
// Generate a table constructor of the form: // Generate a table constructor of the form:
// public static int createName(FlatBufferBuilder builder, args...) // public static int createName(FlatBufferBuilder builder, args...)
auto name = "create" + Esc(struct_def.name); auto name = namer_.LegacyJavaMethod2("create", struct_def, "");
std::stringstream params; std::stringstream params;
params << "builder: FlatBufferBuilder"; params << "builder: FlatBufferBuilder";
for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) { for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) {
auto &field = **it; auto &field = **it;
if (field.deprecated) continue; if (field.deprecated) continue;
params << ", " << ConvertCase(Esc(field.name), Case::kLowerCamel); params << ", " << namer_.Variable(field);
if (!IsScalar(field.value.type.base_type)) { if (!IsScalar(field.value.type.base_type)) {
params << "Offset: "; params << "Offset: ";
} else { } else {
@@ -843,18 +850,15 @@ class KotlinGenerator : public BaseGenerator {
auto base_type_size = SizeOf(field.value.type.base_type); auto base_type_size = SizeOf(field.value.type.base_type);
if (!field.deprecated && if (!field.deprecated &&
(!sortbysize || size == base_type_size)) { (!sortbysize || size == base_type_size)) {
writer.SetValue( writer.SetValue("field_name", namer_.Field(field));
"camel_field_name",
ConvertCase(Esc(field.name), Case::kUpperCamel));
writer.SetValue("field_name", ConvertCase(Esc(field.name),
Case::kLowerCamel));
// we wrap on null check for scalar optionals // we wrap on null check for scalar optionals
writer += field.IsScalarOptional() writer += field.IsScalarOptional()
? "{{field_name}}?.run { \\" ? "{{field_name}}?.run { \\"
: "\\"; : "\\";
writer += "add{{camel_field_name}}(builder, {{field_name}}\\"; writer += namer_.LegacyKotlinMethod("add", field, "") +
"(builder, {{field_name}}\\";
if (!IsScalar(field.value.type.base_type)) { if (!IsScalar(field.value.type.base_type)) {
writer += "Offset\\"; writer += "Offset\\";
} }
@@ -874,7 +878,7 @@ class KotlinGenerator : public BaseGenerator {
// Check if a buffer has the identifier. // Check if a buffer has the identifier.
if (parser_.root_struct_def_ != &struct_def || !file_identifier.length()) if (parser_.root_struct_def_ != &struct_def || !file_identifier.length())
return; return;
auto name = ConvertCase(Esc(struct_def.name), Case::kLowerCamel); auto name = namer_.Function(struct_def);
GenerateFunOneLine( GenerateFunOneLine(
writer, name + "BufferHasIdentifier", "_bb: ByteBuffer", "Boolean", writer, name + "BufferHasIdentifier", "_bb: ByteBuffer", "Boolean",
[&]() { [&]() {
@@ -893,7 +897,7 @@ class KotlinGenerator : public BaseGenerator {
GenerateComment(field.doc_comment, writer, &comment_config); GenerateComment(field.doc_comment, writer, &comment_config);
auto field_name = ConvertCase(Esc(field.name), Case::kLowerCamel); auto field_name = namer_.Field(field);
auto field_type = GenTypeGet(field.value.type); auto field_type = GenTypeGet(field.value.type);
auto field_default_value = GenDefaultValue(field); auto field_default_value = GenDefaultValue(field);
auto return_type = GetterReturnType(field); auto return_type = GetterReturnType(field);
@@ -1064,8 +1068,7 @@ class KotlinGenerator : public BaseGenerator {
auto &kfield = **kit; auto &kfield = **kit;
if (kfield.key) { if (kfield.key) {
auto qualified_name = WrapInNameSpace(sd); auto qualified_name = WrapInNameSpace(sd);
auto name = auto name = namer_.Method(field, "ByKey");
ConvertCase(Esc(field.name), Case::kLowerCamel) + "ByKey";
auto params = "key: " + GenTypeGet(kfield.value.type); auto params = "key: " + GenTypeGet(kfield.value.type);
auto rtype = qualified_name + "?"; auto rtype = qualified_name + "?";
GenerateFun(writer, name, params, rtype, [&]() { GenerateFun(writer, name, params, rtype, [&]() {
@@ -1158,9 +1161,9 @@ class KotlinGenerator : public BaseGenerator {
auto underlying_type = value_base_type == BASE_TYPE_VECTOR auto underlying_type = value_base_type == BASE_TYPE_VECTOR
? value_type.VectorType() ? value_type.VectorType()
: value_type; : value_type;
auto name = "mutate" + ConvertCase(Esc(field.name), Case::kUpperCamel); auto name = namer_.LegacyKotlinMethod("mutate", field, "");
auto size = NumToString(InlineSize(underlying_type)); auto size = NumToString(InlineSize(underlying_type));
auto params = Esc(field.name) + ": " + GenTypeGet(underlying_type); auto params = namer_.Field(field) + ": " + GenTypeGet(underlying_type);
// A vector mutator also needs the index of the vector element it should // A vector mutator also needs the index of the vector element it should
// mutate. // mutate.
if (value_base_type == BASE_TYPE_VECTOR) params.insert(0, "j: Int, "); if (value_base_type == BASE_TYPE_VECTOR) params.insert(0, "j: Int, ");
@@ -1169,8 +1172,8 @@ class KotlinGenerator : public BaseGenerator {
// representation. // representation.
auto setter_parameter = auto setter_parameter =
underlying_type.base_type == BASE_TYPE_BOOL underlying_type.base_type == BASE_TYPE_BOOL
? "(if(" + Esc(field.name) + ") 1 else 0).toByte()" ? "(if(" + namer_.Field(field) + ") 1 else 0).toByte()"
: Esc(field.name); : namer_.Field(field);
auto setter_index = auto setter_index =
value_base_type == BASE_TYPE_VECTOR value_base_type == BASE_TYPE_VECTOR
@@ -1303,9 +1306,9 @@ class KotlinGenerator : public BaseGenerator {
} }
} }
static void GenerateGetRootAsAccessors(const std::string &struct_name, void GenerateGetRootAsAccessors(const std::string &struct_name,
CodeWriter &writer, CodeWriter &writer,
IDLOptions options) { IDLOptions options) const {
// Generate a special accessor for the table that when used as the root // Generate a special accessor for the table that when used as the root
// ex: fun getRootAsMonster(_bb: ByteBuffer): Monster {...} // ex: fun getRootAsMonster(_bb: ByteBuffer): Monster {...}
writer.SetValue("gr_name", struct_name); writer.SetValue("gr_name", struct_name);
@@ -1331,13 +1334,12 @@ class KotlinGenerator : public BaseGenerator {
writer += "}"; writer += "}";
} }
static void GenerateStaticConstructor(const StructDef &struct_def, void GenerateStaticConstructor(const StructDef &struct_def, CodeWriter &code,
CodeWriter &code, const IDLOptions options) const {
const IDLOptions options) {
// create a struct constructor function // create a struct constructor function
auto params = StructConstructorParams(struct_def); auto params = StructConstructorParams(struct_def);
GenerateFun( GenerateFun(
code, "create" + Esc(struct_def.name), params, "Int", code, namer_.LegacyJavaMethod2("create", struct_def, ""), params, "Int",
[&]() { [&]() {
GenStructBody(struct_def, code, ""); GenStructBody(struct_def, code, "");
code += "return builder.offset()"; code += "return builder.offset()";
@@ -1345,8 +1347,8 @@ class KotlinGenerator : public BaseGenerator {
options.gen_jvmstatic); options.gen_jvmstatic);
} }
static std::string StructConstructorParams(const StructDef &struct_def, std::string StructConstructorParams(const StructDef &struct_def,
const std::string &prefix = "") { const std::string &prefix = "") const {
// builder: FlatBufferBuilder // builder: FlatBufferBuilder
std::stringstream out; std::stringstream out;
auto field_vec = struct_def.fields.vec; auto field_vec = struct_def.fields.vec;
@@ -1359,10 +1361,10 @@ class KotlinGenerator : public BaseGenerator {
// constructing a nested struct, prefix the name with the field // constructing a nested struct, prefix the name with the field
// name. // name.
out << StructConstructorParams(*field.value.type.struct_def, out << StructConstructorParams(*field.value.type.struct_def,
prefix + (Esc(field.name) + "_")); prefix + (namer_.Variable(field) + "_"));
} else { } else {
out << ", " << prefix << ConvertCase(Esc(field.name), Case::kLowerCamel) out << ", " << prefix << namer_.Variable(field) << ": "
<< ": " << GenTypeBasic(field.value.type.base_type); << GenTypeBasic(field.value.type.base_type);
} }
} }
return out.str(); return out.str();
@@ -1531,9 +1533,7 @@ class KotlinGenerator : public BaseGenerator {
if (gen_jvmstatic) { code += "@JvmStatic"; } if (gen_jvmstatic) { code += "@JvmStatic"; }
} }
// This tracks the current namespace used to determine if a type need to be const IdlNamer namer_;
// prefixed by its namespace
const Namespace *cur_name_space_;
}; };
} // namespace kotlin } // namespace kotlin

View File

@@ -63,6 +63,10 @@ class IdlNamer : public Namer {
std::string Method(const std::string &prefix, const FieldDef &d) const { std::string Method(const std::string &prefix, const FieldDef &d) const {
return Method(prefix, d.name); return Method(prefix, d.name);
} }
std::string Method(const std::string &prefix, const FieldDef &d,
const std::string &suffix) const {
return Method(prefix, d.name, suffix);
}
std::string Namespace(const struct Namespace &ns) const { std::string Namespace(const struct Namespace &ns) const {
return Namespace(ns.components); return Namespace(ns.components);
@@ -96,7 +100,6 @@ class IdlNamer : public Namer {
return "VT_" + ConvertCase(EscapeKeyword(field.name), Case::kAllUpper); return "VT_" + ConvertCase(EscapeKeyword(field.name), Case::kAllUpper);
} }
// TODO(caspern): What's up with this case style?
std::string LegacySwiftVariant(const EnumVal &ev) const { std::string LegacySwiftVariant(const EnumVal &ev) const {
auto name = ev.name; auto name = ev.name;
if (isupper(name.front())) { if (isupper(name.front())) {
@@ -105,11 +108,29 @@ class IdlNamer : public Namer {
return EscapeKeyword(ConvertCase(name, Case::kLowerCamel)); return EscapeKeyword(ConvertCase(name, Case::kLowerCamel));
} }
// Also used by Kotlin, lol.
std::string LegacyJavaMethod2(const std::string &prefix, const StructDef &sd, std::string LegacyJavaMethod2(const std::string &prefix, const StructDef &sd,
const std::string &suffix) const { const std::string &suffix) const {
return prefix + sd.name + suffix; return prefix + sd.name + suffix;
} }
std::string LegacyKotlinVariant(EnumVal &ev) const {
// Namer assumes the input case is snake case which is wrong...
return ConvertCase(EscapeKeyword(ev.name), Case::kLowerCamel);
}
// Kotlin methods escapes keywords after case conversion but before
// prefixing and suffixing.
std::string LegacyKotlinMethod(const std::string &prefix, const FieldDef &d,
const std::string &suffix) const {
return prefix + ConvertCase(EscapeKeyword(d.name), Case::kUpperCamel) +
suffix;
}
std::string LegacyKotlinMethod(const std::string &prefix, const StructDef &d,
const std::string &suffix) const {
return prefix + ConvertCase(EscapeKeyword(d.name), Case::kUpperCamel) +
suffix;
}
private: private:
std::string NamespacedString(const struct Namespace *ns, std::string NamespacedString(const struct Namespace *ns,
const std::string &str) const { const std::string &str) const {

View File

@@ -114,11 +114,15 @@ class Namer {
return Method(s.name); return Method(s.name);
} }
virtual std::string Method(const std::string &pre,
const std::string &mid,
const std::string &suf) const {
return Format(pre + "_" + mid + "_" + suf, config_.methods);
}
virtual std::string Method(const std::string &pre, virtual std::string Method(const std::string &pre,
const std::string &suf) const { const std::string &suf) const {
return Format(pre + "_" + suf, config_.methods); return Format(pre + "_" + suf, config_.methods);
} }
virtual std::string Method(const std::string &s) const { virtual std::string Method(const std::string &s) const {
return Format(s, config_.methods); return Format(s, config_.methods);
} }