From bee4c839d2daa81b10ea890b5c78f58074a0ec8d Mon Sep 17 00:00:00 2001 From: dsavvinov Date: Wed, 20 Jul 2016 15:33:11 +0300 Subject: [PATCH] Protobuf: refactored FieldGenerator interface heavily. Now it offers much more clearier interface for names getting (separating simple names from full-qualified names) --- .../google/protobuf/compiler/kotlin/Makefile | 9 +- .../google/protobuf/compiler/kotlin/protoc | Bin 0 -> 101128 bytes .../kotlin/src/UnreachableStateException.cc | 19 +++ .../kotlin/src/UnreachableStateException.h | 28 ++++ .../kotlin/src/kotlin_class_generator.cc | 74 ++++----- .../kotlin/src/kotlin_class_generator.h | 21 +-- .../kotlin/src/kotlin_field_generator.cc | 147 +++++++++++++----- .../kotlin/src/kotlin_field_generator.h | 64 +++++--- .../kotlin/src/kotlin_name_resolver.cc | 43 ++--- .../kotlin/src/kotlin_name_resolver.h | 6 +- proto/compiler/src/addressbook.kt | 86 +++++----- proto/compiler/src/nested-msg.kt | 58 +++---- 12 files changed, 322 insertions(+), 233 deletions(-) create mode 100755 proto/compiler/google/src/google/protobuf/compiler/kotlin/protoc create mode 100644 proto/compiler/google/src/google/protobuf/compiler/kotlin/src/UnreachableStateException.cc create mode 100644 proto/compiler/google/src/google/protobuf/compiler/kotlin/src/UnreachableStateException.h diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/Makefile b/proto/compiler/google/src/google/protobuf/compiler/kotlin/Makefile index 7998b70fe47..3dfd1f19b76 100644 --- a/proto/compiler/google/src/google/protobuf/compiler/kotlin/Makefile +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/Makefile @@ -23,9 +23,14 @@ $(BINDIR): mkdir -p $(BINDIR) clean: - rm -rf $(BINDIR) $(EXE) + rm -rf $(BINDIR) generate: ./protoc --kotlin_out=$$HOME/Downloads/carkot/proto/compiler/src ./test/addressbook.proto ./protoc --kotlin_out=$$HOME/Downloads/carkot/proto/compiler/src ./test/nested-msg.proto -.PHONY: clean all generate + +debug: + gdb --args ./protoc --kotlin_out=$$HOME/Downloads/carkot/proto/compiler/src ./test/addressbook.proto + gdb --args ./protoc --kotlin_out=$$HOME/Downloads/carkot/proto/compiler/src ./test/nested-msg.proto + +.PHONY: clean all generate debug diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/protoc b/proto/compiler/google/src/google/protobuf/compiler/kotlin/protoc new file mode 100755 index 0000000000000000000000000000000000000000..e2de4608816beabbcda5e50ff30c163d7465d2cf GIT binary patch literal 101128 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 o-Q0eQaCQUCw| literal 0 HcmV?d00001 diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/UnreachableStateException.cc b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/UnreachableStateException.cc new file mode 100644 index 00000000000..058c13efd4e --- /dev/null +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/UnreachableStateException.cc @@ -0,0 +1,19 @@ +// +// Created by user on 7/20/16. +// + +#include "UnreachableStateException.h" +namespace google { +namespace protobuf { +namespace compiler { +namespace kotlin { + +UnreachableStateException::UnreachableStateException(std::string const & what) + : std::logic_error(what) +{ } + +} // namespace kotlin +} // namespace compiler +} // namespace protobuf +} // namespace google + diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/UnreachableStateException.h b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/UnreachableStateException.h new file mode 100644 index 00000000000..a247fa9a1c8 --- /dev/null +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/UnreachableStateException.h @@ -0,0 +1,28 @@ +// +// Created by user on 7/20/16. +// + +#ifndef GOOGLE_UNREACHABLESTATEEXCEPTION_H +#define GOOGLE_UNREACHABLESTATEEXCEPTION_H + + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace kotlin { + +class UnreachableStateException : public std::logic_error { +public: + UnreachableStateException(std::string const & what); +}; + +} // namespace kotlin +} // namespace compiler +} // namespace protobuf +} // namespace google + + +#endif //GOOGLE_UNREACHABLESTATEEXCEPTION_H 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 0fb824de168..9c4cad56f86 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 @@ -80,8 +80,6 @@ ClassGenerator::ClassGenerator(Descriptor const *descriptor, NameResolver * name : descriptor(descriptor) , nameResolver(nameResolver) { - simpleName = descriptor->name(); - int field_count = descriptor->field_count(); for (int i = 0; i < field_count; ++i) { FieldDescriptor const * fieldDescriptor = descriptor->field(i); @@ -91,14 +89,14 @@ 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(), nameResolver->getClassName(simpleName)); + nameResolver->addClass(nestedClassDescriptor->name(), getFullType()); classesDeclarations.push_back(new ClassGenerator(nestedClassDescriptor, nameResolver)); } 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(), nameResolver->getClassName(simpleName)); + nameResolver->addClass(nestedEnumDescriptor->name(), getFullType()); enumsDeclaraions.push_back(new EnumGenerator(nestedEnumDescriptor)); } @@ -109,7 +107,7 @@ ClassGenerator::ClassGenerator(Descriptor const *descriptor, NameResolver * name */ std::sort(properties.begin(), properties.end(), [](FieldGenerator const * first, FieldGenerator const * second) { - return first->fieldNumber < second->fieldNumber; + return first->getFieldNumber() < second->getFieldNumber(); }); } @@ -137,7 +135,7 @@ void ClassGenerator::generateMergeMethods(io::Printer *printer) const { // mergeWith(other: Message) printer->Print("\n"); - vars["className"] = simpleName; + vars["className"] = getFullType(); printer->Print(vars, "fun mergeWith (other: $className$) {\n"); printer->Indent(); @@ -145,12 +143,12 @@ void ClassGenerator::generateMergeMethods(io::Printer *printer) const { vars["fieldName"] = properties[i]->simpleName; // concatenate repeated fields - if (properties[i]->modifier == FieldDescriptor::LABEL_REPEATED) { + if (properties[i]->getProtoLabel() == FieldDescriptor::LABEL_REPEATED) { printer->Print(vars, "$fieldName$.addAll(other.$fieldName$)\n"); } // Bytes type is handled separately - else if (properties[i]->protoType == FieldDescriptor::TYPE_BYTES) { + else if (properties[i]->getProtoType() == FieldDescriptor::TYPE_BYTES) { vars["initValue"] = properties[i]->getInitValue(); printer->Print(vars, "$fieldName$.plus(other.$fieldName$)\n"); } @@ -170,7 +168,7 @@ void ClassGenerator::generateMergeMethods(io::Printer *printer) const { printer->Print(vars, "fun mergeFrom (input: CodedInputStream) {\n"); printer->Indent(); - vars["builderName"] = nameResolver->getBuilderName(simpleName); + vars["builderName"] = getBuilderFullType(); printer->Print(vars, "val builder = $builderName$()\n"); printer->Print("mergeWith(builder.parseFrom(input).build())"); @@ -184,7 +182,7 @@ void ClassGenerator::generateSerializers(io::Printer *printer, bool isRead) cons vars["funName"]= isRead ? "readFrom" : "writeTo"; vars["stream"] = isRead ? "CodedInputStream" : "CodedOutputStream"; vars["arg"] = isRead ? "input" : "output"; - vars["returnType"] = isRead ? nameResolver->getBuilderName(simpleName) : "Unit"; + vars["returnType"] = isRead ? getBuilderFullType() : "Unit"; vars["maybeReturn"] = isRead ? "return this\n" : ""; // generate function header @@ -209,14 +207,14 @@ 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) { - argumentList += properties[i]->simpleName + ": " + properties[i]->fullType + " = " + properties[i]->getInitValue(); + argumentList += properties[i]->simpleName + ": " + properties[i]->getFullType() + " = " + properties[i]->getInitValue(); if (i + 1 != properties.size()) { argumentList += ", "; } } map vars; - vars["name"] = isBuilder? "Builder" + simpleName : simpleName; + vars["name"] = isBuilder? getBuidlerSimpleType() : getSimpleType(); vars["argumentList"] = argumentList; vars["maybePrivate"] = isBuilder? "" : " private"; printer->Print(vars, @@ -227,7 +225,7 @@ void ClassGenerator::generateHeader(io::Printer * printer, bool isBuilder) const void ClassGenerator::generateBuildMethod(io::Printer * printer) const { map vars; - vars["returnType"] = simpleName; + vars["returnType"] = getFullType(); printer->Print(vars, "fun build(): $returnType$ {\n"); printer->Indent(); @@ -266,7 +264,7 @@ void ClassGenerator::generateInitSection(io::Printer * printer) const { void ClassGenerator::generateParseMethods(io::Printer *printer) const { // parseFieldFrom(input: CodedInputStream): Boolean map vars; - vars["builderName"] = nameResolver->getBuilderName(simpleName); + vars["builderName"] = getBuilderFullType(); printer->Print("fun parseFieldFrom(input: CodedInputStream): Boolean {\n"); printer->Indent(); @@ -287,21 +285,21 @@ void ClassGenerator::generateParseMethods(io::Printer *printer) const { printer->Indent(); for (int i = 0; i < properties.size(); ++i) { - vars["fieldNumber"] = std::to_string(properties[i]->fieldNumber); + vars["fieldNumber"] = std::to_string(properties[i]->getFieldNumber()); vars["kotlinFunSuffix"] = properties[i]->getKotlinFunctionSuffix(); printer->Print(vars, "$fieldNumber$ -> "); // code for serialization arrays and messages consists of more than one line and needs enclosing brackets - if (properties[i]->modifier == FieldDescriptor::LABEL_REPEATED - || properties[i]->protoType == FieldDescriptor::TYPE_MESSAGE) { + if (properties[i]->getProtoLabel() == FieldDescriptor::LABEL_REPEATED + || properties[i]->getProtoType() == FieldDescriptor::TYPE_MESSAGE) { printer->Print("{\n"); printer->Indent(); } properties[i]->generateSerializationCode(printer, /* isRead = */ true, /* noTag = */ true); - if (properties[i]->modifier == FieldDescriptor::LABEL_REPEATED - || properties[i]->protoType == FieldDescriptor::TYPE_MESSAGE) { + if (properties[i]->getProtoLabel() == FieldDescriptor::LABEL_REPEATED + || properties[i]->getProtoType() == FieldDescriptor::TYPE_MESSAGE) { printer->Outdent(); printer->Print("}\n"); } @@ -339,36 +337,20 @@ void ClassGenerator::generateGetSizeMethod(io::Printer *printer) const { printer->Print("}\n"); } - - -//int ClassGenerator::getSizeWithoutHeader() { -// int size = 0; -// for (int i = 0; i < properties.size(); ++i) { -// size += properties[i].getSizeWithHeader(); -// } -// return 0; -//} - - -const string ClassModifier::getName() const { - string result = ""; - switch (type) { - case CLASS: - result = "class"; - break; - case INTERFACE: - result = "interface"; - break; - } - return result; +string ClassGenerator::getSimpleType() const { + return descriptor->name(); } -ClassModifier::ClassModifier(ClassModifier::Type type) - : type(type) -{ } +string ClassGenerator::getFullType() const { + return nameResolver->getClassName(getSimpleType()); +} -ClassModifier::ClassModifier() { - type = CLASS; +string ClassGenerator::getBuilderFullType() const { + return nameResolver->getBuilderName(getSimpleType()); +} + +string ClassGenerator::getBuidlerSimpleType() const { + return "Builder" + getSimpleType(); } 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 73ef7596150..b0d7f0dcc28 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 @@ -20,24 +20,13 @@ namespace kotlin { class FieldGenerator; // declared in "kotlin_file_generator.h" class NameResolver; // declared in "kotlin_name_resolver.h" -// wrapper for enum CLASS/INTERFACE with convenience method of getting name -class ClassModifier { -public: - enum Type { - CLASS, - INTERFACE - }; - ClassModifier(); - ClassModifier(Type type); - Type type; - - string const getName() const; -}; - class ClassGenerator { public: - string simpleName; - string fullName; + string getSimpleType() const; + string getFullType() const; + string getBuidlerSimpleType() const; + string getBuilderFullType() const; + vector properties; vector classesDeclarations; vector enumsDeclaraions; 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 e24cee2022e..91200759842 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 @@ -7,6 +7,7 @@ #include #include #include "kotlin_name_resolver.h" +#include "UnreachableStateException.h" #include namespace google { @@ -15,13 +16,22 @@ namespace compiler { namespace kotlin { string FieldGenerator::getInitValue() const { - return name_resolving::protobufTypeToInitValue(this); + if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) { + return "mutableListOf()"; + } + if (getProtoType() == FieldDescriptor::TYPE_MESSAGE) { + return getBuilderFullType() + "().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; - vars["field"] = name_resolving::protobufToKotlinField(descriptor); + vars["field"] = getFullType(); printer->Print(vars, "var $name$ : $field$\n"); // make setter private @@ -35,29 +45,25 @@ void FieldGenerator::generateCode(io::Printer *printer, bool isBuilder) const { } // generate additional methods for repeated fields - if (modifier == FieldDescriptor::LABEL_REPEATED) { + if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) { generateRepeatedMethods(printer, isBuilder); } } FieldGenerator::FieldGenerator(FieldDescriptor const * descriptor, ClassGenerator const * enclosingClass, NameResolver * nameResolver) : descriptor(descriptor) - , modifier(descriptor->label()) , enclosingClass(enclosingClass) - , simpleName(descriptor->name()) - , underlyingType(name_resolving::protobufToKotlinType(descriptor)) - , fullType(name_resolving::protobufToKotlinField(descriptor)) - , protoType(descriptor->type()) - , fieldNumber(descriptor->number()) , nameResolver(nameResolver) + , simpleName(descriptor->name()) + , protoLabel(descriptor->label()) { } // TODO: long, complicated and messy method. Refactor it ASAP void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead, bool noTag) const { map vars; - vars["type"] = name_resolving::protobufTypeToKotlinFunctionSuffix(descriptor->type()) + (noTag ? "NoTag" : ""); - vars["fieldNumber"] = std::to_string(fieldNumber); - vars["maybeFieldNumber"] = noTag ? "" : std::to_string(fieldNumber); + vars["type"] = getKotlinFunctionSuffix() + (noTag ? "NoTag" : ""); + vars["fieldNumber"] = std::to_string(getFieldNumber()); + vars["maybeFieldNumber"] = noTag ? "" : std::to_string(getFieldNumber()); vars["fieldName"] = simpleName; vars["arg"] = isRead ? "input" : "output"; vars["maybeComma"] = ", "; @@ -70,7 +76,7 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead * - Write length as int32 (note that tag shouldn't be added) * - Write all repeated elements via recursive call (again, without tags) */ - if (modifier == FieldDescriptor::LABEL_REPEATED) { + if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) { // tag if (isRead) { if (!noTag) { @@ -90,7 +96,7 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead removed as soon as target code will support inheritance and interfaces. (then writing CodedOutputStream.writeMessage will be possible). */ - FieldGenerator singleFieldGen = FieldGenerator(descriptor, enclosingClass, nameResolver); + FieldGenerator singleFieldGen = getUnderlyingTypeGenerator(); /* Another dirty hack here: create tmp variable of a given type and read it from input stream then add that tmp var into list. @@ -99,11 +105,11 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead to ArrayOutOfIndex errors. */ // TODO: stub here, resolve name properly! - vars["fieldType"] = underlyingType + ".Builder" + underlyingType; - vars["initValue"] = underlyingType + ".Builder" + underlyingType + "()"; - printer->Print(vars, "val tmp: $fieldType$ = $initValue$\n"); + vars["builderType"] = getUnderlyingTypeGenerator().getFullType(); + vars["initValue"] = getUnderlyingTypeGenerator().getInitValue(); + printer->Print(vars, "val tmp: $builderType$ = $initValue$\n"); singleFieldGen.simpleName = "tmp"; - singleFieldGen.modifier = FieldDescriptor::LABEL_OPTIONAL; + singleFieldGen.protoLabel = FieldDescriptor::LABEL_OPTIONAL; // Note that primitive types are packed by default in proto3, i.e. they are should be written without tag bool isPrimitive = descriptor->type() != FieldDescriptor::TYPE_BYTES && @@ -112,9 +118,9 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead descriptor->type() != FieldDescriptor::TYPE_ENUM; singleFieldGen.generateSerializationCode(printer, isRead, /* noTag = */ isPrimitive); - singleFieldGen.generateSizeEstimationCode(printer, "readSize"); // add size of current element to total size + singleFieldGen.generateSizeEstimationCode(printer, /* varName = */ "readSize"); // add size of current element to total size - printer->Print(vars, "$fieldName$.add(tmp.build())\n"); + printer->Print(vars, "$fieldName$.add(tmp)\n"); printer->Outdent(); printer->Print("}\n"); @@ -138,7 +144,7 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead // hack: see above FieldGenerator singleFieldGen = FieldGenerator(descriptor, enclosingClass, nameResolver); singleFieldGen.simpleName = "item"; - singleFieldGen.modifier = FieldDescriptor::LABEL_OPTIONAL; + singleFieldGen.protoLabel = FieldDescriptor::LABEL_OPTIONAL; // TODO: maybe refactor this in name_resolving or separate method at least // Note that primitive types are packed by default in proto3, i.e. they are should be written without tag @@ -167,7 +173,7 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead Example: output.writeEnum(42, enumField.ord) */ if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { - vars["converter"] = underlyingType + ".fromIntTo" + underlyingType; + vars["converter"] = getEnumFromIntConverter(); if (isRead) { printer->Print(vars, "$fieldName$ = $converter$(input.read$type$($maybeFieldNumber$))\n"); } @@ -185,7 +191,7 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead */ if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) { if (isRead) { - vars["fieldNumber"] = std::to_string(fieldNumber); + vars["fieldNumber"] = std::to_string(getFieldNumber()); vars["dollar"] = "$"; // read tag @@ -205,7 +211,7 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead "\") }\n"); } else { - vars["fieldNumber"] = std::to_string(fieldNumber); + vars["fieldNumber"] = std::to_string(getFieldNumber()); // write tag printer->Print(vars, "output.writeTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n"); @@ -233,8 +239,8 @@ void FieldGenerator::generateSetter(io::Printer *printer) const { map vars; vars["camelCaseName"] = name_resolving::makeFirstLetterUpper(simpleName); vars["fieldName"] = simpleName; - vars["builderName"] = nameResolver->getBuilderName(enclosingClass->simpleName); - vars["type"] = fullType; + vars["builderName"] = enclosingClass->getBuilderFullType(); + vars["type"] = getFullType(); printer->Print(vars, "fun set$camelCaseName$(value: $type$): $builderName$ {\n"); printer->Indent(); @@ -247,10 +253,10 @@ void FieldGenerator::generateSetter(io::Printer *printer) const { void FieldGenerator::generateRepeatedMethods(io::Printer * printer, bool isBuilder) const { map vars; - vars["elementType"] = underlyingType; + vars["elementType"] = getUnderlyingTypeGenerator().getSimpleType(); vars["arg"] = "value"; vars["fieldName"] = simpleName; - vars["builderName"] = nameResolver->getBuilderName(underlyingType); // TODO: call to non-existent field in map. + vars["builderName"] = enclosingClass->getBuilderFullType(); // TODO: call to non-existent field in map. // generate indexed setter for builders if (isBuilder) { @@ -292,21 +298,14 @@ string FieldGenerator::getKotlinFunctionSuffix() const { return name_resolving::protobufTypeToKotlinFunctionSuffix(descriptor->type()); } -string FieldGenerator::getUnderlyingTypeInitValue() const { - if (protoType == FieldDescriptor::TYPE_MESSAGE) { - return "Builder" + underlyingType + "().build()"; - } - return name_resolving::protobufTypeToInitValue(this); -} - void FieldGenerator::generateSizeEstimationCode(io::Printer *printer, string varName, bool noTag) const { map vars; vars["varName"] = varName; vars["fieldName"] = simpleName; - vars["fieldNumber"] = std::to_string(fieldNumber); + vars["fieldNumber"] = std::to_string(getFieldNumber()); // First of all, generate code for repeated fields - if (modifier == FieldDescriptor::LABEL_REPEATED) { + if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) { // We will need total byte size of array, because that size is itself a part of the message and // adds to total message size. // For the sake of hygiene, temporary variables are created in anonymous scope @@ -322,7 +321,7 @@ void FieldGenerator::generateSizeEstimationCode(io::Printer *printer, string var // hack: reuse generateSizeEstimationCode in the same manner as in generateSerializationCode FieldGenerator singleFieldGen = FieldGenerator(descriptor, enclosingClass, nameResolver); - singleFieldGen.modifier = FieldDescriptor::LABEL_OPTIONAL; + singleFieldGen.protoLabel = FieldDescriptor::LABEL_OPTIONAL; singleFieldGen.simpleName = "item"; singleFieldGen.generateSizeEstimationCode(printer, "arraySize"); @@ -348,7 +347,7 @@ void FieldGenerator::generateSizeEstimationCode(io::Printer *printer, string var // Then, call getSize recursively for nested messages // TODO: currently suboptimal repeatative calls getSize() are being made. We can optimize it later via caching calls to getSize() - if (protoType == FieldDescriptor::TYPE_MESSAGE) { + if (getProtoType() == FieldDescriptor::TYPE_MESSAGE) { // don't forget about tag and length annotation printer->Print(vars, "$varName$ += $fieldName$.getSize()" " + " @@ -360,18 +359,82 @@ void FieldGenerator::generateSizeEstimationCode(io::Printer *printer, string var } // Next, process enums as they should be casted to ints manually - if (protoType == FieldDescriptor::TYPE_ENUM) { - vars["enumName"] = fullType; + if (getProtoType() == FieldDescriptor::TYPE_ENUM) { printer->Print(vars, "$varName$ += WireFormat.getEnumSize($fieldNumber$, $fieldName$.ord)\n"); return; } // Finally, get size of all primitive types trivially via call to WireFormat in runtime - vars["kotlinSuffix"] = name_resolving::protobufTypeToKotlinFunctionSuffix(descriptor->type()); + vars["kotlinSuffix"] = getKotlinFunctionSuffix(); printer->Print(vars, "$varName$ += WireFormat.get$kotlinSuffix$Size($fieldNumber$, $fieldName$)\n"); return; } +FieldDescriptor::Label FieldGenerator::getProtoLabel() const { + return protoLabel; +} + +FieldDescriptor::Type FieldGenerator::getProtoType() const { + return descriptor->type(); +} + +int FieldGenerator::getFieldNumber() const { + return descriptor->number(); +} + + +string FieldGenerator::getSimpleType() const { + if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) { + return "MutableList <" + getUnderlyingTypeGenerator().getSimpleType() + ">"; + } + if (getProtoType() == FieldDescriptor::TYPE_MESSAGE) { + return descriptor->message_type()->name(); + } + if (getProtoType() == FieldDescriptor::TYPE_ENUM) { + return descriptor->enum_type()->name(); + } + return name_resolving::protobufToKotlinType(descriptor->type()); +} + +string FieldGenerator::getFullType() const { + if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) { + return "MutableList <" + getUnderlyingTypeGenerator().getFullType() + ">"; + } + if (getProtoType() == FieldDescriptor::TYPE_MESSAGE || + getProtoType() == FieldDescriptor::TYPE_ENUM) { + return nameResolver->getClassName(getSimpleType()); + } + return name_resolving::protobufToKotlinType(getProtoType()); +} + +string FieldGenerator::getBuilderFullType() const { + if (getProtoType() != FieldDescriptor::TYPE_MESSAGE) { + throw UnreachableStateException("Error: trying to get builder name for non-message field " + simpleName); + } + return nameResolver->getBuilderName(getSimpleType()); +} + +string FieldGenerator::getBuilderSimpleType() const { + if (getProtoType() != FieldDescriptor::TYPE_MESSAGE) { + throw UnreachableStateException("Error: trying to get builder name for non-message field " + simpleName); + } + return "Builder" + getSimpleType(); +} + +string FieldGenerator::getEnumFromIntConverter() const { + return getFullType() + ".fromIntTo" + getSimpleType(); +} + +FieldGenerator FieldGenerator::getUnderlyingTypeGenerator() const { + if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) { + FieldGenerator singleFieldGen = FieldGenerator(descriptor, enclosingClass, nameResolver); + singleFieldGen.protoLabel = FieldDescriptor::LABEL_OPTIONAL; + return singleFieldGen; + } + return *this; +} + + } // namespace kotlin } // namespace compiler } // namespace protobuf 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 cd721189ebd..b04629b34c3 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 @@ -27,32 +27,58 @@ private: void generateSetter(io::Printer * printer) const; void generateRepeatedMethods(io::Printer * printer, bool isBuilder) const; public: - FieldDescriptor::Label modifier; ClassGenerator const * enclosingClass; // class, in which that field is defined - string simpleName; - string underlyingType; // unwrapped type. - - /** - * Full type of field. - * fullType = Array for REPEATED fields - * fullType = underlyingType? for OPTIONAL fields - * fullType = underlyingType for all other cases - */ - string fullType; - string builderName; - string fullName; - string getInitValue() const; - string getUnderlyingTypeInitValue() const; - FieldDescriptor::Type protoType; - int fieldNumber; NameResolver * nameResolver; + string simpleName; + FieldDescriptor::Label protoLabel; // TODO: hack here - this field is used for some dark magic that allows us to drop generics from the generated code + + FieldDescriptor::Label getProtoLabel() const; + FieldDescriptor::Type getProtoType() const; + + /* Return declared tag number */ + int getFieldNumber() const; + + /* Returns instance of FieldGenerator, that generated underlying type for repeated fields. + * For non-repeated fields, returns `this` */ + FieldGenerator getUnderlyingTypeGenerator() const; + + /* For repeated fields, returns simple name of single element. + * For all other cases, returns simple name of field, which is the same as getType() + */ + + /* For repeated fields, return simple name of single element, wrapped into corresponding Kotlin array type + * Example: Array + * For other types, return simple name (without full-qualification for non-primitive types) of field's type + */ + string getSimpleType() const; + + string getBuilderSimpleType() const; + + /* Returns full=qualified name of builder if field type is user-defined message */ + string getBuilderFullType() const; + + /* Returns the same as getType(), but with full-qualification for non-primitive types if necessary. + * Example: Array + */ + string getFullType() const; + + /* Returns initial value of this field's type. + * Note that full qualification for non-primitive types will always used here. + */ + 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) + */ + string getKotlinFunctionSuffix() const; + + /* Return function name in enum namespace that converts from enum to Int */ + string getEnumFromIntConverter() const; void generateCode(io::Printer * printer, bool isBuilder) const; void generateSerializationCode(io::Printer * printer, bool isRead = false, bool noTag = false) const; void generateSizeEstimationCode(io::Printer * printer, string varName, bool noTag = false) const; FieldGenerator(FieldDescriptor const * descriptor, ClassGenerator const * enclosingClass, NameResolver * nameResolver); - string getKotlinFunctionSuffix() const; - }; } // namespace kotlin 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 6ab33327387..3b29043a6b5 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 @@ -5,7 +5,7 @@ #include "kotlin_name_resolver.h" #include "kotlin_field_generator.h" #include - +#include "UnreachableStateException.h" #include namespace google { @@ -33,8 +33,7 @@ string getKotlinOutputByProtoName(string protoName) { return justName + ".kt"; } -string protobufToKotlinType(FieldDescriptor const * descriptor) { - FieldDescriptor::Type type = descriptor->type(); +string protobufToKotlinType(FieldDescriptor::Type type) { switch(type) { case FieldDescriptor::TYPE_BOOL: return "Boolean"; @@ -43,7 +42,8 @@ string protobufToKotlinType(FieldDescriptor const * descriptor) { case FieldDescriptor::TYPE_DOUBLE: return "Double"; case FieldDescriptor::TYPE_ENUM: - return string(descriptor->enum_type()->name()); + throw UnreachableStateException + ("Error: mapping protobuf enum types to kotlin types should be resolved by field generator, not by protobufToKotlinType function"); case FieldDescriptor::TYPE_FIXED32: // we map uint32 into Int, storing top bit in sign bit return "Int"; @@ -57,7 +57,8 @@ string protobufToKotlinType(FieldDescriptor const * descriptor) { case FieldDescriptor::TYPE_INT64: return "Long"; case FieldDescriptor::TYPE_MESSAGE: - return string(descriptor->message_type()->name()); + throw UnreachableStateException + ("Error: mapping protobuf message types to kotlin types should be resolved by field generator, not by protobufToKotlinType function"); case FieldDescriptor::TYPE_SFIXED32: return "Int"; case FieldDescriptor::TYPE_SFIXED64: @@ -67,7 +68,7 @@ string protobufToKotlinType(FieldDescriptor const * descriptor) { case FieldDescriptor::TYPE_SINT64: return "Long"; case FieldDescriptor::TYPE_STRING: - return "kotlin.String"; + return "String"; case FieldDescriptor::TYPE_UINT32: return "Int"; // see notes for TYPE_FIXED32 case FieldDescriptor::TYPE_UINT64: @@ -75,30 +76,9 @@ string protobufToKotlinType(FieldDescriptor const * descriptor) { } } -string protobufToKotlinField(FieldDescriptor const * descriptor) { - FieldDescriptor::Label modifier = descriptor->label(); - string preamble = "", - postamble = ""; - switch (modifier) { - case FieldDescriptor::LABEL_REQUIRED: - break; - case FieldDescriptor::LABEL_OPTIONAL: - break; - case FieldDescriptor::LABEL_REPEATED: - preamble = "MutableList <"; - postamble = "> "; - break; - } - return preamble + protobufToKotlinType(descriptor) + postamble; -} // TODO: think about nested arrays -string protobufTypeToInitValue(FieldGenerator const * fieldGen) { - if (fieldGen->modifier == FieldDescriptor::LABEL_REPEATED) { - return "mutableListOf()"; - } - - FieldDescriptor::Type type = fieldGen->protoType; +string protobufTypeToInitValue(FieldDescriptor::Type type) { switch(type) { case FieldDescriptor::TYPE_BOOL: return "false"; @@ -106,9 +86,8 @@ string protobufTypeToInitValue(FieldGenerator const * fieldGen) { return "ByteArray(0)"; case FieldDescriptor::TYPE_DOUBLE: return "0.0"; - case FieldDescriptor::TYPE_ENUM: { - return fieldGen->nameResolver->getClassName(fieldGen->fullType) + ".fromIntTo" + fieldGen->fullType + "(0)"; // produce enum from 0, as demanded by Google - } + case FieldDescriptor::TYPE_ENUM: + throw UnreachableStateException("Error: getting init values of enums should be handled by FieldGenerator, not by protobufToInitValue"); case FieldDescriptor::TYPE_FIXED32: return "0"; case FieldDescriptor::TYPE_FIXED64: @@ -120,7 +99,7 @@ string protobufTypeToInitValue(FieldGenerator const * fieldGen) { case FieldDescriptor::TYPE_INT64: return "0L"; case FieldDescriptor::TYPE_MESSAGE: - return fieldGen->nameResolver->getBuilderName(fieldGen->fullType) + "().build()"; + throw UnreachableStateException("Error: getting init values of enums should be handled by FieldGenerator, not by protobufToInitValue"); case FieldDescriptor::TYPE_SFIXED32: return "0"; case FieldDescriptor::TYPE_SFIXED64: 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 25179993b40..93910c9b586 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 @@ -37,11 +37,9 @@ std::string getFileNameWithoutExtension(std::string fullName); std::string getKotlinOutputByProtoName(std::string protoName); -std::string protobufTypeToInitValue(FieldGenerator const * fieldGenerator); +std::string protobufTypeToInitValue(FieldDescriptor::Type type); -std::string protobufToKotlinField(FieldDescriptor const * descriptor); - -std::string protobufToKotlinType(FieldDescriptor const * descriptor); +std::string protobufToKotlinType(FieldDescriptor::Type type); /** * Converts one of protobuf wire types to corresponding Kotlin type with proper diff --git a/proto/compiler/src/addressbook.kt b/proto/compiler/src/addressbook.kt index 586aee2f031..6ea425f7226 100644 --- a/proto/compiler/src/addressbook.kt +++ b/proto/compiler/src/addressbook.kt @@ -1,14 +1,14 @@ -class Person private constructor (name: kotlin.String = "", id: Int = 0, email: kotlin.String = "", phones: MutableList = mutableListOf(), someBytes: ByteArray = ByteArray(0)) { - var name : kotlin.String +class Person private constructor (name: String = "", id: Int = 0, email: String = "", phones: MutableList = mutableListOf(), someBytes: ByteArray = ByteArray(0)) { + var name : String private set var id : Int private set - var email : kotlin.String + var email : String private set - var phones : MutableList + var phones : MutableList private set var someBytes : ByteArray @@ -38,11 +38,11 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email: } } } - class PhoneNumber private constructor (number: kotlin.String = "", type: PhoneType = Person.PhoneType.fromIntToPhoneType(0)) { - var number : kotlin.String + class PhoneNumber private constructor (number: String = "", type: Person.PhoneType = Person.PhoneType.fromIntToPhoneType(0)) { + var number : String private set - var type : PhoneType + var type : Person.PhoneType private set @@ -56,17 +56,17 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email: output.writeEnum (2, type.ord) } - class BuilderPhoneNumber constructor (number: kotlin.String = "", type: PhoneType = Person.PhoneType.fromIntToPhoneType(0)) { - var number : kotlin.String + class BuilderPhoneNumber constructor (number: String = "", type: Person.PhoneType = Person.PhoneType.fromIntToPhoneType(0)) { + var number : String private set - fun setNumber(value: kotlin.String): Person.PhoneNumber.BuilderPhoneNumber { + fun setNumber(value: String): Person.PhoneNumber.BuilderPhoneNumber { number = value return this } - var type : PhoneType + var type : Person.PhoneType private set - fun setType(value: PhoneType): Person.PhoneNumber.BuilderPhoneNumber { + fun setType(value: Person.PhoneType): Person.PhoneNumber.BuilderPhoneNumber { type = value return this } @@ -79,12 +79,12 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email: fun readFrom (input: CodedInputStream): Person.PhoneNumber.BuilderPhoneNumber { number = input.readString(1) - type = PhoneType.fromIntToPhoneType(input.readEnum(2)) + type = Person.PhoneType.fromIntToPhoneType(input.readEnum(2)) return this } - fun build(): PhoneNumber { - return PhoneNumber(number, type) + fun build(): Person.PhoneNumber { + return Person.PhoneNumber(number, type) } fun parseFieldFrom(input: CodedInputStream): Boolean { @@ -95,7 +95,7 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email: val wireType = WireFormat.getTagWireType(tag) when(fieldNumber) { 1 -> number = input.readStringNoTag() - 2 -> type = PhoneType.fromIntToPhoneType(input.readEnumNoTag()) + 2 -> type = Person.PhoneType.fromIntToPhoneType(input.readEnumNoTag()) } return true} fun parseFrom(input: CodedInputStream): Person.PhoneNumber.BuilderPhoneNumber { @@ -111,7 +111,7 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email: } - fun mergeWith (other: PhoneNumber) { + fun mergeWith (other: Person.PhoneNumber) { number = other.number type = other.type } @@ -152,10 +152,10 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email: output.writeBytes (5, someBytes) } - class BuilderPerson constructor (name: kotlin.String = "", id: Int = 0, email: kotlin.String = "", phones: MutableList = mutableListOf(), someBytes: ByteArray = ByteArray(0)) { - var name : kotlin.String + class BuilderPerson constructor (name: String = "", id: Int = 0, email: String = "", phones: MutableList = mutableListOf(), someBytes: ByteArray = ByteArray(0)) { + var name : String private set - fun setName(value: kotlin.String): Person.BuilderPerson { + fun setName(value: String): Person.BuilderPerson { name = value return this } @@ -167,28 +167,28 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email: return this } - var email : kotlin.String + var email : String private set - fun setEmail(value: kotlin.String): Person.BuilderPerson { + fun setEmail(value: String): Person.BuilderPerson { email = value return this } - var phones : MutableList + var phones : MutableList private set - fun setPhones(value: MutableList ): Person.BuilderPerson { + fun setPhones(value: MutableList ): Person.BuilderPerson { phones = value return this } - fun setPhoneNumber(index: Int, value: PhoneNumber): Person.PhoneNumber.BuilderPhoneNumber { + fun setPhoneNumber(index: Int, value: PhoneNumber): Person.BuilderPerson { phones[index] = value return this } - fun addPhoneNumber(value: PhoneNumber): Person.PhoneNumber.BuilderPhoneNumber { + fun addPhoneNumber(value: PhoneNumber): Person.BuilderPerson { phones.add(value) return this } - fun addAllPhoneNumber(value: Iterable): Person.PhoneNumber.BuilderPhoneNumber { + fun addAllPhoneNumber(value: Iterable): Person.BuilderPerson { for (item in value) { phones.add(item) } @@ -219,13 +219,13 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email: val expectedSize = input.readInt32NoTag() var readSize = 0 while(readSize != expectedSize) { - val tmp: PhoneNumber.BuilderPhoneNumber = PhoneNumber.BuilderPhoneNumber() + val tmp: Person.PhoneNumber = Person.PhoneNumber.BuilderPhoneNumber().build() input.readTag(4, WireType.LENGTH_DELIMITED) val expectedSize = input.readInt32NoTag() tmp.mergeFrom(input) if (expectedSize != tmp.getSize()) { throw InvalidProtocolBufferException ("Expected size ${expectedSize} got ${tmp.getSize()}") } readSize += tmp.getSize() + WireFormat.getTagSize(4, WireType.LENGTH_DELIMITED) + WireFormat.getVarint32Size(tmp.getSize()) - phones.add(tmp.build()) + phones.add(tmp) } someBytes = input.readBytes(5) return this @@ -249,13 +249,13 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email: val expectedSize = input.readInt32NoTag() var readSize = 0 while(readSize != expectedSize) { - val tmp: PhoneNumber.BuilderPhoneNumber = PhoneNumber.BuilderPhoneNumber() + val tmp: Person.PhoneNumber = Person.PhoneNumber.BuilderPhoneNumber().build() input.readTag(4, WireType.LENGTH_DELIMITED) val expectedSize = input.readInt32NoTag() tmp.mergeFrom(input) if (expectedSize != tmp.getSize()) { throw InvalidProtocolBufferException ("Expected size ${expectedSize} got ${tmp.getSize()}") } readSize += tmp.getSize() + WireFormat.getTagSize(4, WireType.LENGTH_DELIMITED) + WireFormat.getVarint32Size(tmp.getSize()) - phones.add(tmp.build()) + phones.add(tmp) } } 5 -> someBytes = input.readBytesNoTag() @@ -312,8 +312,8 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email: } -class AddressBook private constructor (people: MutableList = mutableListOf()) { - var people : MutableList +class AddressBook private constructor (people: MutableList = mutableListOf()) { + var people : MutableList private set @@ -341,22 +341,22 @@ class AddressBook private constructor (people: MutableList = mutableLi } } - class BuilderAddressBook constructor (people: MutableList = mutableListOf()) { - var people : MutableList + class BuilderAddressBook constructor (people: MutableList = mutableListOf()) { + var people : MutableList private set - fun setPeople(value: MutableList ): AddressBook.BuilderAddressBook { + fun setPeople(value: MutableList ): AddressBook.BuilderAddressBook { people = value return this } - fun setPerson(index: Int, value: Person): Person.BuilderPerson { + fun setPerson(index: Int, value: Person): AddressBook.BuilderAddressBook { people[index] = value return this } - fun addPerson(value: Person): Person.BuilderPerson { + fun addPerson(value: Person): AddressBook.BuilderAddressBook { people.add(value) return this } - fun addAllPerson(value: Iterable): Person.BuilderPerson { + fun addAllPerson(value: Iterable): AddressBook.BuilderAddressBook { for (item in value) { people.add(item) } @@ -373,13 +373,13 @@ class AddressBook private constructor (people: MutableList = mutableLi val expectedSize = input.readInt32NoTag() var readSize = 0 while(readSize != expectedSize) { - val tmp: Person.BuilderPerson = Person.BuilderPerson() + val tmp: Person = Person.BuilderPerson().build() input.readTag(1, WireType.LENGTH_DELIMITED) val expectedSize = input.readInt32NoTag() tmp.mergeFrom(input) if (expectedSize != tmp.getSize()) { throw InvalidProtocolBufferException ("Expected size ${expectedSize} got ${tmp.getSize()}") } readSize += tmp.getSize() + WireFormat.getTagSize(1, WireType.LENGTH_DELIMITED) + WireFormat.getVarint32Size(tmp.getSize()) - people.add(tmp.build()) + people.add(tmp) } return this } @@ -399,13 +399,13 @@ class AddressBook private constructor (people: MutableList = mutableLi val expectedSize = input.readInt32NoTag() var readSize = 0 while(readSize != expectedSize) { - val tmp: Person.BuilderPerson = Person.BuilderPerson() + val tmp: Person = Person.BuilderPerson().build() input.readTag(1, WireType.LENGTH_DELIMITED) val expectedSize = input.readInt32NoTag() tmp.mergeFrom(input) if (expectedSize != tmp.getSize()) { throw InvalidProtocolBufferException ("Expected size ${expectedSize} got ${tmp.getSize()}") } readSize += tmp.getSize() + WireFormat.getTagSize(1, WireType.LENGTH_DELIMITED) + WireFormat.getVarint32Size(tmp.getSize()) - people.add(tmp.build()) + people.add(tmp) } } } diff --git a/proto/compiler/src/nested-msg.kt b/proto/compiler/src/nested-msg.kt index 5659b2ff539..b17f6e407d7 100644 --- a/proto/compiler/src/nested-msg.kt +++ b/proto/compiler/src/nested-msg.kt @@ -1,29 +1,29 @@ -class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2().build()) { - var field1 : Level2 +class Level1 private constructor (field1: Level1.Level2 = Level1.Level2.BuilderLevel2().build()) { + var field1 : Level1.Level2 private set init { this.field1 = field1 } - class Level2 private constructor (field2: Level3 = Level1.Level2.Level3.BuilderLevel3().build()) { - var field2 : Level3 + class Level2 private constructor (field2: Level1.Level2.Level3 = Level1.Level2.Level3.BuilderLevel3().build()) { + var field2 : Level1.Level2.Level3 private set init { this.field2 = field2 } - class Level3 private constructor (field3: Level4 = Level1.Level2.Level3.Level4.BuilderLevel4().build()) { - var field3 : Level4 + class Level3 private constructor (field3: Level1.Level2.Level3.Level4 = Level1.Level2.Level3.Level4.BuilderLevel4().build()) { + var field3 : Level1.Level2.Level3.Level4 private set init { this.field3 = field3 } - class Level4 private constructor (field4: kotlin.String = "") { - var field4 : kotlin.String + class Level4 private constructor (field4: String = "") { + var field4 : String private set @@ -35,10 +35,10 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2() output.writeString (4, field4) } - class BuilderLevel4 constructor (field4: kotlin.String = "") { - var field4 : kotlin.String + class BuilderLevel4 constructor (field4: String = "") { + var field4 : String private set - fun setField4(value: kotlin.String): Level1.Level2.Level3.Level4.BuilderLevel4 { + fun setField4(value: String): Level1.Level2.Level3.Level4.BuilderLevel4 { field4 = value return this } @@ -53,8 +53,8 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2() return this } - fun build(): Level4 { - return Level4(field4) + fun build(): Level1.Level2.Level3.Level4 { + return Level1.Level2.Level3.Level4(field4) } fun parseFieldFrom(input: CodedInputStream): Boolean { @@ -79,7 +79,7 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2() } - fun mergeWith (other: Level4) { + fun mergeWith (other: Level1.Level2.Level3.Level4) { field4 = other.field4 } @@ -100,10 +100,10 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2() field3.writeTo(output) } - class BuilderLevel3 constructor (field3: Level4 = Level1.Level2.Level3.Level4.BuilderLevel4().build()) { - var field3 : Level4 + class BuilderLevel3 constructor (field3: Level1.Level2.Level3.Level4 = Level1.Level2.Level3.Level4.BuilderLevel4().build()) { + var field3 : Level1.Level2.Level3.Level4 private set - fun setField3(value: Level4): Level1.Level2.Level3.BuilderLevel3 { + fun setField3(value: Level1.Level2.Level3.Level4): Level1.Level2.Level3.BuilderLevel3 { field3 = value return this } @@ -121,8 +121,8 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2() return this } - fun build(): Level3 { - return Level3(field3) + fun build(): Level1.Level2.Level3 { + return Level1.Level2.Level3(field3) } fun parseFieldFrom(input: CodedInputStream): Boolean { @@ -152,7 +152,7 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2() } - fun mergeWith (other: Level3) { + fun mergeWith (other: Level1.Level2.Level3) { field3 = other.field3 } @@ -173,10 +173,10 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2() field2.writeTo(output) } - class BuilderLevel2 constructor (field2: Level3 = Level1.Level2.Level3.BuilderLevel3().build()) { - var field2 : Level3 + class BuilderLevel2 constructor (field2: Level1.Level2.Level3 = Level1.Level2.Level3.BuilderLevel3().build()) { + var field2 : Level1.Level2.Level3 private set - fun setField2(value: Level3): Level1.Level2.BuilderLevel2 { + fun setField2(value: Level1.Level2.Level3): Level1.Level2.BuilderLevel2 { field2 = value return this } @@ -194,8 +194,8 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2() return this } - fun build(): Level2 { - return Level2(field2) + fun build(): Level1.Level2 { + return Level1.Level2(field2) } fun parseFieldFrom(input: CodedInputStream): Boolean { @@ -225,7 +225,7 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2() } - fun mergeWith (other: Level2) { + fun mergeWith (other: Level1.Level2) { field2 = other.field2 } @@ -246,10 +246,10 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2() field1.writeTo(output) } - class BuilderLevel1 constructor (field1: Level2 = Level1.Level2.BuilderLevel2().build()) { - var field1 : Level2 + class BuilderLevel1 constructor (field1: Level1.Level2 = Level1.Level2.BuilderLevel2().build()) { + var field1 : Level1.Level2 private set - fun setField1(value: Level2): Level1.BuilderLevel1 { + fun setField1(value: Level1.Level2): Level1.BuilderLevel1 { field1 = value return this }