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 00000000000..e2de4608816 Binary files /dev/null and b/proto/compiler/google/src/google/protobuf/compiler/kotlin/protoc differ 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 }