diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_class_generator.cc b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_class_generator.cc index 17189080888..40996a01d87 100644 --- a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_class_generator.cc +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_class_generator.cc @@ -7,6 +7,7 @@ #include "kotlin_enum_generator.h" #include "kotlin_field_generator.h" #include "kotlin_name_resolver.h" +#include "UnreachableStateException.h" #include namespace google { @@ -34,9 +35,6 @@ void ClassGenerator::generateCode(io::Printer *printer, bool isBuilder) const { // Generate construction routines generateInitSection(printer); printer->Print("\n"); - generateConstructor(printer, isBuilder); - printer->Print("\n"); - // enum declarations and nested classes declarations only for fair classes if (!isBuilder) { @@ -106,15 +104,15 @@ ClassGenerator::ClassGenerator(Descriptor const *descriptor, NameResolver * name int nested_types_count = descriptor->nested_type_count(); for (int i = 0; i < nested_types_count; ++i) { Descriptor const * nestedClassDescriptor = descriptor->nested_type(i); - nameResolver->addClass(nestedClassDescriptor->name(), getFullType()); classesDeclarations.push_back(new ClassGenerator(nestedClassDescriptor, nameResolver)); + nameResolver->addClass(nestedClassDescriptor->name(), getFullType(), classesDeclarations.back()); } int enums_declarations_count = descriptor->enum_type_count(); for (int i = 0; i < enums_declarations_count; ++i) { EnumDescriptor const * nestedEnumDescriptor = descriptor->enum_type(i); - nameResolver->addClass(nestedEnumDescriptor->name(), getFullType()); enumsDeclaraions.push_back(new EnumGenerator(nestedEnumDescriptor, nameResolver)); + nameResolver->addClass(nestedEnumDescriptor->name(), getFullType(), /* classGenerator = */ nullptr); } /** @@ -185,8 +183,9 @@ void ClassGenerator::generateMergeMethods(io::Printer *printer) const { printer->Indent(); vars["builderName"] = getBuilderFullType(); - printer->Print(vars, "val builder = $builderName$()\n"); - printer->Print("mergeWith(builder.parseFromWithSize(input, expectedSize).build())"); + vars["initValue"] = getBuilderInitValue(); + printer->Print(vars, "val builder = $initValue$\n"); + printer->Print("mergeWith(builder.parseFromWithSize(input, expectedSize).build())\n"); printer->Outdent(); printer->Print("}\n"); @@ -197,8 +196,8 @@ void ClassGenerator::generateMergeMethods(io::Printer *printer) const { printer->Indent(); vars["builderName"] = getBuilderFullType(); - printer->Print(vars, "val builder = $builderName$()\n"); - printer->Print("mergeWith(builder.parseFrom(input).build())"); + printer->Print(vars, "val builder = $initValue$\n"); + printer->Print("mergeWith(builder.parseFrom(input).build())\n"); printer->Outdent(); printer->Print("}\n"); @@ -221,7 +220,7 @@ void ClassGenerator::generateWriteToMethod(io::Printer *printer) const { printer->Print("}\n"); } -void ClassGenerator::generateConstructor(io::Printer * printer, bool isBuilder) const { +void ClassGenerator::generateHeader(io::Printer * printer, bool isBuilder) const { // build list of arguments like 'field1: Type1, field2: Type2, ... ' string argumentList = ""; for (int i = 0; i < properties.size(); ++i) { @@ -231,35 +230,12 @@ void ClassGenerator::generateConstructor(io::Printer * printer, bool isBuilder) } } - map vars; - vars["name"] = isBuilder ? getBuidlerSimpleType() : getSimpleType(); - vars["private"] = isBuilder ? "" : "private "; - vars["arguments"] = argumentList; - printer->Print(vars, "$private$constructor ($arguments$) : this() {\n"); - printer->Indent(); - - for (int i = 0; i < properties.size(); ++i) { - map vars; - vars["name"] = properties[i]->simpleName; - vars["initVal"] = properties[i]->getInitValue(); - printer->Print(vars, - "this.$name$ = $name$" - "\n" - ); - } - - printer->Outdent(); - printer->Print("}\n"); -} - -void ClassGenerator::generateHeader(io::Printer * printer, bool isBuilder) const { - - map vars; vars["name"] = isBuilder? getBuidlerSimpleType() : getSimpleType(); vars["maybePrivate"] = isBuilder? "" : " private"; + vars["args"] = argumentList; printer->Print(vars, - "class $name$$maybePrivate$ constructor () {" + "class $name$$maybePrivate$ constructor ($args$) {" "\n" ); } @@ -294,7 +270,7 @@ void ClassGenerator::generateInitSection(io::Printer * printer) const { vars["name"] = properties[i]->simpleName; vars["initVal"] = properties[i]->getInitValue(); printer->Print(vars, - "this.$name$ = $initVal$" + "this.$name$ = $name$" "\n" ); } @@ -441,6 +417,19 @@ string ClassGenerator::getBuidlerSimpleType() const { return "Builder" + getSimpleType(); } +string ClassGenerator::getBuilderInitValue() const { + // build list of arguments like 'field1: Type1, field2: Type2, ... ' + string argumentList = ""; + for (int i = 0; i < properties.size(); ++i) { + argumentList += properties[i]->simpleName + " = " + properties[i]->getInitValue(); + if (i + 1 != properties.size()) { + argumentList += ", "; + } + } + + return getBuilderFullType() + "(" + argumentList + ")"; +} + } // namespace kotlin } // namespace compiler diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_class_generator.h b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_class_generator.h index 2d24c870bc4..4d3d87756d5 100644 --- a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_class_generator.h +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_class_generator.h @@ -27,6 +27,7 @@ public: string getFullType() const; string getBuidlerSimpleType() const; string getBuilderFullType() const; + string getBuilderInitValue() const; vector properties; vector classesDeclarations; @@ -46,7 +47,6 @@ private: NameResolver * nameResolver; void generateHeader (io::Printer * printer, bool isBuilder = false) const; - void generateConstructor (io::Printer * printer, bool isBuilder = false) const; void generateBuilder (io::Printer * printer) const; void generateBuildMethod (io::Printer * printer) const; void generateInitSection (io::Printer * printer) const; diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.cc b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.cc index 15287ee967b..4bb3bd8be6c 100644 --- a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.cc +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.cc @@ -19,15 +19,29 @@ string FieldGenerator::getInitValue() const { if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) { return getFullType() + "(0)"; } + if (getProtoType() == FieldDescriptor::TYPE_MESSAGE) { - return getBuilderFullType() + "().build()"; + ClassGenerator * cg = nameResolver->getClassGenerator(getSimpleType()); + // build list of arguments like 'field1: Type1, field2: Type2, ... ' + string argumentList = ""; + for (int i = 0; i < cg->properties.size(); ++i) { + argumentList += cg->properties[i]->simpleName + " = " + cg->properties[i]->getInitValue(); + if (i + 1 != cg->properties.size()) { + argumentList += ", "; + } + } + + return getBuilderFullType() + "(" + argumentList + ").build()"; } + if (getProtoType() == FieldDescriptor::TYPE_ENUM) { return getEnumFromIntConverter() + "(0)"; } return name_resolving::protobufTypeToInitValue(getProtoType()); } + + void FieldGenerator::generateCode(io::Printer *printer, bool isBuilder) const { map vars; vars["name"] = simpleName; @@ -38,11 +52,6 @@ void FieldGenerator::generateCode(io::Printer *printer, bool isBuilder) const { printer->Print(vars, "var $name$ : $field$\n"); - // make setter private - printer->Indent(); - printer->Print("private set\n"); - printer->Outdent(); - // generate setter for builder if (isBuilder) { generateSetter(printer); diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.h b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.h index be3d8687b1d..0d03e18b6c2 100644 --- a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.h +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.h @@ -73,6 +73,7 @@ public: */ string getInitValue() const; + /* Return string, that is suitable as suffix for corresponding IO methods in ProtoKot runtime. * Example: int64-field -> Int64 (readInt64() and writeInt64() methods exist in ProtoKot runtime) */ diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_file_generator.cc b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_file_generator.cc index 9ef67a067e7..9dcf0b15228 100644 --- a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_file_generator.cc +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_file_generator.cc @@ -37,8 +37,8 @@ bool FileGenerator::Generate(const FileDescriptor *file, const string ¶meter for (int i = 0; i < topLevelMessagesCount; ++i) { Descriptor const * descriptor = file->message_type(i); // TODO: think about order of initialization and cross-branches calls. If we don't allow such things, everythign is ok atm - nameResolver->addClass(descriptor->name(), ""); ClassGenerator * cgen = new ClassGenerator(descriptor, nameResolver); + nameResolver->addClass(descriptor->name(), /* parentName = */ "", cgen); classes.push_back(cgen); } diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_name_resolver.cc b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_name_resolver.cc index a4590b8f2d4..1d847e26831 100644 --- a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_name_resolver.cc +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_name_resolver.cc @@ -199,9 +199,12 @@ string protobufTypeToKotlinWireType(FieldDescriptor::Type type) { NameResolver::NameResolver() { names = map(); builders = map(); + generators = map(); } -void NameResolver::addClass(string simpleName, string parentName) { +void NameResolver::addClass(string simpleName, string parentName, ClassGenerator * classGenerator) { + generators[simpleName] = classGenerator; + if (parentName == "") { names[simpleName] = simpleName; builders[simpleName] = simpleName + ".Builder" + simpleName; @@ -221,6 +224,10 @@ string NameResolver::getBuilderName(string classSimpleName) { return builders[classSimpleName]; } +ClassGenerator * NameResolver::getClassGenerator(string simpleName) { + return generators[simpleName]; +} + } // namespace kotlin } // namespace compiler } // namespace protobuf diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_name_resolver.h b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_name_resolver.h index fac4149615b..99dcc9840a1 100644 --- a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_name_resolver.h +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_name_resolver.h @@ -9,6 +9,7 @@ #include #include #include "kotlin_field_generator.h" +#include "kotlin_class_generator.h" namespace google { namespace protobuf { @@ -22,12 +23,14 @@ class NameResolver { public: NameResolver(); - void addClass (string simpleName, string parentName); + void addClass (string simpleName, string parentName, ClassGenerator * classGenerator); string getClassName (string simpleName); string getBuilderName (string classSimpleName); + ClassGenerator * getClassGenerator (string simpleName); private: std::map names; std::map builders; + std::map generators; }; namespace name_resolving {