diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/protoc b/proto/compiler/google/src/google/protobuf/compiler/kotlin/protoc index e7560ccd23c..126ff029379 100755 Binary files a/proto/compiler/google/src/google/protobuf/compiler/kotlin/protoc and b/proto/compiler/google/src/google/protobuf/compiler/kotlin/protoc differ 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 06f324b8a3f..c1c63afb766 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 @@ -21,31 +21,33 @@ void ClassGenerator::generateCode(io::Printer *printer, bool isBuilder) const { generateHeader(printer, isBuilder); printer->Indent(); - /* - * Field generator should know if it is generating code for builder - * or for fair class to choose between 'val' and 'var'. - * Also note that fields should be declared before init section. - */ - + // Generate code for property declaration + printer->Print("//========== Properties ===========\n"); for (FieldGenerator *gen: properties) { gen->generateCode(printer, isBuilder); printer->Print("\n"); } // Generate field for errors code - printer->Print("\n"); - printer->Print("var errorCode: Int = 0\n"); + printer->Print("var errorCode: Int = 0\n\n"); - printer->Print("\n"); generateInitSection(printer); + printer->Print("\n"); + // enum declarations and nested classes declarations only for fair classes if (!isBuilder) { + if (enumsDeclaraions.size() > 0) { + printer->Print("//========== Nested enums declarations ===========\n"); + } for (EnumGenerator *gen: enumsDeclaraions) { gen->generateCode(printer); printer->Print("\n"); } + if (classesDeclarations.size() > 0) { + printer->Print("//========== Nested classes declarations ===========\n"); + } for (ClassGenerator *gen: classesDeclarations) { gen->generateCode(printer); printer->Print("\n"); @@ -53,30 +55,37 @@ void ClassGenerator::generateCode(io::Printer *printer, bool isBuilder) const { } // write serialization methods only for fair classes, read methods only for Builders) - printer->Print("\n"); + printer->Print("//========== Serialization methods ===========\n"); generateWriteToMethod(printer); + printer->Print("\n"); // builder, mergeFrom and only for fair classes if (!isBuilder) { - printer->Print("\n"); - generateBuilder(printer); - printer->Print("\n"); generateMergeMethods(printer); + printer->Print("\n"); } // build() and setters are only for builders if (isBuilder) { - printer->Print("\n"); + printer->Print("//========== Mutating methods ===========\n"); generateBuildMethod(printer); - printer->Print("\n"); + generateParseMethods(printer); + printer->Print("\n"); } // getSize() + printer->Print("//========== Size-related methods ===========\n"); generateGetSizeMethod(printer); + printer->Print("\n"); + if (!isBuilder) { + printer->Print("//========== Builder ===========\n"); + generateBuilder(printer); + printer->Print("\n"); + } printer->Outdent(); printer->Print("}\n"); } @@ -139,7 +148,6 @@ void ClassGenerator::generateMergeMethods(io::Printer *printer) const { map vars; // mergeWith(other: Message) - printer->Print("\n"); vars["className"] = getFullType(); printer->Print(vars, "fun mergeWith (other: $className$) {\n"); printer->Indent(); @@ -203,6 +211,7 @@ void ClassGenerator::generateWriteToMethod(io::Printer *printer) const { // generate code for serialization/deserialization of fields for (int i = 0; i < properties.size(); ++i) { properties[i]->generateSerializationCode(printer, /* isRead = */ false, /* noTag = */ false); + printer->Print("\n"); } printer->Outdent(); @@ -319,7 +328,7 @@ void ClassGenerator::generateParseMethods(io::Printer *printer) const { printer->Print("return true"); printer->Outdent(); printer->Print("}\n"); // parseFieldFrom body - + printer->Print("\n"); // ====== parseFromWithSize(input: CodedInputStream, expectedSize: Int) ========= printer->Print(vars, @@ -346,7 +355,7 @@ void ClassGenerator::generateParseMethods(io::Printer *printer) const { printer->Outdent(); // function body printer->Print("}\n"); - + printer->Print("\n"); // ======== parseFrom(input: CodedInputStream) ========= printer->Print(vars, @@ -375,7 +384,7 @@ void ClassGenerator::generateGetSizeMethod(io::Printer *printer) const { printer->Print("return size\n"); printer->Outdent(); printer->Print("}\n"); - + printer->Print("\n"); // getSizeNoTag(): Int printer->Print("fun getSizeNoTag(): Int {\n"); 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 a277c583cb8..15287ee967b 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 @@ -32,6 +32,10 @@ void FieldGenerator::generateCode(io::Printer *printer, bool isBuilder) const { map vars; vars["name"] = simpleName; vars["field"] = getFullType(); + vars["protoType"] = getProtoType(); + + generateComment(printer); + printer->Print(vars, "var $name$ : $field$\n"); // make setter private @@ -93,13 +97,19 @@ void FieldGenerator::generateSerializationForPacked(io::Printer *printer, bool i */ FieldGenerator singleFieldGen = getUnderlyingTypeGenerator(); singleFieldGen.simpleName = "singleElemSize"; + + printer->Print("\n"); singleFieldGen.generateSerializationCode(printer, isRead, /* noTag = */ true, /* isField = */ false); + printer->Print("\n"); printer->Print(vars, "val arraySize = expectedByteSize / singleElemSize\n"); // Allocate new array of estimated size printer->Print(vars, "val newArray = $arrayType$(arraySize)\n"); + // place declaration of new variable in anonymous scope for hygiene + printer->Print("run {\n"); + printer->Indent(); printer->Print("var i = 0\n"); printer->Print(vars, "while(i < arraySize) {\n"); printer->Indent(); @@ -113,7 +123,10 @@ void FieldGenerator::generateSerializationForPacked(io::Printer *printer, bool i printer->Print(vars, "$fieldName$[i] = tmp\n"); printer->Print("i += 1\n"); - printer->Outdent(); + printer->Outdent(); // while-loop + printer->Print("}\n"); + + printer->Outdent(); // anonymous scope printer->Print("}\n"); } else { @@ -129,10 +142,17 @@ void FieldGenerator::generateSerializationForPacked(io::Printer *printer, bool i // length printer->Print(vars, "var arrayByteSize = 0\n"); + + printer->Print("\n"); generateSizeEstimationCode(printer, "arrayByteSize", /* noTag = */ true, /* isField = */ false); printer->Print(vars, "output.writeInt32NoTag(arrayByteSize)\n"); + printer->Print("\n"); // all elements + // place declaration of new variable in anonymous scope for hygiene + printer->Print("run {\n"); + printer->Indent(); + printer->Print("var i = 0\n"); printer->Print(vars, "while (i < $fieldName$.size) {\n"); printer->Indent(); @@ -145,7 +165,11 @@ void FieldGenerator::generateSerializationForPacked(io::Printer *printer, bool i singleFieldGen.generateSerializationCode(printer, isRead, /* noTag = */ isPrimitive, /* isField = */ false); printer->Print(vars, "i += 1\n"); - printer->Outdent(); // for-loop + + printer->Outdent(); // while-loop + printer->Print("}\n"); + + printer->Outdent(); // anonymous scope printer->Print("}\n"); } } @@ -250,6 +274,9 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead vars["fieldName"] = simpleName; vars["initValue"] = getInitValue(); + if (isField) { + generateComment(printer); + } /* Try to generate syntax for serialization of repeated fields. * Note that it should be first check because of Google's FieldDescriptor structure */ @@ -376,7 +403,7 @@ void FieldGenerator::generateSizeEstimationCode(io::Printer *printer, string var singleFieldGen.generateSizeEstimationCode(printer, "arraySize", noTag, /* isField = */ false); printer->Print(vars, "i += 1\n"); - + printer->Outdent(); // for-loop printer->Print("}\n"); @@ -498,6 +525,17 @@ string FieldGenerator::getWireType() const { return name_resolving::protobufTypeToKotlinWireType(descriptor->type()); } +void FieldGenerator::generateComment(io::Printer *printer) const { + map vars; + + vars["repeated"] = descriptor->is_repeated() ? "repeated " : ""; + vars["declared_type"] = descriptor->type_name(); + vars["name"] = descriptor->name(); + vars["number"] = std::to_string(descriptor->number()); + + printer->Print(vars, "//$repeated$$declared_type$ $name$ = $number$\n"); +} + } // namespace kotlin } // namespace compiler 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 5f19f8ef045..be3d8687b1d 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 @@ -22,13 +22,12 @@ class NameResolver; // declared in kotlin_name_resolver.h class FieldGenerator { private: FieldDescriptor const * descriptor; - // TODO: refactor from field generator to some static utility namespace void generateSetter(io::Printer * printer) const; + void generateComment(io::Printer * printer) const; void generateRepeatedMethods(io::Printer * printer, bool isBuilder) const; void generateSerializationForPacked (io::Printer * printer, bool isRead, bool noTag, bool isField) const; - void generateSerializationForRepeated (io::Printer * printer, bool isRead, bool noTag, bool isField) const; void generateSerializationForEnums (io::Printer * printer, bool isRead, bool noTag, bool isField) const; void generateSerializationForMessages (io::Printer * printer, bool isRead, bool noTag, bool isField) const; void generateSerializationForPrimitives (io::Printer * printer, bool isRead, bool noTag, bool isField) const;