+++ title = "Kotlin Generated Code Guide" weight = 680 linkTitle = "Generated Code Guide" description = "Describes exactly what Kotlin code the protocol buffer compiler generates for any given protocol definition, in addition to the code generated for Java." type = "docs" +++ Any differences between proto2 and proto3 generated code are highlighted—note that these differences are in the generated code as described in this document, not the base message classes/interfaces, which are the same in both versions. You should read the [proto2 language guide](/programming-guides/proto2) and/or [proto3 language guide](/programming-guides/proto3) before reading this document. ## Compiler Invocation {#invocation} The protocol buffer compiler produces Kotlin code that builds on top of Java code. As a result, it must be invoked with two command-line flags, `--java_out=` and `--kotlin_out=`. The parameter to the `--java_out=` option is the directory where you want the compiler to write your Java output, and the same for the `--kotlin_out=`. For each `.proto` file input, the compiler creates a wrapper `.java` file containing a Java class which represents the `.proto` file itself. **Regardless** of whether or not your `.proto` file contains a line like the following: ```proto option java_multiple_files = true; ``` The compiler will create separate `.kt` files for each of the classes and factory methods which it will generate for each top-level message declared in the `.proto` file. The Java package name for each file is the same as that used by the generated Java code as described in the [Java generated code reference](/reference/java/java-generated#package). The output file is chosen by concatenating the parameter to `--kotlin_out=`, the package name (with periods [.] replaced with slashes [/]), and the suffix `Kt.kt` file name. So, for example, let's say you invoke the compiler as follows: ```shell protoc --proto_path=src --java_out=build/gen/java --kotlin_out=build/gen/kotlin src/foo.proto ``` If `foo.proto`'s Java package is `com.example` and it contains a message named `Bar`, then the protocol buffer compiler will generate the file `build/gen/kotlin/com/example/BarKt.kt`. The protocol buffer compiler will automatically create the `build/gen/kotlin/com` and `build/gen/kotlin/com/example` directories if needed. However, it will not create `build/gen/kotlin`, `build/gen`, or `build`; they must already exist. You can specify multiple `.proto` files in a single invocation; all output files will be generated at once. ## Messages {#message} Given a simple message declaration: ```proto message FooBar {} ``` The protocol buffer compiler generates—in addition to the generated Java code—an object called `FooBarKt`, as well as two top-level functions, having the following structure: ```kotlin object FooBarKt { class Dsl private constructor { ... } } inline fun fooBar(block: FooBarKt.Dsl.() -> Unit): FooBar inline fun FooBar.copy(block: FooBarKt.Dsl.() -> Unit): FooBar ``` ### Nested Types A message can be declared inside another message. For example: ```proto message Foo { message Bar { } } ``` In this case, the compiler nests the `BarKt` object and the `bar` factory method inside `FooKt`, though the `copy` method remains top-level: ```kotlin object FooKt { class Dsl { ... } object BarKt { class Dsl private constructor { ... } } inline fun bar(block: FooKt.BarKt.Dsl.() -> Unit): Foo.Bar } inline fun foo(block: FooKt.Dsl.() -> Unit): Foo inline fun Foo.copy(block: FooKt.Dsl.() -> Unit): Foo inline fun Foo.Bar.copy(block: FooKt.BarKt.Dsl.() -> Unit): Foo.Bar ``` ## Fields In addition to the methods described in the previous section, the protocol buffer compiler generates mutable properties in the DSL for each field defined within the message in the `.proto` file. (Kotlin already infers read-only properties on the message object from the getters generated by Java.) Note that properties always use camel-case naming, even if the field name in the `.proto` file uses lower-case with underscores ([as it should](/programming-guides/style)). The case-conversion works as follows: 1. For each underscore in the name, the underscore is removed, and the following letter is capitalized. 2. If the name will have a prefix attached (for example, "clear"), the first letter is capitalized. Otherwise, it is lower-cased. Thus, the field `foo_bar_baz` becomes `fooBarBaz`. In a few special cases in which a field name conflicts with reserved words in Kotlin or methods already defined in the protobuf library, an extra underscore is appended. For instance, the clearer for a field named `in` is `clearIn_()`. ### Singular Fields (proto2) For any of these field definitions: ```proto optional int32 foo = 1; required int32 foo = 1; ``` The compiler will generate the following accessors in the DSL: - `fun hasFoo(): Boolean`: Returns `true` if the field is set. - `var foo: Int`: The current value of the field. If the field is not set, returns the default value. - `fun clearFoo()`: Clears the value of the field. After calling this, `hasFoo()` will return `false` and `getFoo()` will return the default value. For other simple field types, the corresponding Java type is chosen according to the [scalar value types table](/programming-guides/proto2#scalar). For message and enum types, the value type is replaced with the message or enum class. As the message type is still defined in Java, unsigned types in the message are represented using the standard corresponding signed types in the DSL, for compatibility with Java and older versions of Kotlin. #### Embedded Message Fields Note that there is no special handling of submessages. For example, if you have a field ```proto optional Foo my_foo = 1; ``` you must write ```kotlin myFoo = foo { ... } ``` In general, this is because the compiler does not know whether `Foo` has a Kotlin DSL at all, or e.g. only has the Java APIs generated. This means that you do not have to wait for messages you depend on to add Kotlin code generation. ### Singular Fields (proto3) For this field definition: ```proto int32 foo = 1; ``` The compiler will generate the following property in the DSL: - `var foo: Int`: Returns the current value of the field. If the field is not set, returns the default value for the field's type. - `fun clearFoo()`: Clears the value of the field. After calling this, `getFoo()` will return the default value for the field's type. For other simple field types, the corresponding Java type is chosen according to the [scalar value types table](/programming-guides/proto2#scalar). For message and enum types, the value type is replaced with the message or enum class. As the message type is still defined in Java, unsigned types in the message are represented using the standard corresponding signed types in the DSL, for compatibility with Java and older versions of Kotlin. #### Embedded Message Fields For message field types, an additional accessor method is generated in the DSL: - `boolean hasFoo()`: Returns `true` if the field has been set. Note that there is no shortcut for setting a submessage based on a DSL. For example, if you have a field ```proto Foo my_foo = 1; ``` you must write ```kotlin myFoo = foo { ... } ``` In general, this is because the compiler does not know whether `Foo` has a Kotlin DSL at all, or e.g. only has the Java APIs generated. This means that you do not have to wait for messages you depend on to add Kotlin code generation. ### Repeated Fields {#repeated} For this field definition: ```proto repeated string foo = 1; ``` The compiler will generate the following members in the DSL: - `class FooProxy: DslProxy`, an unconstructable type used only in generics - `val fooList: DslList`, a read-only view of the list of current elements in the repeated field - `fun DslList.add(value: String)`, an extension function allowing elements to be added to the repeated field - `operator fun DslList.plusAssign(value: String)`, an alias for `add` - `fun DslList.addAll(values: Iterable)`, an extension function allowing an `Iterable` of elements to be added to the repeated field - `operator fun DslList.plusAssign(values: Iterable)`, an alias for `addAll` - `operator fun DslList.set(index: Int, value: String)`, an extension function setting the value of the element at the given zero-based inde - `fun DslList.clear()`, an extension function clearing the contents of the repeated field This unusual construction allows `fooList` to \"behave like\" a mutable list within the scope of the DSL, supporting only the methods supported by the underlying builder, while preventing mutability from \"escaping\" the DSL, which could cause confusing side effects. For other simple field types, the corresponding Java type is chosen according to the [scalar value types table](/programming-guides/proto2#scalar). For message and enum types, the type is the message or enum class. ### Oneof Fields For this oneof field definition: ```proto oneof oneof_name { int32 foo = 1; ... } ``` The compiler will generate the following accessor methods in the DSL: - `val oneofNameCase: OneofNameCase`: gets which, if any, of the `oneof_name` fields are set; see the [Java code reference](/reference/java/java-generated#oneof) for the return type - `fun hasFoo(): Boolean` (proto2 only): Returns `true` if the oneof case is `FOO`. - `val foo: Int`: Returns the current value of `oneof_name` if the oneof case is `FOO`. Otherwise, returns the default value of this field. For other simple field types, the corresponding Java type is chosen according to the [scalar value types table](/programming-guides/proto2#scalar). For message and enum types, the value type is replaced with the message or enum class. ### Map Fields For this map field definition: ```proto map weight = 1; ``` The compiler will generate the following members in the DSL class: - `class WeightProxy private constructor(): DslProxy()`, an unconstructable type used only in generics - `val weight: DslMap`, a read-only view of the current entries in the map field - `fun DslMap.put(key: Int, value: Int)`: add the entry to this map field - `operator fun DslMap.put(key: Int, value: Int)`: alias for `put` using operator syntax - `fun DslMap.remove(key: Int)`: removes the entry associated with `key`, if present - `fun DslMap.putAll(map: Map)`: adds all entries from the specified map to this map field, overwriting prior values for already present keys - `fun DslMap.clear()`: clears all entries from this map field ## Extensions (proto2 only) {#extension} Given a message with an extension range: ```proto message Foo { extensions 100 to 199; } ``` The protocol buffer compiler will add the following methods to `FooKt.Dsl`: - `operator fun get(extension: ExtensionLite): T`: gets the current value of the extension field in the DSL - `operator fun get(extension: ExtensionLite>): ExtensionList`: gets the current value of the repeated extension field in the DSL as a read-only `List` - `operator fun > set(extension: ExtensionLite)`: sets the current value of the extension field in the DSL (for `Comparable` field types) - `operator fun set(extension: ExtensionLite)`: sets the current value of the extension field in the DSL (for message field types) - `operator fun set(extension: ExtensionLite)`: sets the current value of the extension field in the DSL (for `bytes` fields) - `operator fun contains(extension: ExtensionLite): Boolean`: returns true if the extension field has a value - `fun clear(extension: ExtensionLite)`: clears the extension field - `fun ExtensionList.add(value: E)`: adds a value to the repeated extension field - `operator fun ExtensionList.plusAssign(value: E)`: alias for `add` using operator syntax - `operator fun ExtensionList.addAll(values: Iterable)`: adds multiple values to the repeated extension field - `operator fun ExtensionList.plusAssign(values: Iterable)`: alias for `addAll` using operator syntax - `operator fun ExtensionList.set(index: Int, value: E)`: sets the element of the repeated extension field at the specified index - `inline fun ExtensionList.clear()`: clears the elements of the repeated extension field The generics here are complex, but the effect is that `this[extension] = value` works for every extension type except repeated extensions, and repeated extensions have \"natural\" list syntax that works similarly to [non-extension repeated fields](#repeated). Given an extension definition: ```proto extend Foo { optional int32 bar = 123; } ``` Java generates the "extension identifier" `bar`, which is used to "key" extension operations above.