Copying in kotlin proto specific files

pull/8272/head
Deanna Garcia 4 years ago
parent 75d125b441
commit 4f829fbecd
  1. 9
      java/core/src/test/java/com/google/protobuf/kotlin/AndroidManifest.xml
  2. 248
      java/core/src/test/java/com/google/protobuf/kotlin/BUILD
  3. 98
      java/core/src/test/java/com/google/protobuf/kotlin/DslListTest.kt
  4. 164
      java/core/src/test/java/com/google/protobuf/kotlin/DslMapTest.kt
  5. 60
      java/core/src/test/java/com/google/protobuf/kotlin/ExtendableMessageExtensionsTest.kt
  6. 60
      java/core/src/test/java/com/google/protobuf/kotlin/ExtendableMessageLiteExtensionsTest.kt
  7. 125
      java/core/src/test/java/com/google/protobuf/kotlin/ExtensionListTest.kt
  8. 988
      java/core/src/test/java/com/google/protobuf/kotlin/Proto2LiteTest.kt
  9. 980
      java/core/src/test/java/com/google/protobuf/kotlin/Proto2Test.kt
  10. 335
      java/core/src/test/java/com/google/protobuf/kotlin/Proto3Test.kt
  11. 63
      java/core/src/test/java/com/google/protobuf/kotlin/evil_names_proto2.proto
  12. 77
      java/core/src/test/java/com/google/protobuf/kotlin/evil_names_proto3.proto
  13. 12
      java/core/src/test/java/com/google/protobuf/kotlin/multiple_files_proto3.proto
  14. 16
      java/core/src/test/java/com/google/protobuf/kotlin/test.proto
  15. 126
      src/google/protobuf/compiler/java/java_enum_field.cc
  16. 2
      src/google/protobuf/compiler/java/java_enum_field.h
  17. 126
      src/google/protobuf/compiler/java/java_enum_field_lite.cc
  18. 2
      src/google/protobuf/compiler/java/java_enum_field_lite.h
  19. 5
      src/google/protobuf/compiler/java/java_field.cc
  20. 2
      src/google/protobuf/compiler/java/java_field.h
  21. 47
      src/google/protobuf/compiler/java/java_file.cc
  22. 5
      src/google/protobuf/compiler/java/java_file.h
  23. 44
      src/google/protobuf/compiler/java/java_helpers.cc
  24. 4
      src/google/protobuf/compiler/java/java_helpers.h
  25. 130
      src/google/protobuf/compiler/java/java_kotlin_generator.cc
  26. 99
      src/google/protobuf/compiler/java/java_map_field.cc
  27. 1
      src/google/protobuf/compiler/java/java_map_field.h
  28. 99
      src/google/protobuf/compiler/java/java_map_field_lite.cc
  29. 1
      src/google/protobuf/compiler/java/java_map_field_lite.h
  30. 237
      src/google/protobuf/compiler/java/java_message.cc
  31. 7
      src/google/protobuf/compiler/java/java_message.h
  32. 124
      src/google/protobuf/compiler/java/java_message_field.cc
  33. 2
      src/google/protobuf/compiler/java/java_message_field.h
  34. 124
      src/google/protobuf/compiler/java/java_message_field_lite.cc
  35. 2
      src/google/protobuf/compiler/java/java_message_field_lite.h
  36. 236
      src/google/protobuf/compiler/java/java_message_lite.cc
  37. 4
      src/google/protobuf/compiler/java/java_message_lite.h
  38. 22
      src/google/protobuf/compiler/java/java_name_resolver.cc
  39. 2
      src/google/protobuf/compiler/java/java_name_resolver.h
  40. 125
      src/google/protobuf/compiler/java/java_primitive_field.cc
  41. 2
      src/google/protobuf/compiler/java/java_primitive_field.h
  42. 125
      src/google/protobuf/compiler/java/java_primitive_field_lite.cc
  43. 2
      src/google/protobuf/compiler/java/java_primitive_field_lite.h
  44. 134
      src/google/protobuf/compiler/java/java_string_field.cc
  45. 2
      src/google/protobuf/compiler/java/java_string_field.h
  46. 134
      src/google/protobuf/compiler/java/java_string_field_lite.cc
  47. 2
      src/google/protobuf/compiler/java/java_string_field_lite.h
  48. 20
      third_party/build_defs/BUILD
  49. 140
      third_party/build_defs/kt_jvm_proto_library.bzl
  50. 177
      third_party/build_defs/kt_jvm_proto_library.internal.bzl

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.google.protobuf.android"
android:installLocation="internalOnly"
>
<application>
</application>
</manifest>

@ -0,0 +1,248 @@
# Tests for the Kotlin proto runtime.
load("//tools/build_defs/android:rules.bzl", "android_binary")
load("//tools/build_defs/kotlin:rules.bzl", "kt_jvm_library")
load("//testing/build_defs:junit_test_suites.bzl", "junit_test_suites")
load(
"//third_party/protobuf/build_defs:kt_jvm_proto_library.bzl",
"kt_jvm_lite_proto_library",
"kt_jvm_proto_library",
)
proto_library(
name = "test_proto",
srcs = ["test.proto"],
)
java_proto_library(
name = "test_java_proto",
deps = [":test_proto"],
)
java_lite_proto_library(
name = "test_java_proto_lite",
deps = [":test_proto"],
)
kt_jvm_library(
name = "shared_tests",
srcs = [
"DslListTest.kt",
"DslMapTest.kt",
"ExtensionListTest.kt",
],
kotlincopts = ["-Xopt-in=kotlin.RequiresOptIn"],
deps = [
":test_java_proto_lite",
"//java/com/google/common/testing",
"//java/com/google/protobuf/kotlin",
"//java/com/google/protobuf/kotlin:only_for_use_in_proto_generated_code_its_generator_and_tests",
"//java/com/google/protobuf/kotlin:shared_runtime",
"//third_party/java/junit",
"//third_party/java/truth",
"//third_party/kotlin/kotlin:kotlin_test",
],
)
junit_test_suites(
name = "shared_test_suite",
sizes = ["small"],
suffix = "Shared",
deps = [":shared_tests"],
)
proto_library(
name = "evil_names_proto2",
srcs = ["evil_names_proto2.proto"],
)
proto_library(
name = "evil_names_proto3",
srcs = ["evil_names_proto3.proto"],
)
proto_library(
name = "multiple_files_proto3",
srcs = ["multiple_files_proto3.proto"],
)
kt_jvm_lite_proto_library(
name = "proto2_unittest_kt_jvm_proto_lite",
deps = [
":evil_names_proto2",
"//net/proto2/internal:unittest_lite_proto",
],
)
kt_jvm_proto_library(
name = "proto2_unittest_kt_jvm_proto",
deps = [
":evil_names_proto2",
"//net/proto2/internal:unittest_proto",
],
)
kt_jvm_lite_proto_library(
name = "proto3_unittest_kt_jvm_proto_lite",
deps = [
":evil_names_proto3",
":multiple_files_proto3",
"//net/proto2/internal:unittest_proto3",
],
)
kt_jvm_proto_library(
name = "proto3_unittest_kt_jvm_proto",
deps = [
":evil_names_proto3",
":multiple_files_proto3",
"//net/proto2/internal:unittest_proto3",
],
)
kt_jvm_library(
name = "proto2_lite_test",
srcs = ["Proto2LiteTest.kt"],
constraints = ["android"],
kotlincopts = [
"-language-version",
"1.3",
],
deps = [
":proto2_unittest_kt_jvm_proto_lite",
"//java/com/google/protobuf/kotlin:shared_runtime",
"//javatests/com/google/protobuf:test_util-android",
"//third_party/java/junit:junit-android",
"//third_party/java/truth:truth-android",
"//third_party/kotlin/kotlin:kotlin_test",
],
)
kt_jvm_library(
name = "proto2_test",
srcs = ["Proto2Test.kt"],
kotlincopts = [
"-language-version",
"1.3",
],
deps = [
"proto2_unittest_kt_jvm_proto",
"//java/com/google/protobuf/kotlin:shared_runtime",
"//javatests/com/google/protobuf:test_util",
"//net/proto2/internal:unittest_java_proto",
"//third_party/java/junit",
"//third_party/java/truth",
"//third_party/kotlin/kotlin:kotlin_test",
],
)
kt_jvm_library(
name = "proto3_lite_test",
srcs = ["Proto3Test.kt"],
kotlincopts = [
"-language-version",
"1.3",
],
deps = [
":proto3_unittest_kt_jvm_proto_lite",
"//java/com/google/protobuf/kotlin:shared_runtime",
"//net/proto2/internal:unittest_proto3_java_proto_lite",
"//third_party/java/junit",
"//third_party/java/truth",
"//third_party/kotlin/kotlin:kotlin_test",
],
)
kt_jvm_library(
name = "proto3_test",
srcs = ["Proto3Test.kt"],
kotlincopts = [
"-language-version",
"1.3",
],
deps = [
":proto3_unittest_kt_jvm_proto",
"//java/com/google/protobuf/kotlin:shared_runtime",
"//net/proto2/internal:unittest_proto3_java_proto",
"//third_party/java/junit",
"//third_party/java/truth",
"//third_party/kotlin/kotlin:kotlin_test",
],
)
junit_test_suites(
name = "proto2_lite_tests_junit",
sizes = ["small"],
suffix = "Proto2LiteGeneratedCode",
deps = [":proto2_lite_test"],
)
junit_test_suites(
name = "proto2_tests_junit",
sizes = ["small"],
suffix = "Proto2GeneratedCode",
deps = [":proto2_test"],
)
junit_test_suites(
name = "generated_proto3_lite",
sizes = ["small"],
suffix = "Proto3LiteGeneratedCode",
deps = ["proto3_lite_test"],
)
junit_test_suites(
name = "generated_full_protos",
sizes = ["small"],
suffix = "Proto3GeneratedCode",
deps = [":proto3_test"],
)
kt_jvm_library(
name = "lite_runtime_tests_lib",
srcs = ["ExtendableMessageLiteExtensionsTest.kt"],
constraints = ["android"],
deps = [
":test_java_proto_lite",
"//java/com/google/protobuf/kotlin:kotlin_lite",
"//third_party/java/junit:junit-android",
"//third_party/java/truth:truth-android",
],
)
junit_test_suites(
name = "lite_runtime_tests",
sizes = ["small"],
suffix = "LiteRuntime",
deps = [":lite_runtime_tests_lib"],
)
kt_jvm_library(
name = "full_runtime_tests_lib",
srcs = ["ExtendableMessageExtensionsTest.kt"],
deps = [
":test_java_proto",
"//java/com/google/protobuf/kotlin",
"//third_party/java/junit",
"//third_party/java/truth",
],
)
junit_test_suites(
name = "full_runtime_tests",
sizes = ["small"],
suffix = "FullRuntime",
deps = [":full_runtime_tests_lib"],
)
# Generate a binary with AppReduce run on it, to verify no choking. The proto runtime includes
# kt_proto.pgcfg, which enforces that the DSLs are stripped out, so we just want to make sure
# that's run.
android_binary(
name = "Proto2LiteTestBinary",
manifest = "AndroidManifest.xml",
proguard_specs = [
"//java/com/google/android/apps/common/proguard:base.pgcfg",
"//java/com/google/android/apps/common/proguard:dev_optimize.pgcfg",
],
deps = [":proto2_lite_test"],
)

@ -0,0 +1,98 @@
package com.google.protobuf.kotlin
import com.google.common.testing.EqualsTester
import com.google.common.truth.Truth.assertThat
import kotlin.test.assertFailsWith
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
/** Tests for [DslList]. */
@RunWith(JUnit4::class)
@OptIn(OnlyForUseByGeneratedProtoCode::class)
class DslListTest {
class DummyProxy private constructor() : DslProxy()
@Test
fun matchesList() {
assertThat(DslList<Int, DummyProxy>(listOf(1, 2, 3))).containsExactly(1, 2, 3).inOrder()
}
@Test
fun reflectsChangesInList() {
val mutableList = mutableListOf(1, 2, 3)
val dslList = DslList<Int, DummyProxy>(mutableList)
mutableList.add(4)
assertThat(dslList).containsExactly(1, 2, 3, 4).inOrder()
}
@Test
fun dslListIsNotMutable() {
val dslList = DslList<Int, DummyProxy>(mutableListOf(1, 2, 3))
assertThat(dslList is MutableList<*>).isFalse()
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun dslListIsNotEvenSecretlyMutable() {
val dslList = DslList<Int, DummyProxy>(mutableListOf(1, 2, 3))
val dslListAsJavaUtil = dslList as java.util.List<Int>
assertFailsWith<UnsupportedOperationException> {
dslListAsJavaUtil.add(4)
}
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun dslList_IteratorIsNotEvenSecretlyMutable() {
val dslList = DslList<Int, DummyProxy>(mutableListOf(1, 2, 3))
val iterator = dslList.iterator() as java.util.Iterator<Int>
iterator.next()
assertFailsWith<UnsupportedOperationException> {
iterator.remove()
}
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun dslList_ListIteratorIsNotEvenSecretlyMutable() {
val dslList = DslList<Int, DummyProxy>(mutableListOf(1, 2, 3))
val iterator = dslList.listIterator() as java.util.ListIterator<Int>
iterator.next()
assertFailsWith<UnsupportedOperationException> {
iterator.remove()
}
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun dslList_ListIteratorIndexIsNotEvenSecretlyMutable() {
val dslList = DslList<Int, DummyProxy>(mutableListOf(1, 2, 3))
val iterator = dslList.listIterator(1) as java.util.ListIterator<Int>
iterator.next()
assertFailsWith<UnsupportedOperationException> {
iterator.remove()
}
}
@Test
fun expectedToString() {
assertThat(DslList<Int, DummyProxy>(listOf(1, 2)).toString()).isEqualTo("[1, 2]")
}
@Test
fun equality() {
EqualsTester()
.addEqualityGroup(DslList<Int, DummyProxy>(listOf(1, 2)), listOf(1, 2))
.addEqualityGroup(DslList<Int, DummyProxy>(listOf(2, 2)), listOf(2, 2))
.addEqualityGroup(
DslList<Int, DummyProxy>(emptyList()),
DslList<String, DummyProxy>(emptyList()),
emptyList<Int>()
)
.testEquals()
}
}

@ -0,0 +1,164 @@
package com.google.protobuf.kotlin
import com.google.common.testing.EqualsTester
import com.google.common.truth.Truth.assertThat
import kotlin.test.assertFailsWith
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@RunWith(JUnit4::class)
@OptIn(OnlyForUseByGeneratedProtoCode::class)
class DslMapTest {
class DummyProxy private constructor() : DslProxy()
@Test
fun matchesMap() {
assertThat(DslMap<Int, Int, DummyProxy>(mapOf(1 to -1, 2 to -2)))
.containsExactly(1, -1, 2, -2)
}
@Test
fun reflectsChangesInMap() {
val mutableMap = mutableMapOf(1 to -1, 2 to -2)
val dslMap = DslMap<Int, Int, DummyProxy>(mutableMap)
mutableMap[3] = -3
assertThat(dslMap).containsExactly(1, -1, 2, -2, 3, -3).inOrder()
}
@Test
fun dslMapIsNotMutable() {
val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
assertThat(dslMap is MutableMap<*, *>).isFalse()
}
@Test
fun dslMapKeysAreNotMutable() {
val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
assertThat(dslMap.keys is MutableSet<*>).isFalse()
}
@Test
fun dslMapValuesAreNotMutable() {
val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
assertThat(dslMap.values is MutableSet<*>).isFalse()
}
@Test
fun dslMapEntriesAreNotMutable() {
val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
assertThat(dslMap.entries is MutableSet<*>).isFalse()
}
@Test
fun dslMapEntryObjectsAreNotMutable() {
val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
assertThat(dslMap.entries.single() is MutableMap.MutableEntry<*, *>).isFalse()
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun dslMapIsNotEvenSecretlyMutable() {
val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
val dslMapAsJavaUtilMap = dslMap as java.util.Map<Int, Int>
assertFailsWith<UnsupportedOperationException> {
dslMapAsJavaUtilMap.put(2, -2)
}
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun dslMapKeysAreNotEvenSecretlyMutable() {
val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
val dslMapKeysAsJavaUtilSet = dslMap.keys as java.util.Set<Int>
assertFailsWith<UnsupportedOperationException> {
dslMapKeysAsJavaUtilSet.remove(1)
}
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun dslMapKeysIteratorIsNotEvenSecretlyMutable() {
val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
val dslMapKeysAsJavaUtilSet = dslMap.keys as java.util.Set<Int>
val itr = dslMapKeysAsJavaUtilSet.iterator()
itr.next()
assertFailsWith<UnsupportedOperationException> {
itr.remove()
}
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun dslMapValuesAreNotEvenSecretlyMutable() {
val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
val dslMapValuesAsJavaUtilCollection = dslMap.values as java.util.Collection<Int>
assertFailsWith<UnsupportedOperationException> {
dslMapValuesAsJavaUtilCollection.remove(1)
}
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun dslMapValuesIteratorIsNotEvenSecretlyMutable() {
val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
val dslMapValuesAsJavaUtilCollection = dslMap.values as java.util.Collection<Int>
val itr = dslMapValuesAsJavaUtilCollection.iterator()
itr.next()
assertFailsWith<UnsupportedOperationException> {
itr.remove()
}
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun dslMapEntriesAreNotEvenSecretlyMutable() {
val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
val dslMapEntriesAsJavaUtilSet = dslMap.entries as java.util.Set<Map.Entry<Int, Int>>
val entry = dslMap.entries.single()
assertFailsWith<UnsupportedOperationException> {
dslMapEntriesAsJavaUtilSet.remove(entry)
}
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun dslMapEntriesIteratorIsNotEvenSecretlyMutable() {
val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
val dslMapEntriesAsJavaUtilSet = dslMap.entries as java.util.Set<Map.Entry<Int, Int>>
val itr = dslMapEntriesAsJavaUtilSet.iterator()
itr.next()
assertFailsWith<UnsupportedOperationException> {
itr.remove()
}
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun dslMapEntryObjectsAreNotEvenSecretlyMutable() {
val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
val dslMapEntryAsJavaUtilMapEntry = dslMap.entries.single() as java.util.Map.Entry<Int, Int>
assertFailsWith<UnsupportedOperationException> {
dslMapEntryAsJavaUtilMapEntry.value = 2
}
}
@Test
fun expectedToString() {
assertThat(DslMap<Int, Int, DummyProxy>(mapOf(1 to 2, 2 to 3)).toString())
.isEqualTo("{1=2, 2=3}")
}
@Test
fun equality() {
EqualsTester()
.addEqualityGroup(DslMap<Int, Int, DummyProxy>(mapOf(1 to 2, 2 to 3)), mapOf(1 to 2, 2 to 3))
.addEqualityGroup(DslMap<Int, Int, DummyProxy>(mapOf(1 to 3, 2 to 3)), mapOf(1 to 3, 2 to 3))
.addEqualityGroup(
DslMap<Int, Int, DummyProxy>(emptyMap()),
DslMap<String, String, DummyProxy>(emptyMap()),
emptyMap<Int, Int>()
)
.testEquals()
}
}

@ -0,0 +1,60 @@
package com.google.protobuf.kotlin
import com.google.common.truth.Truth.assertThat
import com.google.protobuf.kotlin.test.ExampleExtensibleMessage
import com.google.protobuf.kotlin.test.Test as TestProto
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@RunWith(JUnit4::class)
class ExtendableMessageExtensionsTest {
@Test
fun setOnBuilder() {
val builder = ExampleExtensibleMessage.newBuilder()
builder[TestProto.int32Extension] = 5
assertThat(builder.build().getExtension(TestProto.int32Extension)).isEqualTo(5)
}
@Test
fun getOnBuilder() {
val builder = ExampleExtensibleMessage.newBuilder()
.setExtension(TestProto.int32Extension, 6)
assertThat(builder[TestProto.int32Extension]).isEqualTo(6)
}
@Test
fun getOnMessage() {
val message = ExampleExtensibleMessage.newBuilder()
.setExtension(TestProto.int32Extension, 6)
.build()
assertThat(message[TestProto.int32Extension]).isEqualTo(6)
}
@Test
fun containsPositiveOnMessage() {
val message = ExampleExtensibleMessage.newBuilder()
.setExtension(TestProto.int32Extension, 6)
.build()
assertThat(TestProto.int32Extension in message).isTrue()
}
@Test
fun containsPositiveOnBuilder() {
val builder = ExampleExtensibleMessage.newBuilder()
.setExtension(TestProto.int32Extension, 6)
assertThat(TestProto.int32Extension in builder).isTrue()
}
@Test
fun containsNegativeOnMessage() {
val message = ExampleExtensibleMessage.newBuilder().build()
assertThat(TestProto.int32Extension in message).isFalse()
}
@Test
fun containsNegativeOnBuilder() {
val builder = ExampleExtensibleMessage.newBuilder()
assertThat(TestProto.int32Extension in builder).isFalse()
}
}

@ -0,0 +1,60 @@
package com.google.protobuf.kotlin
import com.google.common.truth.Truth.assertThat
import com.google.protobuf.kotlin.test.ExampleExtensibleMessage
import com.google.protobuf.kotlin.test.Test as TestProto
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@RunWith(JUnit4::class)
class ExtendableMessageLiteExtensionsTest {
@Test
fun setOnBuilder() {
val builder = ExampleExtensibleMessage.newBuilder()
builder[TestProto.int32Extension] = 5
assertThat(builder.build().getExtension(TestProto.int32Extension)).isEqualTo(5)
}
@Test
fun getOnBuilder() {
val builder = ExampleExtensibleMessage.newBuilder()
.setExtension(TestProto.int32Extension, 6)
assertThat(builder[TestProto.int32Extension]).isEqualTo(6)
}
@Test
fun getOnMessage() {
val message = ExampleExtensibleMessage.newBuilder()
.setExtension(TestProto.int32Extension, 6)
.build()
assertThat(message[TestProto.int32Extension]).isEqualTo(6)
}
@Test
fun containsPositiveOnMessage() {
val message = ExampleExtensibleMessage.newBuilder()
.setExtension(TestProto.int32Extension, 6)
.build()
assertThat(TestProto.int32Extension in message).isTrue()
}
@Test
fun containsPositiveOnBuilder() {
val builder = ExampleExtensibleMessage.newBuilder()
.setExtension(TestProto.int32Extension, 6)
assertThat(TestProto.int32Extension in builder).isTrue()
}
@Test
fun containsNegativeOnMessage() {
val message = ExampleExtensibleMessage.newBuilder().build()
assertThat(TestProto.int32Extension in message).isFalse()
}
@Test
fun containsNegativeOnBuilder() {
val builder = ExampleExtensibleMessage.newBuilder()
assertThat(TestProto.int32Extension in builder).isFalse()
}
}

@ -0,0 +1,125 @@
package com.google.protobuf.kotlin
import com.google.common.testing.EqualsTester
import com.google.common.truth.Truth.assertThat
import com.google.protobuf.kotlin.test.ExampleExtensibleMessage
import com.google.protobuf.kotlin.test.Test as TestProto
import kotlin.test.assertFailsWith
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
/** Tests for [DslList]. */
@RunWith(JUnit4::class)
@OptIn(OnlyForUseByGeneratedProtoCode::class)
class ExtensionListTest {
class DummyProxy private constructor() : DslProxy()
@Test
fun matchesList() {
assertThat(
ExtensionList<Int, ExampleExtensibleMessage>(
TestProto.repeatedExtension, listOf(1, 2, 3)
)
).containsExactly(1, 2, 3).inOrder()
}
@Test
fun reflectsChangesInList() {
val mutableList = mutableListOf(1, 2, 3)
val extensionList = ExtensionList<Int, ExampleExtensibleMessage>(
TestProto.repeatedExtension, mutableList
)
mutableList.add(4)
assertThat(extensionList).containsExactly(1, 2, 3, 4).inOrder()
}
@Test
fun extensionListIsNotMutable() {
val extensionList = ExtensionList<Int, ExampleExtensibleMessage>(
TestProto.repeatedExtension, mutableListOf(1, 2, 3)
)
assertThat(extensionList is MutableList<*>).isFalse()
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun extensionListIsNotEvenSecretlyMutable() {
val extensionList = ExtensionList<Int, ExampleExtensibleMessage>(
TestProto.repeatedExtension, mutableListOf(1, 2, 3)
)
val extensionListAsJavaUtil = extensionList as java.util.List<Int>
assertFailsWith<UnsupportedOperationException> {
extensionListAsJavaUtil.add(4)
}
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun extensionList_IteratorIsNotEvenSecretlyMutable() {
val extensionList = ExtensionList<Int, ExampleExtensibleMessage>(
TestProto.repeatedExtension, mutableListOf(1, 2, 3)
)
val iterator = extensionList.iterator() as java.util.Iterator<Int>
iterator.next()
assertFailsWith<UnsupportedOperationException> {
iterator.remove()
}
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun extensionList_ListIteratorIsNotEvenSecretlyMutable() {
val extensionList = ExtensionList<Int, ExampleExtensibleMessage>(
TestProto.repeatedExtension, mutableListOf(1, 2, 3)
)
val iterator = extensionList.listIterator() as java.util.ListIterator<Int>
iterator.next()
assertFailsWith<UnsupportedOperationException> {
iterator.remove()
}
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@Test
fun extensionList_ListIteratorIndexIsNotEvenSecretlyMutable() {
val extensionList = ExtensionList<Int, ExampleExtensibleMessage>(
TestProto.repeatedExtension, mutableListOf(1, 2, 3)
)
val iterator = extensionList.listIterator(1) as java.util.ListIterator<Int>
iterator.next()
assertFailsWith<UnsupportedOperationException> {
iterator.remove()
}
}
@Test
fun expectedToString() {
assertThat(
ExtensionList<Int, ExampleExtensibleMessage>(TestProto.repeatedExtension, listOf(1, 2))
.toString()
).isEqualTo("[1, 2]")
}
@Test
fun equality() {
EqualsTester()
.addEqualityGroup(
ExtensionList<Int, ExampleExtensibleMessage>(TestProto.repeatedExtension, listOf(1, 2)),
ExtensionList<Int, ExampleExtensibleMessage>(TestProto.differentExtension, listOf(1, 2)),
listOf(1, 2)
)
.addEqualityGroup(
ExtensionList<Int, ExampleExtensibleMessage>(TestProto.repeatedExtension, listOf(2, 2)),
listOf(2, 2)
)
.addEqualityGroup(
ExtensionList<Int, ExampleExtensibleMessage>(TestProto.repeatedExtension, emptyList()),
emptyList<Int>()
)
.testEquals()
}
}

@ -0,0 +1,988 @@
package com.google.protobuf.kotlin
import com.google.common.truth.Truth.assertThat
import com.google.protobuf.TestAllTypesLiteKt
import com.google.protobuf.TestAllTypesLiteKt.nestedMessage
import com.google.protobuf.TestUtilLite
import com.google.protobuf.TestUtilLite.toBytes
import com.google.protobuf.UnittestImportLite.ImportEnumLite
import com.google.protobuf.UnittestImportLite.ImportMessageLite
import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite
import com.google.protobuf.UnittestLite
import com.google.protobuf.UnittestLite.ForeignEnumLite
import com.google.protobuf.UnittestLite.TestAllTypesLite
import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedEnum
import com.google.protobuf.UnittestLite.TestEmptyMessageLite
import com.google.protobuf.UnittestLite.TestEmptyMessageWithExtensionsLite
import com.google.protobuf.copy
import com.google.protobuf.foreignMessageLite
import com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.EvilNamesProto2
import com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.HardKeywordsAllTypes
import com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.Interface
import com.google.protobuf.kotlin.generator.HardKeywordsAllTypesKt
import com.google.protobuf.kotlin.generator.evilNamesProto2
import com.google.protobuf.kotlin.generator.hardKeywordsAllTypes
import com.google.protobuf.kotlin.generator.interface_
import com.google.protobuf.optionalGroupExtensionLite
import com.google.protobuf.repeatedGroupExtensionLite
import com.google.protobuf.testAllExtensionsLite
import com.google.protobuf.testAllTypesLite
import com.google.protobuf.testEmptyMessageLite
import com.google.protobuf.testEmptyMessageWithExtensionsLite
import com.google.protos.proto2_unittest.MapLiteUnittest.MapEnumLite
import com.google.protos.proto2_unittest.MapLiteUnittest.TestMapLite
import com.google.protos.proto2_unittest.testMapLite
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@RunWith(JUnit4::class)
class Proto2LiteTest {
@Test
fun testSetters() {
assertThat(
testAllTypesLite {
optionalInt32 = 101
optionalInt64 = 102
optionalUint32 = 103
optionalUint64 = 104
optionalSint32 = 105
optionalSint64 = 106
optionalFixed32 = 107
optionalFixed64 = 108
optionalSfixed32 = 109
optionalSfixed64 = 110
optionalFloat = 111.0f
optionalDouble = 112.0
optionalBool = true
optionalString = "115"
optionalBytes = toBytes("116")
optionalGroup =
TestAllTypesLiteKt.optionalGroup { a = 117 }
optionalNestedMessage = nestedMessage { bb = 118 }
optionalForeignMessage =
foreignMessageLite { c = 119 }
optionalImportMessage =
ImportMessageLite.newBuilder().setD(120).build()
optionalPublicImportMessage =
PublicImportMessageLite.newBuilder().setE(126).build()
optionalLazyMessage = nestedMessage { bb = 127 }
optionalNestedEnum = NestedEnum.BAZ
optionalForeignEnum = ForeignEnumLite.FOREIGN_LITE_BAZ
optionalImportEnum = ImportEnumLite.IMPORT_LITE_BAZ
optionalStringPiece = "124"
optionalCord = "125"
repeatedInt32.add(201)
repeatedInt64.add(202)
repeatedUint32.add(203)
repeatedUint64.add(204)
repeatedSint32.add(205)
repeatedSint64.add(206)
repeatedFixed32.add(207)
repeatedFixed64.add(208)
repeatedSfixed32.add(209)
repeatedSfixed64.add(210)
repeatedFloat.add(211f)
repeatedDouble.add(212.0)
repeatedBool.add(true)
repeatedString.add("215")
repeatedBytes.add(toBytes("216"))
repeatedGroup.add(TestAllTypesLiteKt.repeatedGroup { a = 217 })
repeatedNestedMessage.add(nestedMessage { bb = 218 })
repeatedForeignMessage.add(
foreignMessageLite { c = 219 }
)
repeatedImportMessage.add(
ImportMessageLite.newBuilder().setD(220).build()
)
repeatedLazyMessage.add(nestedMessage { bb = 227 })
repeatedNestedEnum.add(NestedEnum.BAR)
repeatedForeignEnum.add(ForeignEnumLite.FOREIGN_LITE_BAR)
repeatedImportEnum.add(ImportEnumLite.IMPORT_LITE_BAR)
repeatedStringPiece.add("224")
repeatedCord.add("225")
repeatedInt32 += 301
repeatedInt64 += 302
repeatedUint32 += 303
repeatedUint64 += 304
repeatedSint32 += 305
repeatedSint64 += 306
repeatedFixed32 += 307
repeatedFixed64 += 308
repeatedSfixed32 += 309
repeatedSfixed64 += 310
repeatedFloat += 311f
repeatedDouble += 312.0
repeatedBool += false
repeatedString += "315"
repeatedBytes += toBytes("316")
repeatedGroup += TestAllTypesLiteKt.repeatedGroup { a = 317 }
repeatedNestedMessage += nestedMessage { bb = 318 }
repeatedForeignMessage +=
foreignMessageLite { c = 319 }
repeatedImportMessage +=
ImportMessageLite.newBuilder().setD(320).build()
repeatedLazyMessage +=
TestAllTypesLiteKt.nestedMessage { bb = 327 }
repeatedNestedEnum += NestedEnum.BAZ
repeatedForeignEnum += ForeignEnumLite.FOREIGN_LITE_BAZ
repeatedImportEnum += ImportEnumLite.IMPORT_LITE_BAZ
repeatedStringPiece += "324"
repeatedCord += "325"
defaultInt32 = 401
defaultInt64 = 402
defaultUint32 = 403
defaultUint64 = 404
defaultSint32 = 405
defaultSint64 = 406
defaultFixed32 = 407
defaultFixed64 = 408
defaultSfixed32 = 409
defaultSfixed64 = 410
defaultFloat = 411f
defaultDouble = 412.0
defaultBool = false
defaultString = "415"
defaultBytes = toBytes("416")
defaultNestedEnum = NestedEnum.FOO
defaultForeignEnum = ForeignEnumLite.FOREIGN_LITE_FOO
defaultImportEnum = ImportEnumLite.IMPORT_LITE_FOO
defaultStringPiece = "424"
defaultCord = "425"
oneofUint32 = 601
oneofNestedMessage =
TestAllTypesLiteKt.nestedMessage { bb = 602 }
oneofString = "603"
oneofBytes = toBytes("604")
}
).isEqualTo(
TestUtilLite.getAllLiteSetBuilder().build()
)
}
@Test
fun testGetters() {
testAllTypesLite {
optionalInt32 = 101
assertThat(optionalInt32).isEqualTo(101)
optionalString = "115"
assertThat(optionalString).isEqualTo("115")
optionalGroup = TestAllTypesLiteKt.optionalGroup { a = 117 }
assertThat(optionalGroup).isEqualTo(TestAllTypesLiteKt.optionalGroup { a = 117 })
optionalNestedMessage = TestAllTypesLiteKt.nestedMessage { bb = 118 }
assertThat(optionalNestedMessage).isEqualTo(TestAllTypesLiteKt.nestedMessage { bb = 118 })
optionalNestedEnum = NestedEnum.BAZ
assertThat(optionalNestedEnum).isEqualTo(NestedEnum.BAZ)
defaultInt32 = 401
assertThat(defaultInt32).isEqualTo(401)
oneofUint32 = 601
assertThat(oneofUint32).isEqualTo(601)
}
}
@Test
fun testDefaultGetters() {
testAllTypesLite {
assertThat(defaultInt32).isEqualTo(41)
assertThat(defaultString).isEqualTo("hello")
assertThat(defaultNestedEnum).isEqualTo(NestedEnum.BAR)
assertThat(defaultStringPiece).isEqualTo("abc")
}
}
@Test
fun testRepeatedGettersAndSetters() {
testAllTypesLite {
repeatedInt32.addAll(listOf(1, 2))
assertThat(repeatedInt32).isEqualTo(listOf(1, 2))
repeatedInt32 += listOf(3, 4)
assertThat(repeatedInt32).isEqualTo(listOf(1, 2, 3, 4))
repeatedInt32[0] = 5
assertThat(repeatedInt32).isEqualTo(listOf(5, 2, 3, 4))
repeatedString.addAll(listOf("1", "2"))
assertThat(repeatedString).isEqualTo(listOf("1", "2"))
repeatedString += listOf("3", "4")
assertThat(repeatedString).isEqualTo(listOf("1", "2", "3", "4"))
repeatedString[0] = "5"
assertThat(repeatedString).isEqualTo(listOf("5", "2", "3", "4"))
repeatedGroup.addAll(
listOf(
TestAllTypesLiteKt.repeatedGroup { a = 1 },
TestAllTypesLiteKt.repeatedGroup { a = 2 }
)
)
assertThat(repeatedGroup).isEqualTo(
listOf(
TestAllTypesLiteKt.repeatedGroup { a = 1 },
TestAllTypesLiteKt.repeatedGroup { a = 2 }
)
)
repeatedGroup +=
listOf(
TestAllTypesLiteKt.repeatedGroup { a = 3 },
TestAllTypesLiteKt.repeatedGroup { a = 4 }
)
assertThat(repeatedGroup).isEqualTo(
listOf(
TestAllTypesLiteKt.repeatedGroup { a = 1 },
TestAllTypesLiteKt.repeatedGroup { a = 2 },
TestAllTypesLiteKt.repeatedGroup { a = 3 },
TestAllTypesLiteKt.repeatedGroup { a = 4 }
)
)
repeatedGroup[0] = TestAllTypesLiteKt.repeatedGroup { a = 5 }
assertThat(repeatedGroup).isEqualTo(
listOf(
TestAllTypesLiteKt.repeatedGroup { a = 5 },
TestAllTypesLiteKt.repeatedGroup { a = 2 },
TestAllTypesLiteKt.repeatedGroup { a = 3 },
TestAllTypesLiteKt.repeatedGroup { a = 4 }
)
)
repeatedNestedMessage.addAll(listOf(nestedMessage { bb = 1 }, nestedMessage { bb = 2 }))
assertThat(repeatedNestedMessage).isEqualTo(
listOf(
nestedMessage { bb = 1 },
nestedMessage { bb = 2 }
)
)
repeatedNestedMessage += listOf(nestedMessage { bb = 3 }, nestedMessage { bb = 4 })
assertThat(repeatedNestedMessage).isEqualTo(
listOf(
nestedMessage { bb = 1 },
nestedMessage { bb = 2 },
nestedMessage { bb = 3 },
nestedMessage { bb = 4 }
)
)
repeatedNestedMessage[0] = nestedMessage { bb = 5 }
assertThat(repeatedNestedMessage).isEqualTo(
listOf(
nestedMessage { bb = 5 },
nestedMessage { bb = 2 },
nestedMessage { bb = 3 },
nestedMessage { bb = 4 }
)
)
repeatedNestedEnum.addAll(listOf(NestedEnum.FOO, NestedEnum.BAR))
assertThat(repeatedNestedEnum).isEqualTo(listOf(NestedEnum.FOO, NestedEnum.BAR))
repeatedNestedEnum += listOf(NestedEnum.BAZ, NestedEnum.FOO)
assertThat(repeatedNestedEnum).isEqualTo(
listOf(NestedEnum.FOO, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
)
repeatedNestedEnum[0] = NestedEnum.BAR
assertThat(repeatedNestedEnum).isEqualTo(
listOf(NestedEnum.BAR, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
)
}
}
@Test
fun testHazzers() {
testAllTypesLite {
optionalInt32 = 101
assertThat(hasOptionalInt32()).isTrue()
assertThat(hasOptionalString()).isFalse()
optionalGroup = TestAllTypesLiteKt.optionalGroup { a = 117 }
assertThat(hasOptionalGroup()).isTrue()
assertThat(hasOptionalNestedMessage()).isFalse()
optionalNestedEnum = NestedEnum.BAZ
assertThat(hasOptionalNestedEnum()).isTrue()
assertThat(hasDefaultInt32()).isFalse()
oneofUint32 = 601
assertThat(hasOneofUint32()).isTrue()
}
testAllTypesLite {
assertThat(hasOptionalInt32()).isFalse()
optionalString = "115"
assertThat(hasOptionalString()).isTrue()
assertThat(hasOptionalGroup()).isFalse()
optionalNestedMessage = TestAllTypesLiteKt.nestedMessage { bb = 118 }
assertThat(hasOptionalNestedMessage()).isTrue()
assertThat(hasOptionalNestedEnum()).isFalse()
defaultInt32 = 401
assertThat(hasDefaultInt32()).isTrue()
assertThat(hasOneofUint32()).isFalse()
}
}
@Test
fun testClears() {
testAllTypesLite {
optionalInt32 = 101
clearOptionalInt32()
assertThat(hasOptionalInt32()).isFalse()
optionalString = "115"
clearOptionalString()
assertThat(hasOptionalString()).isFalse()
optionalGroup = TestAllTypesLiteKt.optionalGroup { a = 117 }
clearOptionalGroup()
assertThat(hasOptionalGroup()).isFalse()
optionalNestedMessage = TestAllTypesLiteKt.nestedMessage { bb = 118 }
clearOptionalNestedMessage()
assertThat(hasOptionalNestedMessage()).isFalse()
optionalNestedEnum = NestedEnum.BAZ
clearOptionalNestedEnum()
assertThat(hasOptionalNestedEnum()).isFalse()
defaultInt32 = 401
clearDefaultInt32()
assertThat(hasDefaultInt32()).isFalse()
oneofUint32 = 601
clearOneofUint32()
assertThat(hasOneofUint32()).isFalse()
}
}
@Test
fun testCopy() {
val message = testAllTypesLite {
optionalInt32 = 101
optionalString = "115"
}
val modifiedMessage = message.copy {
optionalInt32 = 201
}
assertThat(message).isEqualTo(
TestAllTypesLite.newBuilder()
.setOptionalInt32(101)
.setOptionalString("115")
.build()
)
assertThat(modifiedMessage).isEqualTo(
TestAllTypesLite.newBuilder()
.setOptionalInt32(201)
.setOptionalString("115")
.build()
)
}
@Test
fun testOneof() {
val message = testAllTypesLite {
oneofString = "foo"
assertThat(oneofFieldCase)
.isEqualTo(TestAllTypesLite.OneofFieldCase.ONEOF_STRING)
assertThat(oneofString).isEqualTo("foo")
clearOneofField()
assertThat(hasOneofUint32()).isFalse()
assertThat(oneofFieldCase)
.isEqualTo(TestAllTypesLite.OneofFieldCase.ONEOFFIELD_NOT_SET)
oneofUint32 = 5
}
assertThat(message.getOneofFieldCase())
.isEqualTo(TestAllTypesLite.OneofFieldCase.ONEOF_UINT32)
assertThat(message.getOneofUint32()).isEqualTo(5)
}
@Test
fun testExtensionsSet() {
assertThat(
testAllExtensionsLite {
this[UnittestLite.optionalInt32ExtensionLite] = 101
this[UnittestLite.optionalInt64ExtensionLite] = 102L
this[UnittestLite.optionalUint32ExtensionLite] = 103
this[UnittestLite.optionalUint64ExtensionLite] = 104L
this[UnittestLite.optionalSint32ExtensionLite] = 105
this[UnittestLite.optionalSint64ExtensionLite] = 106L
this[UnittestLite.optionalFixed32ExtensionLite] = 107
this[UnittestLite.optionalFixed64ExtensionLite] = 108L
this[UnittestLite.optionalSfixed32ExtensionLite] = 109
this[UnittestLite.optionalSfixed64ExtensionLite] = 110L
this[UnittestLite.optionalFloatExtensionLite] = 111F
this[UnittestLite.optionalDoubleExtensionLite] = 112.0
this[UnittestLite.optionalBoolExtensionLite] = true
this[UnittestLite.optionalStringExtensionLite] = "115"
this[UnittestLite.optionalBytesExtensionLite] = toBytes("116")
this[UnittestLite.optionalGroupExtensionLite] = optionalGroupExtensionLite { a = 117 }
this[UnittestLite.optionalNestedMessageExtensionLite] =
TestAllTypesLiteKt.nestedMessage { bb = 118 }
this[UnittestLite.optionalForeignMessageExtensionLite] = foreignMessageLite { c = 119 }
this[UnittestLite.optionalImportMessageExtensionLite] =
ImportMessageLite.newBuilder().setD(120).build()
this[UnittestLite.optionalPublicImportMessageExtensionLite] =
PublicImportMessageLite.newBuilder().setE(126).build()
this[UnittestLite.optionalLazyMessageExtensionLite] =
TestAllTypesLiteKt.nestedMessage { bb = 127 }
this[UnittestLite.optionalNestedEnumExtensionLite] = NestedEnum.BAZ
this[UnittestLite.optionalForeignEnumExtensionLite] = ForeignEnumLite.FOREIGN_LITE_BAZ
this[UnittestLite.optionalImportEnumExtensionLite] = ImportEnumLite.IMPORT_LITE_BAZ
this[UnittestLite.optionalStringPieceExtensionLite] = "124"
this[UnittestLite.optionalCordExtensionLite] = "125"
this[UnittestLite.repeatedInt32ExtensionLite].add(201)
this[UnittestLite.repeatedInt64ExtensionLite].add(202L)
this[UnittestLite.repeatedUint32ExtensionLite].add(203)
this[UnittestLite.repeatedUint64ExtensionLite].add(204L)
this[UnittestLite.repeatedSint32ExtensionLite].add(205)
this[UnittestLite.repeatedSint64ExtensionLite].add(206L)
this[UnittestLite.repeatedFixed32ExtensionLite].add(207)
this[UnittestLite.repeatedFixed64ExtensionLite].add(208L)
this[UnittestLite.repeatedSfixed32ExtensionLite].add(209)
this[UnittestLite.repeatedSfixed64ExtensionLite].add(210L)
this[UnittestLite.repeatedFloatExtensionLite].add(211F)
this[UnittestLite.repeatedDoubleExtensionLite].add(212.0)
this[UnittestLite.repeatedBoolExtensionLite].add(true)
this[UnittestLite.repeatedStringExtensionLite].add("215")
this[UnittestLite.repeatedBytesExtensionLite].add(toBytes("216"))
this[UnittestLite.repeatedGroupExtensionLite].add(repeatedGroupExtensionLite { a = 217 })
this[UnittestLite.repeatedNestedMessageExtensionLite].add(
TestAllTypesLiteKt.nestedMessage { bb = 218 }
)
this[UnittestLite.repeatedForeignMessageExtensionLite].add(foreignMessageLite { c = 219 })
this[UnittestLite.repeatedImportMessageExtensionLite].add(
ImportMessageLite.newBuilder().setD(220).build()
)
this[UnittestLite.repeatedLazyMessageExtensionLite].add(
TestAllTypesLiteKt.nestedMessage { bb = 227 }
)
this[UnittestLite.repeatedNestedEnumExtensionLite].add(NestedEnum.BAR)
this[UnittestLite.repeatedForeignEnumExtensionLite].add(ForeignEnumLite.FOREIGN_LITE_BAR)
this[UnittestLite.repeatedImportEnumExtensionLite].add(ImportEnumLite.IMPORT_LITE_BAR)
this[UnittestLite.repeatedStringPieceExtensionLite].add("224")
this[UnittestLite.repeatedCordExtensionLite].add("225")
this[UnittestLite.repeatedInt32ExtensionLite] += 301
this[UnittestLite.repeatedInt64ExtensionLite] += 302L
this[UnittestLite.repeatedUint32ExtensionLite] += 303
this[UnittestLite.repeatedUint64ExtensionLite] += 304L
this[UnittestLite.repeatedSint32ExtensionLite] += 305
this[UnittestLite.repeatedSint64ExtensionLite] += 306L
this[UnittestLite.repeatedFixed32ExtensionLite] += 307
this[UnittestLite.repeatedFixed64ExtensionLite] += 308L
this[UnittestLite.repeatedSfixed32ExtensionLite] += 309
this[UnittestLite.repeatedSfixed64ExtensionLite] += 310L
this[UnittestLite.repeatedFloatExtensionLite] += 311F
this[UnittestLite.repeatedDoubleExtensionLite] += 312.0
this[UnittestLite.repeatedBoolExtensionLite] += false
this[UnittestLite.repeatedStringExtensionLite] += "315"
this[UnittestLite.repeatedBytesExtensionLite] += toBytes("316")
this[UnittestLite.repeatedGroupExtensionLite] += repeatedGroupExtensionLite { a = 317 }
this[UnittestLite.repeatedNestedMessageExtensionLite] +=
TestAllTypesLiteKt.nestedMessage { bb = 318 }
this[UnittestLite.repeatedForeignMessageExtensionLite] += foreignMessageLite { c = 319 }
this[UnittestLite.repeatedImportMessageExtensionLite] +=
ImportMessageLite.newBuilder().setD(320).build()
this[UnittestLite.repeatedLazyMessageExtensionLite] +=
TestAllTypesLiteKt.nestedMessage { bb = 327 }
this[UnittestLite.repeatedNestedEnumExtensionLite] += NestedEnum.BAZ
this[UnittestLite.repeatedForeignEnumExtensionLite] += ForeignEnumLite.FOREIGN_LITE_BAZ
this[UnittestLite.repeatedImportEnumExtensionLite] += ImportEnumLite.IMPORT_LITE_BAZ
this[UnittestLite.repeatedStringPieceExtensionLite] += "324"
this[UnittestLite.repeatedCordExtensionLite] += "325"
this[UnittestLite.defaultInt32ExtensionLite] = 401
this[UnittestLite.defaultInt64ExtensionLite] = 402L
this[UnittestLite.defaultUint32ExtensionLite] = 403
this[UnittestLite.defaultUint64ExtensionLite] = 404L
this[UnittestLite.defaultSint32ExtensionLite] = 405
this[UnittestLite.defaultSint64ExtensionLite] = 406L
this[UnittestLite.defaultFixed32ExtensionLite] = 407
this[UnittestLite.defaultFixed64ExtensionLite] = 408L
this[UnittestLite.defaultSfixed32ExtensionLite] = 409
this[UnittestLite.defaultSfixed64ExtensionLite] = 410L
this[UnittestLite.defaultFloatExtensionLite] = 411F
this[UnittestLite.defaultDoubleExtensionLite] = 412.0
this[UnittestLite.defaultBoolExtensionLite] = false
this[UnittestLite.defaultStringExtensionLite] = "415"
this[UnittestLite.defaultBytesExtensionLite] = toBytes("416")
this[UnittestLite.defaultNestedEnumExtensionLite] = NestedEnum.FOO
this[UnittestLite.defaultForeignEnumExtensionLite] = ForeignEnumLite.FOREIGN_LITE_FOO
this[UnittestLite.defaultImportEnumExtensionLite] = ImportEnumLite.IMPORT_LITE_FOO
this[UnittestLite.defaultStringPieceExtensionLite] = "424"
this[UnittestLite.defaultCordExtensionLite] = "425"
this[UnittestLite.oneofUint32ExtensionLite] = 601
this[UnittestLite.oneofNestedMessageExtensionLite] =
TestAllTypesLiteKt.nestedMessage { bb = 602 }
this[UnittestLite.oneofStringExtensionLite] = "603"
this[UnittestLite.oneofBytesExtensionLite] = toBytes("604")
}
).isEqualTo(
TestUtilLite.getAllLiteExtensionsSet()
)
}
@Test
fun testExtensionGetters() {
testAllExtensionsLite {
this[UnittestLite.optionalInt32ExtensionLite] = 101
assertThat(this[UnittestLite.optionalInt32ExtensionLite]).isEqualTo(101)
this[UnittestLite.optionalStringExtensionLite] = "115"
assertThat(this[UnittestLite.optionalStringExtensionLite]).isEqualTo("115")
this[UnittestLite.optionalGroupExtensionLite] = optionalGroupExtensionLite { a = 117 }
assertThat(this[UnittestLite.optionalGroupExtensionLite])
.isEqualTo(optionalGroupExtensionLite { a = 117 })
this[UnittestLite.optionalNestedMessageExtensionLite] =
TestAllTypesLiteKt.nestedMessage { bb = 118 }
assertThat(this[UnittestLite.optionalNestedMessageExtensionLite])
.isEqualTo(TestAllTypesLiteKt.nestedMessage { bb = 118 })
this[UnittestLite.optionalNestedEnumExtensionLite] = NestedEnum.BAZ
assertThat(this[UnittestLite.optionalNestedEnumExtensionLite]).isEqualTo(NestedEnum.BAZ)
this[UnittestLite.defaultInt32ExtensionLite] = 401
assertThat(this[UnittestLite.defaultInt32ExtensionLite]).isEqualTo(401)
this[UnittestLite.oneofUint32ExtensionLite] = 601
assertThat(this[UnittestLite.oneofUint32ExtensionLite]).isEqualTo(601)
}
}
@Test
fun testRepeatedExtensionGettersAndSetters() {
testAllExtensionsLite {
this[UnittestLite.repeatedInt32ExtensionLite].addAll(listOf(1, 2))
assertThat(this[UnittestLite.repeatedInt32ExtensionLite]).isEqualTo(listOf(1, 2))
this[UnittestLite.repeatedInt32ExtensionLite] += listOf(3, 4)
assertThat(this[UnittestLite.repeatedInt32ExtensionLite]).isEqualTo(listOf(1, 2, 3, 4))
this[UnittestLite.repeatedInt32ExtensionLite][0] = 5
assertThat(this[UnittestLite.repeatedInt32ExtensionLite]).isEqualTo(listOf(5, 2, 3, 4))
this[UnittestLite.repeatedStringExtensionLite].addAll(listOf("1", "2"))
assertThat(this[UnittestLite.repeatedStringExtensionLite]).isEqualTo(listOf("1", "2"))
this[UnittestLite.repeatedStringExtensionLite] += listOf("3", "4")
assertThat(this[UnittestLite.repeatedStringExtensionLite])
.isEqualTo(listOf("1", "2", "3", "4"))
this[UnittestLite.repeatedStringExtensionLite][0] = "5"
assertThat(this[UnittestLite.repeatedStringExtensionLite])
.isEqualTo(listOf("5", "2", "3", "4"))
this[UnittestLite.repeatedGroupExtensionLite].addAll(
listOf(
repeatedGroupExtensionLite { a = 1 },
repeatedGroupExtensionLite { a = 2 }
)
)
assertThat(this[UnittestLite.repeatedGroupExtensionLite]).isEqualTo(
listOf(
repeatedGroupExtensionLite { a = 1 },
repeatedGroupExtensionLite { a = 2 }
)
)
this[UnittestLite.repeatedGroupExtensionLite] +=
listOf(
repeatedGroupExtensionLite { a = 3 },
repeatedGroupExtensionLite { a = 4 }
)
assertThat(this[UnittestLite.repeatedGroupExtensionLite]).isEqualTo(
listOf(
repeatedGroupExtensionLite { a = 1 },
repeatedGroupExtensionLite { a = 2 },
repeatedGroupExtensionLite { a = 3 },
repeatedGroupExtensionLite { a = 4 }
)
)
this[UnittestLite.repeatedGroupExtensionLite][0] = repeatedGroupExtensionLite { a = 5 }
assertThat(this[UnittestLite.repeatedGroupExtensionLite]).isEqualTo(
listOf(
repeatedGroupExtensionLite { a = 5 },
repeatedGroupExtensionLite { a = 2 },
repeatedGroupExtensionLite { a = 3 },
repeatedGroupExtensionLite { a = 4 }
)
)
this[UnittestLite.repeatedNestedMessageExtensionLite].addAll(
listOf(nestedMessage { bb = 1 }, nestedMessage { bb = 2 })
)
assertThat(this[UnittestLite.repeatedNestedMessageExtensionLite]).isEqualTo(
listOf(nestedMessage { bb = 1 }, nestedMessage { bb = 2 })
)
this[UnittestLite.repeatedNestedMessageExtensionLite] +=
listOf(nestedMessage { bb = 3 }, nestedMessage { bb = 4 })
assertThat(this[UnittestLite.repeatedNestedMessageExtensionLite]).isEqualTo(
listOf(
nestedMessage { bb = 1 },
nestedMessage { bb = 2 },
nestedMessage { bb = 3 },
nestedMessage { bb = 4 }
)
)
this[UnittestLite.repeatedNestedMessageExtensionLite][0] = nestedMessage { bb = 5 }
assertThat(this[UnittestLite.repeatedNestedMessageExtensionLite]).isEqualTo(
listOf(
nestedMessage { bb = 5 },
nestedMessage { bb = 2 },
nestedMessage { bb = 3 },
nestedMessage { bb = 4 }
)
)
this[UnittestLite.repeatedNestedEnumExtensionLite]
.addAll(listOf(NestedEnum.FOO, NestedEnum.BAR))
assertThat(this[UnittestLite.repeatedNestedEnumExtensionLite])
.isEqualTo(listOf(NestedEnum.FOO, NestedEnum.BAR))
this[UnittestLite.repeatedNestedEnumExtensionLite] += listOf(NestedEnum.BAZ, NestedEnum.FOO)
assertThat(this[UnittestLite.repeatedNestedEnumExtensionLite]).isEqualTo(
listOf(NestedEnum.FOO, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
)
this[UnittestLite.repeatedNestedEnumExtensionLite][0] = NestedEnum.BAR
assertThat(this[UnittestLite.repeatedNestedEnumExtensionLite]).isEqualTo(
listOf(NestedEnum.BAR, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
)
}
}
@Test
fun testExtensionContains() {
testAllExtensionsLite {
this[UnittestLite.optionalInt32ExtensionLite] = 101
assertThat(contains(UnittestLite.optionalInt32ExtensionLite)).isTrue()
assertThat(contains(UnittestLite.optionalStringExtensionLite)).isFalse()
this[UnittestLite.optionalGroupExtensionLite] = optionalGroupExtensionLite { a = 117 }
assertThat(contains(UnittestLite.optionalGroupExtensionLite)).isTrue()
assertThat(contains(UnittestLite.optionalNestedMessageExtensionLite)).isFalse()
this[UnittestLite.optionalNestedEnumExtensionLite] = NestedEnum.BAZ
assertThat(contains(UnittestLite.optionalNestedEnumExtensionLite)).isTrue()
assertThat(contains(UnittestLite.defaultInt32ExtensionLite)).isFalse()
this[UnittestLite.oneofUint32ExtensionLite] = 601
assertThat(contains(UnittestLite.oneofUint32ExtensionLite)).isTrue()
}
testAllExtensionsLite {
assertThat(contains(UnittestLite.optionalInt32ExtensionLite)).isFalse()
this[UnittestLite.optionalStringExtensionLite] = "115"
assertThat(contains(UnittestLite.optionalStringExtensionLite)).isTrue()
assertThat(contains(UnittestLite.optionalGroupExtensionLite)).isFalse()
this[UnittestLite.optionalNestedMessageExtensionLite] =
TestAllTypesLiteKt.nestedMessage { bb = 118 }
assertThat(contains(UnittestLite.optionalNestedMessageExtensionLite)).isTrue()
assertThat(contains(UnittestLite.optionalNestedEnumExtensionLite)).isFalse()
this[UnittestLite.defaultInt32ExtensionLite] = 401
assertThat(contains(UnittestLite.defaultInt32ExtensionLite)).isTrue()
assertThat(contains(UnittestLite.oneofUint32ExtensionLite)).isFalse()
}
}
@Test
fun testExtensionClears() {
testAllExtensionsLite {
this[UnittestLite.optionalInt32ExtensionLite] = 101
clear(UnittestLite.optionalInt32ExtensionLite)
assertThat(contains(UnittestLite.optionalInt32ExtensionLite)).isFalse()
this[UnittestLite.optionalStringExtensionLite] = "115"
clear(UnittestLite.optionalStringExtensionLite)
assertThat(contains(UnittestLite.optionalStringExtensionLite)).isFalse()
this[UnittestLite.optionalGroupExtensionLite] = optionalGroupExtensionLite { a = 117 }
clear(UnittestLite.optionalGroupExtensionLite)
assertThat(contains(UnittestLite.optionalGroupExtensionLite)).isFalse()
this[UnittestLite.optionalNestedMessageExtensionLite] =
TestAllTypesLiteKt.nestedMessage { bb = 118 }
clear(UnittestLite.optionalNestedMessageExtensionLite)
assertThat(contains(UnittestLite.optionalNestedMessageExtensionLite)).isFalse()
this[UnittestLite.optionalNestedEnumExtensionLite] = NestedEnum.BAZ
clear(UnittestLite.optionalNestedEnumExtensionLite)
assertThat(contains(UnittestLite.optionalNestedEnumExtensionLite)).isFalse()
this[UnittestLite.defaultInt32ExtensionLite] = 401
clear(UnittestLite.defaultInt32ExtensionLite)
assertThat(contains(UnittestLite.defaultInt32ExtensionLite)).isFalse()
this[UnittestLite.oneofUint32ExtensionLite] = 601
clear(UnittestLite.oneofUint32ExtensionLite)
assertThat(contains(UnittestLite.oneofUint32ExtensionLite)).isFalse()
}
}
@Test
fun testEmptyMessages() {
assertThat(
testEmptyMessageLite {}
).isEqualTo(
TestEmptyMessageLite.newBuilder().build()
)
assertThat(
testEmptyMessageWithExtensionsLite {}
).isEqualTo(
TestEmptyMessageWithExtensionsLite.newBuilder().build()
)
}
@Test
fun testMapSetters() {
assertThat(
testMapLite {
mapInt32Int32[1] = 2
mapInt64Int64[1L] = 2L
mapUint32Uint32[1] = 2
mapUint64Uint64[1L] = 2L
mapSint32Sint32[1] = 2
mapSint64Sint64[1L] = 2L
mapFixed32Fixed32[1] = 2
mapFixed64Fixed64[1L] = 2L
mapSfixed32Sfixed32[1] = 2
mapSfixed64Sfixed64[1L] = 2L
mapInt32Float[1] = 2F
mapInt32Double[1] = 2.0
mapBoolBool[true] = true
mapStringString["1"] = "2"
mapInt32Bytes[1] = toBytes("2")
mapInt32Enum[1] = MapEnumLite.MAP_ENUM_FOO_LITE
mapInt32ForeignMessage[1] = foreignMessageLite { c = 1 }
}
).isEqualTo(
TestMapLite.newBuilder()
.putMapInt32Int32(1, 2)
.putMapInt64Int64(1L, 2L)
.putMapUint32Uint32(1, 2)
.putMapUint64Uint64(1L, 2L)
.putMapSint32Sint32(1, 2)
.putMapSint64Sint64(1L, 2L)
.putMapFixed32Fixed32(1, 2)
.putMapFixed64Fixed64(1L, 2L)
.putMapSfixed32Sfixed32(1, 2)
.putMapSfixed64Sfixed64(1L, 2L)
.putMapInt32Float(1, 2F)
.putMapInt32Double(1, 2.0)
.putMapBoolBool(true, true)
.putMapStringString("1", "2")
.putMapInt32Bytes(1, toBytes("2"))
.putMapInt32Enum(1, MapEnumLite.MAP_ENUM_FOO_LITE)
.putMapInt32ForeignMessage(1, foreignMessageLite { c = 1 })
.build()
)
}
@Test
fun testMapGettersAndSetters() {
testMapLite {
mapInt32Int32.put(1, 2)
assertThat(mapInt32Int32).isEqualTo(mapOf(1 to 2))
mapInt32Int32[3] = 4
assertThat(mapInt32Int32).isEqualTo(mapOf(1 to 2, 3 to 4))
mapInt32Int32.putAll(mapOf(5 to 6, 7 to 8))
assertThat(mapInt32Int32).isEqualTo(mapOf(1 to 2, 3 to 4, 5 to 6, 7 to 8))
mapStringString.put("1", "2")
assertThat(mapStringString).isEqualTo(mapOf("1" to "2"))
mapStringString["3"] = "4"
assertThat(mapStringString).isEqualTo(mapOf("1" to "2", "3" to "4"))
mapStringString.putAll(mapOf("5" to "6", "7" to "8"))
assertThat(mapStringString).isEqualTo(mapOf("1" to "2", "3" to "4", "5" to "6", "7" to "8"))
mapInt32Enum.put(1, MapEnumLite.MAP_ENUM_FOO_LITE)
assertThat(mapInt32Enum).isEqualTo(mapOf(1 to MapEnumLite.MAP_ENUM_FOO_LITE))
mapInt32Enum[2] = MapEnumLite.MAP_ENUM_BAR_LITE
assertThat(mapInt32Enum).isEqualTo(
mapOf(1 to MapEnumLite.MAP_ENUM_FOO_LITE, 2 to MapEnumLite.MAP_ENUM_BAR_LITE)
)
mapInt32Enum.putAll(
mapOf(3 to MapEnumLite.MAP_ENUM_BAZ_LITE, 4 to MapEnumLite.MAP_ENUM_FOO_LITE)
)
assertThat(mapInt32Enum).isEqualTo(
mapOf(
1 to MapEnumLite.MAP_ENUM_FOO_LITE,
2 to MapEnumLite.MAP_ENUM_BAR_LITE,
3 to MapEnumLite.MAP_ENUM_BAZ_LITE,
4 to MapEnumLite.MAP_ENUM_FOO_LITE
)
)
mapInt32ForeignMessage.put(1, foreignMessageLite { c = 1 })
assertThat(mapInt32ForeignMessage).isEqualTo(mapOf(1 to foreignMessageLite { c = 1 }))
mapInt32ForeignMessage[2] = foreignMessageLite { c = 2 }
assertThat(mapInt32ForeignMessage).isEqualTo(
mapOf(1 to foreignMessageLite { c = 1 }, 2 to foreignMessageLite { c = 2 })
)
mapInt32ForeignMessage.putAll(
mapOf(3 to foreignMessageLite { c = 3 }, 4 to foreignMessageLite { c = 4 })
)
assertThat(mapInt32ForeignMessage).isEqualTo(
mapOf(
1 to foreignMessageLite { c = 1 },
2 to foreignMessageLite { c = 2 },
3 to foreignMessageLite { c = 3 },
4 to foreignMessageLite { c = 4 }
)
)
}
}
@Test
fun testMapRemove() {
testMapLite {
mapInt32Int32.putAll(mapOf(1 to 2, 3 to 4))
mapInt32Int32.remove(1)
assertThat(mapInt32Int32).isEqualTo(mapOf(3 to 4))
mapStringString.putAll(mapOf("1" to "2", "3" to "4"))
mapStringString.remove("1")
assertThat(mapStringString).isEqualTo(mapOf("3" to "4"))
mapInt32Enum.putAll(
mapOf(1 to MapEnumLite.MAP_ENUM_FOO_LITE, 2 to MapEnumLite.MAP_ENUM_BAR_LITE)
)
mapInt32Enum.remove(1)
assertThat(mapInt32Enum).isEqualTo(mapOf(2 to MapEnumLite.MAP_ENUM_BAR_LITE))
mapInt32ForeignMessage.putAll(
mapOf(1 to foreignMessageLite { c = 1 }, 2 to foreignMessageLite { c = 2 })
)
mapInt32ForeignMessage.remove(1)
assertThat(mapInt32ForeignMessage).isEqualTo(mapOf(2 to foreignMessageLite { c = 2 }))
}
}
@Test
fun testMapClear() {
testMapLite {
mapInt32Int32.putAll(mapOf(1 to 2, 3 to 4))
mapInt32Int32.clear()
assertThat(mapInt32Int32.isEmpty()).isTrue()
mapStringString.putAll(mapOf("1" to "2", "3" to "4"))
mapStringString.clear()
assertThat(mapStringString.isEmpty()).isTrue()
mapInt32Enum.putAll(
mapOf(1 to MapEnumLite.MAP_ENUM_FOO_LITE, 2 to MapEnumLite.MAP_ENUM_BAR_LITE)
)
mapInt32Enum.clear()
assertThat(mapInt32Enum.isEmpty()).isTrue()
mapInt32ForeignMessage.putAll(
mapOf(1 to foreignMessageLite { c = 1 }, 2 to foreignMessageLite { c = 2 })
)
mapInt32ForeignMessage.clear()
assertThat(mapInt32ForeignMessage.isEmpty()).isTrue()
}
}
@Test
fun testEvilNames() {
assertThat(
evilNamesProto2 {
initialized = true
hasFoo = true
bar = "foo"
isInitialized = true
fooBar = "foo"
aLLCAPS += "foo"
aLLCAPSMAP[1] = true
hasUnderbarPrecedingNumeric1Foo = true
hasUnderbarPrecedingNumeric42Bar = true
hasUnderbarPrecedingNumeric123Foo42BarBaz = true
extension += "foo"
class_ += 1
int = 1.0
long = true
boolean = 1L
sealed = "foo"
interface_ = 1F
in_ = 1
object_ = "foo"
cachedSize_ = "foo"
serializedSize_ = true
by = "foo"
}
).isEqualTo(
EvilNamesProto2.newBuilder()
.setInitialized(true)
.setHasFoo(true)
.setBar("foo")
.setIsInitialized(true)
.setFooBar("foo")
.addALLCAPS("foo")
.putALLCAPSMAP(1, true)
.setHasUnderbarPrecedingNumeric1Foo(true)
.setHasUnderbarPrecedingNumeric42Bar(true)
.setHasUnderbarPrecedingNumeric123Foo42BarBaz(true)
.addExtension("foo")
.addClass_(1)
.setInt(1.0)
.setLong(true)
.setBoolean(1L)
.setSealed("foo")
.setInterface(1F)
.setIn(1)
.setObject("foo")
.setCachedSize_("foo")
.setSerializedSize_(true)
.setBy("foo")
.build()
)
assertThat(interface_ {}).isEqualTo(Interface.newBuilder().build())
}
@Test
fun testHardKeywordGettersAndSetters() {
hardKeywordsAllTypes {
as_ = 1
assertThat(as_).isEqualTo(1)
in_ = "foo"
assertThat(in_).isEqualTo("foo")
break_ = HardKeywordsAllTypes.NestedEnum.FOO
assertThat(break_).isEqualTo(HardKeywordsAllTypes.NestedEnum.FOO)
do_ = HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }
assertThat(do_).isEqualTo(HardKeywordsAllTypesKt.nestedMessage { while_ = 1 })
continue_[1] = 1
assertThat(continue_[1]).isEqualTo(1)
else_ += 1
assertThat(else_).isEqualTo(listOf(1))
for_ += "foo"
assertThat(for_).isEqualTo(listOf("foo"))
fun_ += HardKeywordsAllTypes.NestedEnum.FOO
assertThat(fun_).isEqualTo(listOf(HardKeywordsAllTypes.NestedEnum.FOO))
if_ += HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }
assertThat(if_).isEqualTo(listOf(HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }))
}
}
@Test
fun testHardKeywordHazzers() {
hardKeywordsAllTypes {
as_ = 1
assertThat(hasAs_()).isTrue()
in_ = "foo"
assertThat(hasIn_()).isTrue()
break_ = HardKeywordsAllTypes.NestedEnum.FOO
assertThat(hasBreak_()).isTrue()
do_ = HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }
assertThat(hasDo_()).isTrue()
}
}
@Test
fun testHardKeywordClears() {
hardKeywordsAllTypes {
as_ = 1
clearAs_()
assertThat(hasAs_()).isFalse()
in_ = "foo"
clearIn_()
assertThat(hasIn_()).isFalse()
break_ = HardKeywordsAllTypes.NestedEnum.FOO
clearBreak_()
assertThat(hasBreak_()).isFalse()
do_ = HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }
clearDo_()
assertThat(hasDo_()).isFalse()
}
}
}

@ -0,0 +1,980 @@
package com.google.protobuf.kotlin
import com.google.common.truth.Truth.assertThat
import com.google.protobuf.TestUtil
import com.google.protobuf.TestUtil.toBytes
import com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.EvilNamesProto2
import com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.HardKeywordsAllTypes
import com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.Interface
import com.google.protobuf.kotlin.generator.HardKeywordsAllTypesKt
import com.google.protobuf.kotlin.generator.evilNamesProto2
import com.google.protobuf.kotlin.generator.hardKeywordsAllTypes
import com.google.protobuf.kotlin.generator.interface_
import com.google.protobuf.test.UnittestImport.ImportEnum
import com.google.protobuf.test.UnittestImport.ImportMessage
import com.google.protobuf.test.UnittestImportPublic.PublicImportMessage
import com.google.protos.proto2_unittest.MapProto2Unittest.Proto2MapEnum
import com.google.protos.proto2_unittest.MapProto2Unittest.TestEnumMap
import com.google.protos.proto2_unittest.MapProto2Unittest.TestIntIntMap
import com.google.protos.proto2_unittest.MapProto2Unittest.TestMaps
import com.google.protos.proto2_unittest.TestAllTypesKt
import com.google.protos.proto2_unittest.TestAllTypesKt.nestedMessage
import com.google.protos.proto2_unittest.UnittestProto
import com.google.protos.proto2_unittest.UnittestProto.ForeignEnum
import com.google.protos.proto2_unittest.UnittestProto.TestAllTypes
import com.google.protos.proto2_unittest.UnittestProto.TestAllTypes.NestedEnum
import com.google.protos.proto2_unittest.UnittestProto.TestEmptyMessage
import com.google.protos.proto2_unittest.UnittestProto.TestEmptyMessageWithExtensions
import com.google.protos.proto2_unittest.copy
import com.google.protos.proto2_unittest.foreignMessage
import com.google.protos.proto2_unittest.optionalGroupExtension
import com.google.protos.proto2_unittest.repeatedGroupExtension
import com.google.protos.proto2_unittest.testAllExtensions
import com.google.protos.proto2_unittest.testAllTypes
import com.google.protos.proto2_unittest.testEmptyMessage
import com.google.protos.proto2_unittest.testEmptyMessageWithExtensions
import com.google.protos.proto2_unittest.testEnumMap
import com.google.protos.proto2_unittest.testIntIntMap
import com.google.protos.proto2_unittest.testMaps
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@RunWith(JUnit4::class)
class Proto2Test {
@Test
fun testSetters() {
assertThat(
testAllTypes {
optionalInt32 = 101
optionalInt64 = 102
optionalUint32 = 103
optionalUint64 = 104
optionalSint32 = 105
optionalSint64 = 106
optionalFixed32 = 107
optionalFixed64 = 108
optionalSfixed32 = 109
optionalSfixed64 = 110
optionalFloat = 111.0f
optionalDouble = 112.0
optionalBool = true
optionalString = "115"
optionalBytes = toBytes("116")
optionalGroup =
TestAllTypesKt.optionalGroup { a = 117 }
optionalNestedMessage = nestedMessage { bb = 118 }
optionalForeignMessage = foreignMessage { c = 119 }
optionalImportMessage =
ImportMessage.newBuilder().setD(120).build()
optionalPublicImportMessage =
PublicImportMessage.newBuilder().setE(126).build()
optionalLazyMessage = nestedMessage { bb = 127 }
optionalNestedEnum = NestedEnum.BAZ
optionalForeignEnum = ForeignEnum.FOREIGN_BAZ
optionalImportEnum = ImportEnum.IMPORT_BAZ
optionalStringPiece = "124"
optionalCord = "125"
repeatedInt32.add(201)
repeatedInt64.add(202)
repeatedUint32.add(203)
repeatedUint64.add(204)
repeatedSint32.add(205)
repeatedSint64.add(206)
repeatedFixed32.add(207)
repeatedFixed64.add(208)
repeatedSfixed32.add(209)
repeatedSfixed64.add(210)
repeatedFloat.add(211f)
repeatedDouble.add(212.0)
repeatedBool.add(true)
repeatedString.add("215")
repeatedBytes.add(toBytes("216"))
repeatedGroup.add(TestAllTypesKt.repeatedGroup { a = 217 })
repeatedNestedMessage.add(nestedMessage { bb = 218 })
repeatedForeignMessage.add(foreignMessage { c = 219 })
repeatedImportMessage.add(
ImportMessage.newBuilder().setD(220).build()
)
repeatedLazyMessage.add(nestedMessage { bb = 227 })
repeatedNestedEnum.add(NestedEnum.BAR)
repeatedForeignEnum.add(ForeignEnum.FOREIGN_BAR)
repeatedImportEnum.add(ImportEnum.IMPORT_BAR)
repeatedStringPiece.add("224")
repeatedCord.add("225")
repeatedInt32 += 301
repeatedInt64 += 302
repeatedUint32 += 303
repeatedUint64 += 304
repeatedSint32 += 305
repeatedSint64 += 306
repeatedFixed32 += 307
repeatedFixed64 += 308
repeatedSfixed32 += 309
repeatedSfixed64 += 310
repeatedFloat += 311f
repeatedDouble += 312.0
repeatedBool += false
repeatedString += "315"
repeatedBytes += toBytes("316")
repeatedGroup += TestAllTypesKt.repeatedGroup { a = 317 }
repeatedNestedMessage += nestedMessage { bb = 318 }
repeatedForeignMessage += foreignMessage { c = 319 }
repeatedImportMessage +=
ImportMessage.newBuilder().setD(320).build()
repeatedLazyMessage +=
TestAllTypesKt.nestedMessage { bb = 327 }
repeatedNestedEnum += NestedEnum.BAZ
repeatedForeignEnum += ForeignEnum.FOREIGN_BAZ
repeatedImportEnum += ImportEnum.IMPORT_BAZ
repeatedStringPiece += "324"
repeatedCord += "325"
defaultInt32 = 401
defaultInt64 = 402
defaultUint32 = 403
defaultUint64 = 404
defaultSint32 = 405
defaultSint64 = 406
defaultFixed32 = 407
defaultFixed64 = 408
defaultSfixed32 = 409
defaultSfixed64 = 410
defaultFloat = 411f
defaultDouble = 412.0
defaultBool = false
defaultString = "415"
defaultBytes = toBytes("416")
defaultNestedEnum = NestedEnum.FOO
defaultForeignEnum = ForeignEnum.FOREIGN_FOO
defaultImportEnum = ImportEnum.IMPORT_FOO
defaultStringPiece = "424"
defaultCord = "425"
oneofUint32 = 601
oneofNestedMessage =
TestAllTypesKt.nestedMessage { bb = 602 }
oneofString = "603"
oneofBytes = toBytes("604")
}
).isEqualTo(
TestUtil.getAllSetBuilder().build()
)
}
@Test
fun testGetters() {
testAllTypes {
optionalInt32 = 101
assertThat(optionalInt32).isEqualTo(101)
optionalString = "115"
assertThat(optionalString).isEqualTo("115")
optionalGroup = TestAllTypesKt.optionalGroup { a = 117 }
assertThat(optionalGroup).isEqualTo(TestAllTypesKt.optionalGroup { a = 117 })
optionalNestedMessage = TestAllTypesKt.nestedMessage { bb = 118 }
assertThat(optionalNestedMessage).isEqualTo(TestAllTypesKt.nestedMessage { bb = 118 })
optionalNestedEnum = NestedEnum.BAZ
assertThat(optionalNestedEnum).isEqualTo(NestedEnum.BAZ)
defaultInt32 = 401
assertThat(defaultInt32).isEqualTo(401)
oneofUint32 = 601
assertThat(oneofUint32).isEqualTo(601)
}
}
@Test
fun testDefaultGetters() {
testAllTypes {
assertThat(defaultInt32).isEqualTo(41)
assertThat(defaultString).isEqualTo("hello")
assertThat(defaultNestedEnum).isEqualTo(NestedEnum.BAR)
assertThat(defaultStringPiece).isEqualTo("abc")
}
}
@Test
fun testRepeatedGettersAndSetters() {
testAllTypes {
repeatedInt32.addAll(listOf(1, 2))
assertThat(repeatedInt32).isEqualTo(listOf(1, 2))
repeatedInt32 += listOf(3, 4)
assertThat(repeatedInt32).isEqualTo(listOf(1, 2, 3, 4))
repeatedInt32[0] = 5
assertThat(repeatedInt32).isEqualTo(listOf(5, 2, 3, 4))
repeatedString.addAll(listOf("1", "2"))
assertThat(repeatedString).isEqualTo(listOf("1", "2"))
repeatedString += listOf("3", "4")
assertThat(repeatedString).isEqualTo(listOf("1", "2", "3", "4"))
repeatedString[0] = "5"
assertThat(repeatedString).isEqualTo(listOf("5", "2", "3", "4"))
repeatedGroup.addAll(
listOf(
TestAllTypesKt.repeatedGroup { a = 1 },
TestAllTypesKt.repeatedGroup { a = 2 }
)
)
assertThat(repeatedGroup).isEqualTo(
listOf(
TestAllTypesKt.repeatedGroup { a = 1 },
TestAllTypesKt.repeatedGroup { a = 2 }
)
)
repeatedGroup +=
listOf(
TestAllTypesKt.repeatedGroup { a = 3 },
TestAllTypesKt.repeatedGroup { a = 4 }
)
assertThat(repeatedGroup).isEqualTo(
listOf(
TestAllTypesKt.repeatedGroup { a = 1 },
TestAllTypesKt.repeatedGroup { a = 2 },
TestAllTypesKt.repeatedGroup { a = 3 },
TestAllTypesKt.repeatedGroup { a = 4 }
)
)
repeatedGroup[0] = TestAllTypesKt.repeatedGroup { a = 5 }
assertThat(repeatedGroup).isEqualTo(
listOf(
TestAllTypesKt.repeatedGroup { a = 5 },
TestAllTypesKt.repeatedGroup { a = 2 },
TestAllTypesKt.repeatedGroup { a = 3 },
TestAllTypesKt.repeatedGroup { a = 4 }
)
)
repeatedNestedMessage.addAll(listOf(nestedMessage { bb = 1 }, nestedMessage { bb = 2 }))
assertThat(repeatedNestedMessage).isEqualTo(
listOf(
nestedMessage { bb = 1 },
nestedMessage { bb = 2 }
)
)
repeatedNestedMessage += listOf(nestedMessage { bb = 3 }, nestedMessage { bb = 4 })
assertThat(repeatedNestedMessage).isEqualTo(
listOf(
nestedMessage { bb = 1 },
nestedMessage { bb = 2 },
nestedMessage { bb = 3 },
nestedMessage { bb = 4 }
)
)
repeatedNestedMessage[0] = nestedMessage { bb = 5 }
assertThat(repeatedNestedMessage).isEqualTo(
listOf(
nestedMessage { bb = 5 },
nestedMessage { bb = 2 },
nestedMessage { bb = 3 },
nestedMessage { bb = 4 }
)
)
repeatedNestedEnum.addAll(listOf(NestedEnum.FOO, NestedEnum.BAR))
assertThat(repeatedNestedEnum).isEqualTo(listOf(NestedEnum.FOO, NestedEnum.BAR))
repeatedNestedEnum += listOf(NestedEnum.BAZ, NestedEnum.FOO)
assertThat(repeatedNestedEnum).isEqualTo(
listOf(NestedEnum.FOO, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
)
repeatedNestedEnum[0] = NestedEnum.BAR
assertThat(repeatedNestedEnum).isEqualTo(
listOf(NestedEnum.BAR, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
)
}
}
@Test
fun testHazzers() {
testAllTypes {
optionalInt32 = 101
assertThat(hasOptionalInt32()).isTrue()
assertThat(hasOptionalString()).isFalse()
optionalGroup = TestAllTypesKt.optionalGroup { a = 117 }
assertThat(hasOptionalGroup()).isTrue()
assertThat(hasOptionalNestedMessage()).isFalse()
optionalNestedEnum = NestedEnum.BAZ
assertThat(hasOptionalNestedEnum()).isTrue()
assertThat(hasDefaultInt32()).isFalse()
oneofUint32 = 601
assertThat(hasOneofUint32()).isTrue()
}
testAllTypes {
assertThat(hasOptionalInt32()).isFalse()
optionalString = "115"
assertThat(hasOptionalString()).isTrue()
assertThat(hasOptionalGroup()).isFalse()
optionalNestedMessage = TestAllTypesKt.nestedMessage { bb = 118 }
assertThat(hasOptionalNestedMessage()).isTrue()
assertThat(hasOptionalNestedEnum()).isFalse()
defaultInt32 = 401
assertThat(hasDefaultInt32()).isTrue()
assertThat(hasOneofUint32()).isFalse()
}
}
@Test
fun testClears() {
testAllTypes {
optionalInt32 = 101
clearOptionalInt32()
assertThat(hasOptionalInt32()).isFalse()
optionalString = "115"
clearOptionalString()
assertThat(hasOptionalString()).isFalse()
optionalGroup = TestAllTypesKt.optionalGroup { a = 117 }
clearOptionalGroup()
assertThat(hasOptionalGroup()).isFalse()
optionalNestedMessage = TestAllTypesKt.nestedMessage { bb = 118 }
clearOptionalNestedMessage()
assertThat(hasOptionalNestedMessage()).isFalse()
optionalNestedEnum = NestedEnum.BAZ
clearOptionalNestedEnum()
assertThat(hasOptionalNestedEnum()).isFalse()
defaultInt32 = 401
clearDefaultInt32()
assertThat(hasDefaultInt32()).isFalse()
oneofUint32 = 601
clearOneofUint32()
assertThat(hasOneofUint32()).isFalse()
}
}
@Test
fun testCopy() {
val message = testAllTypes {
optionalInt32 = 101
optionalString = "115"
}
val modifiedMessage = message.copy {
optionalInt32 = 201
}
assertThat(message).isEqualTo(
TestAllTypes.newBuilder()
.setOptionalInt32(101)
.setOptionalString("115")
.build()
)
assertThat(modifiedMessage).isEqualTo(
TestAllTypes.newBuilder()
.setOptionalInt32(201)
.setOptionalString("115")
.build()
)
}
@Test
fun testOneof() {
val message = testAllTypes {
oneofString = "foo"
assertThat(oneofFieldCase)
.isEqualTo(TestAllTypes.OneofFieldCase.ONEOF_STRING)
assertThat(oneofString).isEqualTo("foo")
clearOneofField()
assertThat(hasOneofUint32()).isFalse()
assertThat(oneofFieldCase)
.isEqualTo(TestAllTypes.OneofFieldCase.ONEOFFIELD_NOT_SET)
oneofUint32 = 5
}
assertThat(message.getOneofFieldCase())
.isEqualTo(TestAllTypes.OneofFieldCase.ONEOF_UINT32)
assertThat(message.getOneofUint32()).isEqualTo(5)
}
@Test
fun testExtensionsSet() {
assertThat(
testAllExtensions {
this[UnittestProto.optionalInt32Extension] = 101
this[UnittestProto.optionalInt64Extension] = 102L
this[UnittestProto.optionalUint32Extension] = 103
this[UnittestProto.optionalUint64Extension] = 104L
this[UnittestProto.optionalSint32Extension] = 105
this[UnittestProto.optionalSint64Extension] = 106L
this[UnittestProto.optionalFixed32Extension] = 107
this[UnittestProto.optionalFixed64Extension] = 108L
this[UnittestProto.optionalSfixed32Extension] = 109
this[UnittestProto.optionalSfixed64Extension] = 110L
this[UnittestProto.optionalFloatExtension] = 111F
this[UnittestProto.optionalDoubleExtension] = 112.0
this[UnittestProto.optionalBoolExtension] = true
this[UnittestProto.optionalStringExtension] = "115"
this[UnittestProto.optionalBytesExtension] = toBytes("116")
this[UnittestProto.optionalGroupExtension] = optionalGroupExtension { a = 117 }
this[UnittestProto.optionalNestedMessageExtension] =
TestAllTypesKt.nestedMessage { bb = 118 }
this[UnittestProto.optionalForeignMessageExtension] = foreignMessage { c = 119 }
this[UnittestProto.optionalImportMessageExtension] =
ImportMessage.newBuilder().setD(120).build()
this[UnittestProto.optionalPublicImportMessageExtension] =
PublicImportMessage.newBuilder().setE(126).build()
this[UnittestProto.optionalLazyMessageExtension] = TestAllTypesKt.nestedMessage { bb = 127 }
this[UnittestProto.optionalNestedEnumExtension] = NestedEnum.BAZ
this[UnittestProto.optionalForeignEnumExtension] = ForeignEnum.FOREIGN_BAZ
this[UnittestProto.optionalImportEnumExtension] = ImportEnum.IMPORT_BAZ
this[UnittestProto.optionalStringPieceExtension] = "124"
this[UnittestProto.optionalCordExtension] = "125"
this[UnittestProto.repeatedInt32Extension].add(201)
this[UnittestProto.repeatedInt64Extension].add(202L)
this[UnittestProto.repeatedUint32Extension].add(203)
this[UnittestProto.repeatedUint64Extension].add(204L)
this[UnittestProto.repeatedSint32Extension].add(205)
this[UnittestProto.repeatedSint64Extension].add(206L)
this[UnittestProto.repeatedFixed32Extension].add(207)
this[UnittestProto.repeatedFixed64Extension].add(208L)
this[UnittestProto.repeatedSfixed32Extension].add(209)
this[UnittestProto.repeatedSfixed64Extension].add(210L)
this[UnittestProto.repeatedFloatExtension].add(211F)
this[UnittestProto.repeatedDoubleExtension].add(212.0)
this[UnittestProto.repeatedBoolExtension].add(true)
this[UnittestProto.repeatedStringExtension].add("215")
this[UnittestProto.repeatedBytesExtension].add(toBytes("216"))
this[UnittestProto.repeatedGroupExtension].add(repeatedGroupExtension { a = 217 })
this[UnittestProto.repeatedNestedMessageExtension]
.add(TestAllTypesKt.nestedMessage { bb = 218 })
this[UnittestProto.repeatedForeignMessageExtension].add(foreignMessage { c = 219 })
this[UnittestProto.repeatedImportMessageExtension]
.add(ImportMessage.newBuilder().setD(220).build())
this[UnittestProto.repeatedLazyMessageExtension]
.add(TestAllTypesKt.nestedMessage { bb = 227 })
this[UnittestProto.repeatedNestedEnumExtension].add(NestedEnum.BAR)
this[UnittestProto.repeatedForeignEnumExtension].add(ForeignEnum.FOREIGN_BAR)
this[UnittestProto.repeatedImportEnumExtension].add(ImportEnum.IMPORT_BAR)
this[UnittestProto.repeatedStringPieceExtension].add("224")
this[UnittestProto.repeatedCordExtension].add("225")
this[UnittestProto.repeatedInt32Extension] += 301
this[UnittestProto.repeatedInt64Extension] += 302L
this[UnittestProto.repeatedUint32Extension] += 303
this[UnittestProto.repeatedUint64Extension] += 304L
this[UnittestProto.repeatedSint32Extension] += 305
this[UnittestProto.repeatedSint64Extension] += 306L
this[UnittestProto.repeatedFixed32Extension] += 307
this[UnittestProto.repeatedFixed64Extension] += 308L
this[UnittestProto.repeatedSfixed32Extension] += 309
this[UnittestProto.repeatedSfixed64Extension] += 310L
this[UnittestProto.repeatedFloatExtension] += 311F
this[UnittestProto.repeatedDoubleExtension] += 312.0
this[UnittestProto.repeatedBoolExtension] += false
this[UnittestProto.repeatedStringExtension] += "315"
this[UnittestProto.repeatedBytesExtension] += toBytes("316")
this[UnittestProto.repeatedGroupExtension] += repeatedGroupExtension { a = 317 }
this[UnittestProto.repeatedNestedMessageExtension] +=
TestAllTypesKt.nestedMessage { bb = 318 }
this[UnittestProto.repeatedForeignMessageExtension] += foreignMessage { c = 319 }
this[UnittestProto.repeatedImportMessageExtension] +=
ImportMessage.newBuilder().setD(320).build()
this[UnittestProto.repeatedLazyMessageExtension] +=
TestAllTypesKt.nestedMessage { bb = 327 }
this[UnittestProto.repeatedNestedEnumExtension] += NestedEnum.BAZ
this[UnittestProto.repeatedForeignEnumExtension] += ForeignEnum.FOREIGN_BAZ
this[UnittestProto.repeatedImportEnumExtension] += ImportEnum.IMPORT_BAZ
this[UnittestProto.repeatedStringPieceExtension] += "324"
this[UnittestProto.repeatedCordExtension] += "325"
this[UnittestProto.defaultInt32Extension] = 401
this[UnittestProto.defaultInt64Extension] = 402L
this[UnittestProto.defaultUint32Extension] = 403
this[UnittestProto.defaultUint64Extension] = 404L
this[UnittestProto.defaultSint32Extension] = 405
this[UnittestProto.defaultSint64Extension] = 406L
this[UnittestProto.defaultFixed32Extension] = 407
this[UnittestProto.defaultFixed64Extension] = 408L
this[UnittestProto.defaultSfixed32Extension] = 409
this[UnittestProto.defaultSfixed64Extension] = 410L
this[UnittestProto.defaultFloatExtension] = 411F
this[UnittestProto.defaultDoubleExtension] = 412.0
this[UnittestProto.defaultBoolExtension] = false
this[UnittestProto.defaultStringExtension] = "415"
this[UnittestProto.defaultBytesExtension] = toBytes("416")
this[UnittestProto.defaultNestedEnumExtension] = NestedEnum.FOO
this[UnittestProto.defaultForeignEnumExtension] = ForeignEnum.FOREIGN_FOO
this[UnittestProto.defaultImportEnumExtension] = ImportEnum.IMPORT_FOO
this[UnittestProto.defaultStringPieceExtension] = "424"
this[UnittestProto.defaultCordExtension] = "425"
this[UnittestProto.oneofUint32Extension] = 601
this[UnittestProto.oneofNestedMessageExtension] = TestAllTypesKt.nestedMessage { bb = 602 }
this[UnittestProto.oneofStringExtension] = "603"
this[UnittestProto.oneofBytesExtension] = toBytes("604")
}
).isEqualTo(
TestUtil.getAllExtensionsSet()
)
}
@Test
fun testExtensionGetters() {
testAllExtensions {
this[UnittestProto.optionalInt32Extension] = 101
assertThat(this[UnittestProto.optionalInt32Extension]).isEqualTo(101)
this[UnittestProto.optionalStringExtension] = "115"
assertThat(this[UnittestProto.optionalStringExtension]).isEqualTo("115")
this[UnittestProto.optionalGroupExtension] = optionalGroupExtension { a = 117 }
assertThat(this[UnittestProto.optionalGroupExtension])
.isEqualTo(optionalGroupExtension { a = 117 })
this[UnittestProto.optionalNestedMessageExtension] =
TestAllTypesKt.nestedMessage { bb = 118 }
assertThat(this[UnittestProto.optionalNestedMessageExtension])
.isEqualTo(TestAllTypesKt.nestedMessage { bb = 118 })
this[UnittestProto.optionalNestedEnumExtension] = NestedEnum.BAZ
assertThat(this[UnittestProto.optionalNestedEnumExtension]).isEqualTo(NestedEnum.BAZ)
this[UnittestProto.defaultInt32Extension] = 401
assertThat(this[UnittestProto.defaultInt32Extension]).isEqualTo(401)
this[UnittestProto.oneofUint32Extension] = 601
assertThat(this[UnittestProto.oneofUint32Extension]).isEqualTo(601)
}
}
@Test
fun testRepeatedExtensionGettersAndSetters() {
testAllExtensions {
this[UnittestProto.repeatedInt32Extension].addAll(listOf(1, 2))
assertThat(this[UnittestProto.repeatedInt32Extension]).isEqualTo(listOf(1, 2))
this[UnittestProto.repeatedInt32Extension] += listOf(3, 4)
assertThat(this[UnittestProto.repeatedInt32Extension]).isEqualTo(listOf(1, 2, 3, 4))
this[UnittestProto.repeatedInt32Extension][0] = 5
assertThat(this[UnittestProto.repeatedInt32Extension]).isEqualTo(listOf(5, 2, 3, 4))
this[UnittestProto.repeatedStringExtension].addAll(listOf("1", "2"))
assertThat(this[UnittestProto.repeatedStringExtension]).isEqualTo(listOf("1", "2"))
this[UnittestProto.repeatedStringExtension] += listOf("3", "4")
assertThat(this[UnittestProto.repeatedStringExtension]).isEqualTo(listOf("1", "2", "3", "4"))
this[UnittestProto.repeatedStringExtension][0] = "5"
assertThat(this[UnittestProto.repeatedStringExtension]).isEqualTo(listOf("5", "2", "3", "4"))
this[UnittestProto.repeatedGroupExtension].addAll(
listOf(
repeatedGroupExtension { a = 1 },
repeatedGroupExtension { a = 2 }
)
)
assertThat(this[UnittestProto.repeatedGroupExtension]).isEqualTo(
listOf(
repeatedGroupExtension { a = 1 },
repeatedGroupExtension { a = 2 }
)
)
this[UnittestProto.repeatedGroupExtension] +=
listOf(
repeatedGroupExtension { a = 3 },
repeatedGroupExtension { a = 4 }
)
assertThat(this[UnittestProto.repeatedGroupExtension]).isEqualTo(
listOf(
repeatedGroupExtension { a = 1 },
repeatedGroupExtension { a = 2 },
repeatedGroupExtension { a = 3 },
repeatedGroupExtension { a = 4 }
)
)
this[UnittestProto.repeatedGroupExtension][0] = repeatedGroupExtension { a = 5 }
assertThat(this[UnittestProto.repeatedGroupExtension]).isEqualTo(
listOf(
repeatedGroupExtension { a = 5 },
repeatedGroupExtension { a = 2 },
repeatedGroupExtension { a = 3 },
repeatedGroupExtension { a = 4 }
)
)
this[UnittestProto.repeatedNestedMessageExtension].addAll(
listOf(nestedMessage { bb = 1 }, nestedMessage { bb = 2 })
)
assertThat(this[UnittestProto.repeatedNestedMessageExtension]).isEqualTo(
listOf(nestedMessage { bb = 1 }, nestedMessage { bb = 2 })
)
this[UnittestProto.repeatedNestedMessageExtension] +=
listOf(nestedMessage { bb = 3 }, nestedMessage { bb = 4 })
assertThat(this[UnittestProto.repeatedNestedMessageExtension]).isEqualTo(
listOf(
nestedMessage { bb = 1 },
nestedMessage { bb = 2 },
nestedMessage { bb = 3 },
nestedMessage { bb = 4 }
)
)
this[UnittestProto.repeatedNestedMessageExtension][0] = nestedMessage { bb = 5 }
assertThat(this[UnittestProto.repeatedNestedMessageExtension]).isEqualTo(
listOf(
nestedMessage { bb = 5 },
nestedMessage { bb = 2 },
nestedMessage { bb = 3 },
nestedMessage { bb = 4 }
)
)
this[UnittestProto.repeatedNestedEnumExtension]
.addAll(listOf(NestedEnum.FOO, NestedEnum.BAR))
assertThat(this[UnittestProto.repeatedNestedEnumExtension])
.isEqualTo(listOf(NestedEnum.FOO, NestedEnum.BAR))
this[UnittestProto.repeatedNestedEnumExtension] += listOf(NestedEnum.BAZ, NestedEnum.FOO)
assertThat(this[UnittestProto.repeatedNestedEnumExtension]).isEqualTo(
listOf(NestedEnum.FOO, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
)
}
}
@Test
fun testExtensionContains() {
testAllExtensions {
this[UnittestProto.optionalInt32Extension] = 101
assertThat(contains(UnittestProto.optionalInt32Extension)).isTrue()
assertThat(contains(UnittestProto.optionalStringExtension)).isFalse()
this[UnittestProto.optionalGroupExtension] = optionalGroupExtension { a = 117 }
assertThat(contains(UnittestProto.optionalGroupExtension)).isTrue()
assertThat(contains(UnittestProto.optionalNestedMessageExtension)).isFalse()
this[UnittestProto.optionalNestedEnumExtension] = NestedEnum.BAZ
assertThat(contains(UnittestProto.optionalNestedEnumExtension)).isTrue()
assertThat(contains(UnittestProto.defaultInt32Extension)).isFalse()
this[UnittestProto.oneofUint32Extension] = 601
assertThat(contains(UnittestProto.optionalInt32Extension)).isTrue()
}
testAllExtensions {
assertThat(contains(UnittestProto.optionalInt32Extension)).isFalse()
this[UnittestProto.optionalStringExtension] = "115"
assertThat(contains(UnittestProto.optionalStringExtension)).isTrue()
assertThat(contains(UnittestProto.optionalGroupExtension)).isFalse()
this[UnittestProto.optionalNestedMessageExtension] =
TestAllTypesKt.nestedMessage { bb = 118 }
assertThat(contains(UnittestProto.optionalNestedMessageExtension)).isTrue()
assertThat(contains(UnittestProto.optionalNestedEnumExtension)).isFalse()
this[UnittestProto.defaultInt32Extension] = 401
assertThat(contains(UnittestProto.defaultInt32Extension)).isTrue()
assertThat(contains(UnittestProto.oneofUint32Extension)).isFalse()
}
}
@Test
fun testExtensionClears() {
testAllExtensions {
this[UnittestProto.optionalInt32Extension] = 101
clear(UnittestProto.optionalInt32Extension)
assertThat(contains(UnittestProto.optionalInt32Extension)).isFalse()
this[UnittestProto.optionalStringExtension] = "115"
clear(UnittestProto.optionalStringExtension)
assertThat(contains(UnittestProto.optionalStringExtension)).isFalse()
this[UnittestProto.optionalGroupExtension] = optionalGroupExtension { a = 117 }
clear(UnittestProto.optionalGroupExtension)
assertThat(contains(UnittestProto.optionalGroupExtension)).isFalse()
this[UnittestProto.optionalNestedMessageExtension] =
TestAllTypesKt.nestedMessage { bb = 118 }
clear(UnittestProto.optionalNestedMessageExtension)
assertThat(contains(UnittestProto.optionalNestedMessageExtension)).isFalse()
this[UnittestProto.optionalNestedEnumExtension] = NestedEnum.BAZ
clear(UnittestProto.optionalNestedEnumExtension)
assertThat(contains(UnittestProto.optionalNestedEnumExtension)).isFalse()
this[UnittestProto.defaultInt32Extension] = 401
clear(UnittestProto.defaultInt32Extension)
assertThat(contains(UnittestProto.oneofUint32Extension)).isFalse()
}
}
@Test
fun testEmptyMessages() {
assertThat(
testEmptyMessage {}
).isEqualTo(
TestEmptyMessage.newBuilder().build()
)
assertThat(
testEmptyMessageWithExtensions {}
).isEqualTo(
TestEmptyMessageWithExtensions.newBuilder().build()
)
}
@Test
fun testMapSetters() {
val intMap = testIntIntMap { m[1] = 2 }
assertThat(intMap).isEqualTo(
TestIntIntMap.newBuilder().putM(1, 2).build()
)
assertThat(
testMaps {
mInt32[1] = intMap
mInt64[1L] = intMap
mUint32[1] = intMap
mUint64[1L] = intMap
mSint32[1] = intMap
mSint64[1L] = intMap
mFixed32[1] = intMap
mFixed64[1L] = intMap
mSfixed32[1] = intMap
mSfixed64[1] = intMap
mBool[true] = intMap
mString["1"] = intMap
}
).isEqualTo(
TestMaps.newBuilder()
.putMInt32(1, intMap)
.putMInt64(1L, intMap)
.putMUint32(1, intMap)
.putMUint64(1L, intMap)
.putMSint32(1, intMap)
.putMSint64(1L, intMap)
.putMFixed32(1, intMap)
.putMFixed64(1L, intMap)
.putMSfixed32(1, intMap)
.putMSfixed64(1L, intMap)
.putMBool(true, intMap)
.putMString("1", intMap)
.build()
)
assertThat(
testEnumMap {
knownMapField[1] = Proto2MapEnum.PROTO2_MAP_ENUM_FOO
}
).isEqualTo(
TestEnumMap.newBuilder()
.putKnownMapField(1, Proto2MapEnum.PROTO2_MAP_ENUM_FOO)
.build()
)
}
@Test
fun testMapGettersAndSetters() {
val intMap =
testIntIntMap {
m.put(1, 2)
assertThat(m).isEqualTo(mapOf(1 to 2))
m[3] = 4
assertThat(m).isEqualTo(mapOf(1 to 2, 3 to 4))
m.putAll(mapOf(5 to 6, 7 to 8))
assertThat(m).isEqualTo(mapOf(1 to 2, 3 to 4, 5 to 6, 7 to 8))
}
testMaps {
mInt32.put(1, intMap)
assertThat(mInt32).isEqualTo(mapOf(1 to intMap))
mInt32[2] = intMap
assertThat(mInt32).isEqualTo(mapOf(1 to intMap, 2 to intMap))
mInt32.putAll(mapOf(3 to intMap, 4 to intMap))
assertThat(mInt32).isEqualTo(mapOf(1 to intMap, 2 to intMap, 3 to intMap, 4 to intMap))
mString.put("1", intMap)
assertThat(mString).isEqualTo(mapOf("1" to intMap))
mString["2"] = intMap
assertThat(mString).isEqualTo(mapOf("1" to intMap, "2" to intMap))
mString.putAll(mapOf("3" to intMap, "4" to intMap))
assertThat(mString).isEqualTo(
mapOf("1" to intMap, "2" to intMap, "3" to intMap, "4" to intMap)
)
}
testEnumMap {
knownMapField.put(1, Proto2MapEnum.PROTO2_MAP_ENUM_FOO)
assertThat(knownMapField).isEqualTo(mapOf(1 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO))
knownMapField[2] = Proto2MapEnum.PROTO2_MAP_ENUM_BAR
assertThat(knownMapField).isEqualTo(
mapOf(1 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO, 2 to Proto2MapEnum.PROTO2_MAP_ENUM_BAR)
)
knownMapField.putAll(
mapOf(3 to Proto2MapEnum.PROTO2_MAP_ENUM_BAZ, 4 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO)
)
assertThat(knownMapField).isEqualTo(
mapOf(
1 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO,
2 to Proto2MapEnum.PROTO2_MAP_ENUM_BAR,
3 to Proto2MapEnum.PROTO2_MAP_ENUM_BAZ,
4 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO
)
)
}
}
@Test
fun testMapRemove() {
val intMap =
testIntIntMap {
m.putAll(mapOf(1 to 2, 3 to 4))
m.remove(1)
assertThat(m).isEqualTo(mapOf(3 to 4))
}
testMaps {
mInt32.putAll(mapOf(1 to intMap, 2 to intMap))
mInt32.remove(1)
assertThat(mInt32).isEqualTo(mapOf(2 to intMap))
mString.putAll(mapOf("1" to intMap, "2" to intMap))
mString.remove("1")
assertThat(mString).isEqualTo(mapOf("2" to intMap))
}
testEnumMap {
knownMapField.putAll(
mapOf(1 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO, 2 to Proto2MapEnum.PROTO2_MAP_ENUM_BAR)
)
knownMapField.remove(1)
assertThat(knownMapField).isEqualTo(mapOf(2 to Proto2MapEnum.PROTO2_MAP_ENUM_BAR))
}
}
@Test
fun testMapClear() {
val intMap =
testIntIntMap {
m.putAll(mapOf(1 to 2, 3 to 4))
m.clear()
assertThat(m.isEmpty()).isTrue()
}
testMaps {
mInt32.putAll(mapOf(1 to intMap, 2 to intMap))
mInt32.clear()
assertThat(mInt32.isEmpty()).isTrue()
mString.putAll(mapOf("1" to intMap, "2" to intMap))
mString.clear()
assertThat(mString.isEmpty()).isTrue()
}
testEnumMap {
knownMapField.putAll(
mapOf(1 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO, 2 to Proto2MapEnum.PROTO2_MAP_ENUM_BAR)
)
knownMapField.clear()
assertThat(knownMapField.isEmpty()).isTrue()
}
}
@Test
fun testEvilNames() {
assertThat(
evilNamesProto2 {
initialized = true
hasFoo = true
bar = "foo"
isInitialized = true
fooBar = "foo"
aLLCAPS += "foo"
aLLCAPSMAP[1] = true
hasUnderbarPrecedingNumeric1Foo = true
hasUnderbarPrecedingNumeric42Bar = true
hasUnderbarPrecedingNumeric123Foo42BarBaz = true
extension += "foo"
class_ += 1
int = 1.0
long = true
boolean = 1L
sealed = "foo"
interface_ = 1F
in_ = 1
object_ = "foo"
cachedSize_ = "foo"
serializedSize_ = true
by = "foo"
}
).isEqualTo(
EvilNamesProto2.newBuilder()
.setInitialized(true)
.setHasFoo(true)
.setBar("foo")
.setIsInitialized(true)
.setFooBar("foo")
.addALLCAPS("foo")
.putALLCAPSMAP(1, true)
.setHasUnderbarPrecedingNumeric1Foo(true)
.setHasUnderbarPrecedingNumeric42Bar(true)
.setHasUnderbarPrecedingNumeric123Foo42BarBaz(true)
.addExtension("foo")
.addClass_(1)
.setInt(1.0)
.setLong(true)
.setBoolean(1L)
.setSealed("foo")
.setInterface(1F)
.setIn(1)
.setObject("foo")
.setCachedSize_("foo")
.setSerializedSize_(true)
.setBy("foo")
.build()
)
assertThat(interface_ {}).isEqualTo(Interface.newBuilder().build())
}
@Test
fun testHardKeywordGettersAndSetters() {
hardKeywordsAllTypes {
as_ = 1
assertThat(as_).isEqualTo(1)
in_ = "foo"
assertThat(in_).isEqualTo("foo")
break_ = HardKeywordsAllTypes.NestedEnum.FOO
assertThat(break_).isEqualTo(HardKeywordsAllTypes.NestedEnum.FOO)
do_ = HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }
assertThat(do_).isEqualTo(HardKeywordsAllTypesKt.nestedMessage { while_ = 1 })
continue_[1] = 1
assertThat(continue_[1]).isEqualTo(1)
else_ += 1
assertThat(else_).isEqualTo(listOf(1))
for_ += "foo"
assertThat(for_).isEqualTo(listOf("foo"))
fun_ += HardKeywordsAllTypes.NestedEnum.FOO
assertThat(fun_).isEqualTo(listOf(HardKeywordsAllTypes.NestedEnum.FOO))
if_ += HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }
assertThat(if_).isEqualTo(listOf(HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }))
}
}
@Test
fun testHardKeywordHazzers() {
hardKeywordsAllTypes {
as_ = 1
assertThat(hasAs_()).isTrue()
in_ = "foo"
assertThat(hasIn_()).isTrue()
break_ = HardKeywordsAllTypes.NestedEnum.FOO
assertThat(hasBreak_()).isTrue()
do_ = HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }
assertThat(hasDo_()).isTrue()
}
}
@Test
fun testHardKeywordClears() {
hardKeywordsAllTypes {
as_ = 1
clearAs_()
assertThat(hasAs_()).isFalse()
in_ = "foo"
clearIn_()
assertThat(hasIn_()).isFalse()
break_ = HardKeywordsAllTypes.NestedEnum.FOO
clearBreak_()
assertThat(hasBreak_()).isFalse()
do_ = HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }
clearDo_()
assertThat(hasDo_()).isFalse()
}
}
}

@ -0,0 +1,335 @@
package com.google.protobuf.kotlin
import com.google.common.truth.Truth.assertThat
import com.google.protobuf.kotlin.generator.EvilNamesProto3OuterClass.Class
import com.google.protobuf.kotlin.generator.EvilNamesProto3OuterClass.EvilNamesProto3
import com.google.protobuf.kotlin.generator.EvilNamesProto3OuterClass.HardKeywordsAllTypes
import com.google.protobuf.kotlin.generator.HardKeywordsAllTypesKt
import com.google.protobuf.kotlin.generator.class_
import com.google.protobuf.kotlin.generator.evilNamesProto3
import com.google.protobuf.kotlin.generator.hardKeywordsAllTypes
import com.google.protos.proto3_unittest.TestAllTypesKt
import com.google.protos.proto3_unittest.TestAllTypesKt.nestedMessage
import com.google.protos.proto3_unittest.UnittestProto3.TestAllTypes
import com.google.protos.proto3_unittest.UnittestProto3.TestAllTypes.NestedEnum
import com.google.protos.proto3_unittest.UnittestProto3.TestEmptyMessage
import com.google.protos.proto3_unittest.copy
import com.google.protos.proto3_unittest.testAllTypes
import com.google.protos.proto3_unittest.testEmptyMessage
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@RunWith(JUnit4::class)
class Proto3Test {
@Test
fun testGettersAndSetters() {
testAllTypes {
optionalInt32 = 101
assertThat(optionalInt32).isEqualTo(101)
optionalString = "115"
assertThat(optionalString).isEqualTo("115")
optionalNestedMessage = TestAllTypesKt.nestedMessage { bb = 118 }
assertThat(optionalNestedMessage).isEqualTo(TestAllTypesKt.nestedMessage { bb = 118 })
optionalNestedEnum = NestedEnum.BAZ
assertThat(optionalNestedEnum).isEqualTo(NestedEnum.BAZ)
oneofUint32 = 601
assertThat(oneofUint32).isEqualTo(601)
}
}
@Test
fun testRepeatedGettersAndSetters() {
testAllTypes {
repeatedInt32.addAll(listOf(1, 2))
assertThat(repeatedInt32).isEqualTo(listOf(1, 2))
repeatedInt32 += listOf(3, 4)
assertThat(repeatedInt32).isEqualTo(listOf(1, 2, 3, 4))
repeatedInt32[0] = 5
assertThat(repeatedInt32).isEqualTo(listOf(5, 2, 3, 4))
repeatedString.addAll(listOf("1", "2"))
assertThat(repeatedString).isEqualTo(listOf("1", "2"))
repeatedString += listOf("3", "4")
assertThat(repeatedString).isEqualTo(listOf("1", "2", "3", "4"))
repeatedString[0] = "5"
assertThat(repeatedString).isEqualTo(listOf("5", "2", "3", "4"))
repeatedNestedMessage.addAll(listOf(nestedMessage { bb = 1 }, nestedMessage { bb = 2 }))
assertThat(repeatedNestedMessage).isEqualTo(
listOf(
nestedMessage { bb = 1 },
nestedMessage { bb = 2 }
)
)
repeatedNestedMessage += listOf(nestedMessage { bb = 3 }, nestedMessage { bb = 4 })
assertThat(repeatedNestedMessage).isEqualTo(
listOf(
nestedMessage { bb = 1 },
nestedMessage { bb = 2 },
nestedMessage { bb = 3 },
nestedMessage { bb = 4 }
)
)
repeatedNestedMessage[0] = nestedMessage { bb = 5 }
assertThat(repeatedNestedMessage).isEqualTo(
listOf(
nestedMessage { bb = 5 },
nestedMessage { bb = 2 },
nestedMessage { bb = 3 },
nestedMessage { bb = 4 }
)
)
repeatedNestedEnum.addAll(listOf(NestedEnum.FOO, NestedEnum.BAR))
assertThat(repeatedNestedEnum).isEqualTo(listOf(NestedEnum.FOO, NestedEnum.BAR))
repeatedNestedEnum += listOf(NestedEnum.BAZ, NestedEnum.FOO)
assertThat(repeatedNestedEnum).isEqualTo(
listOf(NestedEnum.FOO, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
)
repeatedNestedEnum[0] = NestedEnum.BAR
assertThat(repeatedNestedEnum).isEqualTo(
listOf(NestedEnum.BAR, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
)
}
}
@Test
fun testClears() {
assertThat(
testAllTypes {
optionalInt32 = 101
clearOptionalInt32()
optionalString = "115"
clearOptionalString()
optionalNestedMessage = TestAllTypesKt.nestedMessage { bb = 118 }
clearOptionalNestedMessage()
optionalNestedEnum = NestedEnum.BAZ
clearOptionalNestedEnum()
oneofUint32 = 601
clearOneofUint32()
}
).isEqualTo(
TestAllTypes.newBuilder().build()
)
}
@Test
fun testCopy() {
val message = testAllTypes {
optionalInt32 = 101
optionalString = "115"
}
val modifiedMessage = message.copy {
optionalInt32 = 201
}
assertThat(message).isEqualTo(
TestAllTypes.newBuilder()
.setOptionalInt32(101)
.setOptionalString("115")
.build()
)
assertThat(modifiedMessage).isEqualTo(
TestAllTypes.newBuilder()
.setOptionalInt32(201)
.setOptionalString("115")
.build()
)
}
@Test
fun testOneof() {
val message = testAllTypes {
oneofString = "foo"
assertThat(oneofFieldCase)
.isEqualTo(TestAllTypes.OneofFieldCase.ONEOF_STRING)
assertThat(oneofString).isEqualTo("foo")
clearOneofField()
assertThat(oneofFieldCase)
.isEqualTo(TestAllTypes.OneofFieldCase.ONEOFFIELD_NOT_SET)
oneofUint32 = 5
}
assertThat(message.getOneofFieldCase())
.isEqualTo(TestAllTypes.OneofFieldCase.ONEOF_UINT32)
assertThat(message.getOneofUint32()).isEqualTo(5)
}
@Test
fun testEmptyMessages() {
assertThat(
testEmptyMessage {}
).isEqualTo(
TestEmptyMessage.newBuilder().build()
)
}
@Test
fun testEvilNames() {
assertThat(
evilNamesProto3 {
initialized = true
hasFoo = true
bar = "foo"
isInitialized = true
fooBar = "foo"
aLLCAPS += "foo"
aLLCAPSMAP[1] = true
hasUnderbarPrecedingNumeric1Foo = true
hasUnderbarPrecedingNumeric42Bar = true
hasUnderbarPrecedingNumeric123Foo42BarBaz = true
extension += "foo"
class_ = "foo"
int = 1.0
long = true
boolean = 1L
sealed = "foo"
interface_ = 1F
in_ = 1
object_ = "foo"
cachedSize_ = "foo"
serializedSize_ = true
value = "foo"
index = 1L
values += "foo"
newValues += "foo"
builder = true
k[1] = 1
v["foo"] = "foo"
key["foo"] = 1
map[1] = "foo"
pairs["foo"] = 1
LeadingUnderscore = "foo"
option = 1
}
).isEqualTo(
EvilNamesProto3.newBuilder()
.setInitialized(true)
.setHasFoo(true)
.setBar("foo")
.setIsInitialized(true)
.setFooBar("foo")
.addALLCAPS("foo")
.putALLCAPSMAP(1, true)
.setHasUnderbarPrecedingNumeric1Foo(true)
.setHasUnderbarPrecedingNumeric42Bar(true)
.setHasUnderbarPrecedingNumeric123Foo42BarBaz(true)
.addExtension("foo")
.setClass_("foo")
.setInt(1.0)
.setLong(true)
.setBoolean(1L)
.setSealed("foo")
.setInterface(1F)
.setIn(1)
.setObject("foo")
.setCachedSize_("foo")
.setSerializedSize_(true)
.setValue("foo")
.setIndex(1L)
.addValues("foo")
.addNewValues("foo")
.setBuilder(true)
.putK(1, 1)
.putV("foo", "foo")
.putKey("foo", 1)
.putMap(1, "foo")
.putPairs("foo", 1)
.setLeadingUnderscore("foo")
.setOption(1)
.build()
)
assertThat(class_ {}).isEqualTo(Class.newBuilder().build())
}
@Test
fun testHardKeywordGettersAndSetters() {
hardKeywordsAllTypes {
as_ = 1
assertThat(as_).isEqualTo(1)
in_ = "foo"
assertThat(in_).isEqualTo("foo")
break_ = HardKeywordsAllTypes.NestedEnum.FOO
assertThat(break_).isEqualTo(HardKeywordsAllTypes.NestedEnum.FOO)
do_ = HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }
assertThat(do_).isEqualTo(HardKeywordsAllTypesKt.nestedMessage { while_ = 1 })
continue_[1] = 1
assertThat(continue_[1]).isEqualTo(1)
else_ += 1
assertThat(else_).isEqualTo(listOf(1))
for_ += "foo"
assertThat(for_).isEqualTo(listOf("foo"))
fun_ += HardKeywordsAllTypes.NestedEnum.FOO
assertThat(fun_).isEqualTo(listOf(HardKeywordsAllTypes.NestedEnum.FOO))
if_ += HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }
assertThat(if_).isEqualTo(listOf(HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }))
}
}
@Test
fun testHardKeywordHazzers() {
hardKeywordsAllTypes {
as_ = 1
assertThat(hasAs_()).isTrue()
in_ = "foo"
assertThat(hasIn_()).isTrue()
break_ = HardKeywordsAllTypes.NestedEnum.FOO
assertThat(hasBreak_()).isTrue()
do_ = HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }
assertThat(hasDo_()).isTrue()
}
}
@Test
fun testHardKeywordClears() {
hardKeywordsAllTypes {
as_ = 1
clearAs_()
assertThat(hasAs_()).isFalse()
in_ = "foo"
clearIn_()
assertThat(hasIn_()).isFalse()
break_ = HardKeywordsAllTypes.NestedEnum.FOO
clearBreak_()
assertThat(hasBreak_()).isFalse()
do_ = HardKeywordsAllTypesKt.nestedMessage { while_ = 1 }
clearDo_()
assertThat(hasDo_()).isFalse()
}
}
@Test
fun testMultipleFiles() {
assertThat(
com.google.protobuf.kotlin.generator.multipleFilesMessageA {}
).isEqualTo(
com.google.protobuf.kotlin.generator.MultipleFilesMessageA.newBuilder().build()
)
assertThat(
com.google.protobuf.kotlin.generator.multipleFilesMessageB {}
).isEqualTo(
com.google.protobuf.kotlin.generator.MultipleFilesMessageB.newBuilder().build()
)
}
}

@ -0,0 +1,63 @@
// LINT: LEGACY_NAMES
syntax = "proto2";
package protobuf.kotlin.generator;
option java_package = "com.google.protobuf.kotlin.generator";
message EvilNamesProto2 {
optional bool initialized = 1;
optional bool has_foo = 2;
optional string Bar = 3;
optional bool is_initialized = 4;
oneof camelCase {
string fooBar = 5;
}
repeated string ALL_CAPS = 7;
map<int32, bool> ALL_CAPS_MAP = 8;
optional bool has_underbar_preceding_numeric_1foo = 9;
optional bool has_underbar_preceding_numeric_42bar = 13;
optional bool has_underbar_preceding_numeric_123foo42bar_baz = 14;
extensions 100 to max;
repeated string extension = 12;
repeated int32 class = 15;
optional double int = 16;
optional bool long = 17;
optional int64 boolean = 18;
optional string sealed = 19;
optional float interface = 20;
optional int32 in = 21;
optional string object = 22;
optional string cached_size = 23;
optional bool serialized_size = 24;
optional string by = 25;
}
message HardKeywordsAllTypes {
message NestedMessage {
optional int32 while = 1;
}
enum NestedEnum {
FOO = 1;
BAR = 2;
}
optional int32 as = 1;
optional string in = 2;
optional NestedEnum break = 3;
map<int32, int32> continue = 4;
optional NestedMessage do = 5;
repeated int32 else = 6;
repeated string for = 7;
repeated NestedEnum fun = 8;
repeated NestedMessage if = 9;
}
message Interface {}

@ -0,0 +1,77 @@
// LINT: LEGACY_NAMES
syntax = "proto3";
package protobuf.kotlin.generator;
option java_package = "com.google.protobuf.kotlin.generator";
message EvilNamesProto3 {
bool initialized = 1;
bool has_foo = 2;
string Bar = 3;
bool is_initialized = 4;
oneof camelCase {
string fooBar = 5;
}
repeated string ALL_CAPS = 7;
map<int32, bool> ALL_CAPS_MAP = 8;
bool has_underbar_preceding_numeric_1foo = 9;
bool has_underbar_preceding_numeric_42bar = 10;
bool has_underbar_preceding_numeric_123foo42bar_baz = 11;
repeated string extension = 12;
string class = 13;
double int = 14;
bool long = 15;
int64 boolean = 16;
string sealed = 17;
float interface = 18;
int32 in = 19;
string object = 20;
string cached_size = 21;
bool serialized_size = 22;
string value = 23;
int64 index = 24;
repeated string values = 25;
repeated string new_values = 26;
bool builder = 27;
map<int32, int32> k = 28;
map<string, string> v = 29;
map<string, int32> key = 30;
map<int32, string> map = 31;
map<string, int32> pairs = 32;
string _leading_underscore = 33;
oneof _leading_underscore_oneof {
int32 option = 34;
}
}
message HardKeywordsAllTypes {
message NestedMessage {
optional int32 while = 1;
}
enum NestedEnum {
ZERO = 0;
FOO = 1;
BAR = 2;
}
optional int32 as = 1;
optional string in = 2;
optional NestedEnum break = 3;
map<int32, int32> continue = 4;
optional NestedMessage do = 5;
repeated int32 else = 6;
repeated string for = 7;
repeated NestedEnum fun = 8;
repeated NestedMessage if = 9;
}
message Class {}

@ -0,0 +1,12 @@
syntax = "proto3";
package protobuf.kotlin.generator;
option java_package = "com.google.protobuf.kotlin.generator";
option java_multiple_files = true;
enum NestedEnum { FOO = 0; }
message MultipleFilesMessageA {}
message MultipleFilesMessageB {}

@ -0,0 +1,16 @@
syntax = "proto2";
package protobuf.kotlin.test;
option java_package = "com.google.protobuf.kotlin.test";
option java_multiple_files = true;
message ExampleExtensibleMessage {
extensions 10 to 20;
}
extend ExampleExtensibleMessage {
repeated int32 repeated_extension = 10;
repeated int32 different_extension = 11;
optional int32 int32_extension = 12;
}

@ -61,6 +61,7 @@ void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
(*variables)["type"] =
name_resolver->GetImmutableClassName(descriptor->enum_type());
(*variables)["kt_type"] = (*variables)["type"];
(*variables)["mutable_type"] =
name_resolver->GetMutableClassName(descriptor->enum_type());
(*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
@ -74,6 +75,11 @@ void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
// by the proto compiler
(*variables)["deprecation"] =
descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] =
descriptor->options().deprecated()
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
" is deprecated\") "
: "";
(*variables)["on_changed"] = "onChanged();";
// Use deprecated valueOf() method to be compatible with old generated code
// for v2.5.0/v2.6.1.
@ -268,6 +274,34 @@ void ImmutableEnumFieldGenerator::GenerateBuilderMembers(
printer->Annotate("{", "}", descriptor_);
}
void ImmutableEnumFieldGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$kt_deprecation$var $kt_name$: $kt_type$\n"
" @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
" get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
" @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
" set(value) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
" }\n");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"fun ${$clear$kt_capitalized_name$$}$() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}\n");
if (HasHazzer(descriptor_)) {
WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
printer->Print(variables_,
"fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
" return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
"}\n");
}
}
void ImmutableEnumFieldGenerator::GenerateFieldBuilderInitializationCode(
io::Printer* printer) const {
// noop for enums
@ -1035,6 +1069,98 @@ void RepeatedImmutableEnumFieldGenerator::GenerateHashCode(
"}\n");
}
void RepeatedImmutableEnumFieldGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
printer->Print(
variables_,
"/**\n"
" * An uninstantiable, behaviorless type to represent the field in\n"
" * generics.\n"
" */\n"
"@kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
"class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
" : com.google.protobuf.kotlin.DslProxy()\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$kt_deprecation$ val $kt_name$: "
"com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" @kotlin.jvm.JvmSynthetic\n"
" get() = com.google.protobuf.kotlin.DslList(\n"
" $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
" )\n");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"add(value: $kt_type$) {\n"
" $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(value: $kt_type$) {\n"
" add(value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
" $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
" addAll(values)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
"operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"set(index: kotlin.Int, value: $kt_type$) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"clear() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}");
}
std::string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const {
return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
}

@ -80,6 +80,7 @@ class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator {
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCode(io::Printer* printer) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;
@ -138,6 +139,7 @@ class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator {
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCode(io::Printer* printer) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;

@ -68,6 +68,7 @@ void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
(*variables)["type"] =
name_resolver->GetImmutableClassName(descriptor->enum_type());
(*variables)["kt_type"] = (*variables)["type"];
(*variables)["mutable_type"] =
name_resolver->GetMutableClassName(descriptor->enum_type());
(*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
@ -81,6 +82,11 @@ void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
// by the proto compiler
(*variables)["deprecation"] =
descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] =
descriptor->options().deprecated()
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
" is deprecated\") "
: "";
(*variables)["required"] = descriptor->is_required() ? "true" : "false";
if (HasHasbit(descriptor)) {
@ -273,6 +279,34 @@ void ImmutableEnumFieldLiteGenerator::GenerateBuilderMembers(
printer->Annotate("{", "}", descriptor_);
}
void ImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$kt_deprecation$var $kt_name$: $kt_type$\n"
" @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
" get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
" @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
" set(value) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
" }\n");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"fun ${$clear$kt_capitalized_name$$}$() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}\n");
if (HasHazzer(descriptor_)) {
WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
printer->Print(variables_,
"fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
" return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
"}\n");
}
}
void ImmutableEnumFieldLiteGenerator::GenerateInitializationCode(
io::Printer* printer) const {
if (!IsDefaultValueJavaDefault(descriptor_)) {
@ -772,6 +806,98 @@ void RepeatedImmutableEnumFieldLiteGenerator::GenerateInitializationCode(
printer->Print(variables_, "$name$_ = emptyIntList();\n");
}
void RepeatedImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
printer->Print(
variables_,
"/**\n"
" * An uninstantiable, behaviorless type to represent the field in\n"
" * generics.\n"
" */\n"
"@kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
"class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
" : com.google.protobuf.kotlin.DslProxy()\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$kt_deprecation$ val $kt_name$: "
"com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" @kotlin.jvm.JvmSynthetic\n"
" get() = com.google.protobuf.kotlin.DslList(\n"
" $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
" )\n");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"add(value: $kt_type$) {\n"
" $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(value: $kt_type$) {\n"
" add(value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
" $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
" addAll(values)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
"operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"set(index: kotlin.Int, value: $kt_type$) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"clear() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}");
}
std::string RepeatedImmutableEnumFieldLiteGenerator::GetBoxedType() const {
return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
}

@ -71,6 +71,7 @@ class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator {
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16>* output) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;
@ -116,6 +117,7 @@ class RepeatedImmutableEnumFieldLiteGenerator
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16>* output) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;

@ -258,6 +258,11 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
// empty string.
(*variables)["{"] = "";
(*variables)["}"] = "";
(*variables)["kt_name"] =
IsForbiddenKotlin(info->name) ? info->name + "_" : info->name;
(*variables)["kt_capitalized_name"] = IsForbiddenKotlin(info->name)
? info->capitalized_name + "_"
: info->capitalized_name;
}
void SetCommonOneofVariables(const FieldDescriptor* descriptor,

@ -83,6 +83,7 @@ class ImmutableFieldGenerator {
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
virtual void GenerateFieldBuilderInitializationCode(
io::Printer* printer) const = 0;
virtual void GenerateKotlinDslMembers(io::Printer* printer) const = 0;
virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
virtual void GenerateHashCode(io::Printer* printer) const = 0;
@ -105,6 +106,7 @@ class ImmutableFieldLiteGenerator {
virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
virtual void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16>* output) const = 0;
virtual void GenerateKotlinDslMembers(io::Printer* printer) const = 0;
virtual std::string GetBoxedType() const = 0;

@ -675,6 +675,53 @@ void FileGenerator::GenerateSiblings(
}
}
std::string FileGenerator::GetKotlinClassname() {
return name_resolver_->GetFileClassName(file_, immutable_api_, true);
}
void FileGenerator::GenerateKotlinSiblings(
const std::string& package_dir, GeneratorContext* context,
std::vector<std::string>* file_list,
std::vector<std::string>* annotation_list) {
for (int i = 0; i < file_->message_type_count(); i++) {
const Descriptor* descriptor = file_->message_type(i);
MessageGenerator* generator = message_generators_[i].get();
auto open_file = [context](const string& filename) {
return std::unique_ptr<io::ZeroCopyOutputStream>(context->Open(filename));
};
std::string filename = package_dir + descriptor->name() + "Kt.kt";
file_list->push_back(filename);
std::string info_full_path = filename + ".pb.meta";
GeneratedCodeInfo annotations;
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
&annotations);
auto output = open_file(filename);
io::Printer printer(
output.get(), '$',
options_.annotate_code ? &annotation_collector : nullptr);
printer.Print(
"//Generated by the protocol buffer compiler. DO NOT EDIT!\n"
"// source: $filename$\n"
"\n",
"filename", descriptor->file()->name());
if (!java_package_.empty()) {
printer.Print(
"package $package$;\n"
"\n",
"package", java_package_);
}
generator->GenerateKotlinMembers(&printer);
generator->GenerateTopLevelKotlinMembers(&printer);
if (options_.annotate_code) {
auto info_output = open_file(info_full_path);
annotations.SerializeToZeroCopyStream(info_output.get());
annotation_list->push_back(info_full_path);
}
}
}
bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor,
bool immutable_api) {

@ -78,6 +78,11 @@ class FileGenerator {
void Generate(io::Printer* printer);
std::string GetKotlinClassname();
void GenerateKotlinSiblings(const std::string& package_dir,
GeneratorContext* generator_context,
std::vector<std::string>* file_list,
std::vector<std::string>* annotation_list);
// If we aren't putting everything into one file, this will write all the
// files other than the outer file (i.e. one for each message, enum, and

@ -90,6 +90,17 @@ const std::unordered_set<std::string>* kReservedNames =
"transient", "try", "void", "volatile", "while",
});
// Names that should be avoided as field names in Kotlin.
// All Kotlin hard keywords are in this list.
const std::unordered_set<std::string>* kKotlinForbiddenNames =
new std::unordered_set<std::string>({
"as", "as?", "break", "class", "continue", "do", "else",
"false", "for", "fun", "if", "in", "!in", "interface",
"is", "!is", "null", "object", "package", "return", "super",
"this", "throw", "true", "try", "typealias", "typeof", "val",
"var", "when", "while",
});
bool IsForbidden(const std::string& field_name) {
for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) {
if (field_name == kForbiddenWordList[i]) {
@ -216,6 +227,10 @@ std::string UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field) {
return name;
}
bool IsForbiddenKotlin(const std::string& field_name) {
return kKotlinForbiddenNames->find(field_name) !=
kKotlinForbiddenNames->end();
}
std::string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
@ -422,6 +437,35 @@ const char* BoxedPrimitiveTypeName(const FieldDescriptor* descriptor) {
return BoxedPrimitiveTypeName(GetJavaType(descriptor));
}
const char* KotlinTypeName(JavaType type) {
switch (type) {
case JAVATYPE_INT:
return "kotlin.Int";
case JAVATYPE_LONG:
return "kotlin.Long";
case JAVATYPE_FLOAT:
return "kotlin.Float";
case JAVATYPE_DOUBLE:
return "kotlin.Double";
case JAVATYPE_BOOLEAN:
return "kotlin.Boolean";
case JAVATYPE_STRING:
return "kotlin.String";
case JAVATYPE_BYTES:
return "com.google.protobuf.ByteString";
case JAVATYPE_ENUM:
return NULL;
case JAVATYPE_MESSAGE:
return NULL;
// No default because we want the compiler to complain if any new
// JavaTypes are added.
}
LOG(FATAL) << "Can't get here.";
return NULL;
}
std::string GetOneofStoredType(const FieldDescriptor* field) {
const JavaType javaType = GetJavaType(field);

@ -51,6 +51,7 @@ namespace java {
extern const char kThickSeparator[];
extern const char kThinSeparator[];
bool IsForbiddenKotlin(const std::string& field_name);
// If annotation_file is non-empty, prints a javax.annotation.Generated
// annotation to the given Printer. annotation_file will be referenced in the
@ -214,6 +215,9 @@ const char* PrimitiveTypeName(JavaType type);
// types.
const char* BoxedPrimitiveTypeName(JavaType type);
// Kotlin source does not distinguish between primitives and non-primitives,
// but does use Kotlin-specific qualified types for them.
const char* KotlinTypeName(JavaType type);
// Get the name of the java enum constant representing this type. E.g.,
// "INT32" for FieldDescriptor::TYPE_INT32. The enum constant's full

@ -0,0 +1,130 @@
#include "net/proto2/compiler/java/public/kotlin_generator.h"
#include "net/proto2/compiler/java/internal/file.h"
#include "net/proto2/compiler/java/internal/helpers.h"
#include "net/proto2/compiler/java/internal/options.h"
#include "net/proto2/compiler/java/public/generator.h"
#include "net/proto2/compiler/public/code_generator.h"
namespace proto2 {
namespace compiler {
namespace java {
KotlinGenerator::KotlinGenerator() {}
KotlinGenerator::~KotlinGenerator() {}
uint64_t KotlinGenerator::GetSupportedFeatures() const {
return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL;
}
bool KotlinGenerator::Generate(const FileDescriptor* file,
const std::string& parameter,
GeneratorContext* context,
std::string* error) const {
// -----------------------------------------------------------------
// parse generator options
std::vector<std::pair<std::string, std::string> > options;
ParseGeneratorParameter(parameter, &options);
Options file_options;
for (auto& option : options) {
if (option.first == "output_list_file") {
file_options.output_list_file = option.second;
} else if (option.first == "immutable") {
file_options.generate_immutable_code = true;
} else if (option.first == "mutable") {
*error = "Mutable not supported by Kotlin generator";
return false;
} else if (option.first == "shared") {
file_options.generate_shared_code = true;
} else if (option.first == "lite") {
file_options.enforce_lite = true;
} else if (option.first == "annotate_code") {
file_options.annotate_code = true;
} else if (option.first == "annotation_list_file") {
file_options.annotation_list_file = option.second;
} else {
*error = "Unknown generator option: " + option.first;
return false;
}
}
// By default we generate immutable code and shared code for immutable API.
if (!file_options.generate_immutable_code &&
!file_options.generate_shared_code) {
file_options.generate_immutable_code = true;
file_options.generate_shared_code = true;
}
std::vector<std::string> all_files;
std::vector<std::string> all_annotations;
std::unique_ptr<FileGenerator> file_generator;
if (file_options.generate_immutable_code) {
file_generator = absl::make_unique<FileGenerator>(
file, file_options, /* immutable_api = */ true);
}
if (!file_generator->Validate(error)) {
return false;
}
auto open_file = [context](const string& filename) {
return std::unique_ptr<io::ZeroCopyOutputStream>(context->Open(filename));
};
std::string package_dir = JavaPackageToDir(file_generator->java_package());
std::string kotlin_filename = package_dir;
kotlin_filename += file_generator->GetKotlinClassname();
kotlin_filename += ".kt";
all_files.push_back(kotlin_filename);
std::string info_full_path = kotlin_filename + ".pb.meta";
if (file_options.annotate_code) {
all_annotations.push_back(info_full_path);
}
// Generate main kotlin file.
auto output = open_file(kotlin_filename);
GeneratedCodeInfo annotations;
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
&annotations);
io::Printer printer(
output.get(), '$',
file_options.annotate_code ? &annotation_collector : nullptr);
file_generator->GenerateKotlinSiblings(package_dir, context, &all_files,
&all_annotations);
if (file_options.annotate_code) {
auto info_output = open_file(info_full_path);
annotations.SerializeToZeroCopyStream(info_output.get());
}
// Generate output list if requested.
if (!file_options.output_list_file.empty()) {
// Generate output list. This is just a simple text file placed in a
// deterministic location which lists the .kt files being generated.
auto srclist_raw_output = open_file(file_options.output_list_file);
io::Printer srclist_printer(srclist_raw_output.get(), '$');
for (auto& all_file : all_files) {
srclist_printer.Print("$filename$\n", "filename", all_file);
}
}
if (!file_options.annotation_list_file.empty()) {
// Generate output list. This is just a simple text file placed in a
// deterministic location which lists the .kt files being generated.
auto annotation_list_raw_output =
open_file(file_options.annotation_list_file);
io::Printer annotation_list_printer(annotation_list_raw_output.get(), '$');
for (auto& all_annotation : all_annotations) {
annotation_list_printer.Print("$filename$\n", "filename", all_annotation);
}
}
return true;
}
} // namespace java
} // namespace compiler
} // namespace proto2

@ -69,6 +69,17 @@ std::string TypeName(const FieldDescriptor* field,
}
}
std::string KotlinTypeName(const FieldDescriptor* field,
ClassNameResolver* name_resolver) {
if (GetJavaType(field) == JAVATYPE_MESSAGE) {
return name_resolver->GetImmutableClassName(field->message_type());
} else if (GetJavaType(field) == JAVATYPE_ENUM) {
return name_resolver->GetImmutableClassName(field->enum_type());
} else {
return KotlinTypeName(GetJavaType(field));
}
}
std::string WireType(const FieldDescriptor* field) {
return "com.google.protobuf.WireFormat.FieldType." +
std::string(FieldTypeName(field->type()));
@ -91,6 +102,8 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
(*variables)["key_type"] = TypeName(key, name_resolver, false);
std::string boxed_key_type = TypeName(key, name_resolver, true);
(*variables)["boxed_key_type"] = boxed_key_type;
(*variables)["kt_key_type"] = KotlinTypeName(key, name_resolver);
(*variables)["kt_value_type"] = KotlinTypeName(value, name_resolver);
// Used for calling the serialization function.
(*variables)["short_key_type"] =
boxed_key_type.substr(boxed_key_type.rfind('.') + 1);
@ -136,6 +149,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
// by the proto compiler
(*variables)["deprecation"] =
descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] =
descriptor->options().deprecated()
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
" is deprecated\") "
: "";
(*variables)["on_changed"] = "onChanged();";
// For repeated fields, one bit is used for whether the array is immutable
@ -651,6 +669,87 @@ void ImmutableMapFieldGenerator::GenerateMapGetters(
}
}
void ImmutableMapFieldGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
printer->Print(
variables_,
"/**\n"
" * An uninstantiable, behaviorless type to represent the field in\n"
" * generics.\n"
" */\n"
"@kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
"class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
" : com.google.protobuf.kotlin.DslProxy()\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"$kt_deprecation$ val $kt_name$: "
"com.google.protobuf.kotlin.DslMap"
"<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" @kotlin.jvm.JvmSynthetic\n"
" @JvmName(\"get$kt_capitalized_name$Map\")\n"
" get() = com.google.protobuf.kotlin.DslMap(\n"
" $kt_dsl_builder$.${$get$capitalized_name$Map$}$()\n"
" )\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"@JvmName(\"put$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslMap"
"<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" .put(key: $kt_key_type$, value: $kt_value_type$) {\n"
" $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n"
" }\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@JvmName(\"set$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslMap"
"<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" .set(key: $kt_key_type$, value: $kt_value_type$) {\n"
" put(key, value)\n"
" }\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@JvmName(\"remove$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslMap"
"<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" .remove(key: $kt_key_type$) {\n"
" $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n"
" }\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@JvmName(\"putAll$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslMap"
"<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" .putAll(map: kotlin.collections.Map<$kt_key_type$, $kt_value_type$>) "
"{\n"
" $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n"
" }\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@JvmName(\"clear$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslMap"
"<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" .clear() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
" }\n");
}
void ImmutableMapFieldGenerator::GenerateFieldBuilderInitializationCode(
io::Printer* printer) const {
// Nothing to initialize.

@ -62,6 +62,7 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator {
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCode(io::Printer* printer) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;

@ -69,6 +69,17 @@ std::string TypeName(const FieldDescriptor* field,
}
}
std::string KotlinTypeName(const FieldDescriptor* field,
ClassNameResolver* name_resolver) {
if (GetJavaType(field) == JAVATYPE_MESSAGE) {
return name_resolver->GetImmutableClassName(field->message_type());
} else if (GetJavaType(field) == JAVATYPE_ENUM) {
return name_resolver->GetImmutableClassName(field->enum_type());
} else {
return KotlinTypeName(GetJavaType(field));
}
}
std::string WireType(const FieldDescriptor* field) {
return "com.google.protobuf.WireFormat.FieldType." +
std::string(FieldTypeName(field->type()));
@ -90,6 +101,8 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
(*variables)["key_type"] = TypeName(key, name_resolver, false);
(*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
(*variables)["kt_key_type"] = KotlinTypeName(key, name_resolver);
(*variables)["kt_value_type"] = KotlinTypeName(value, name_resolver);
(*variables)["key_wire_type"] = WireType(key);
(*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
// We use `x.getClass()` as a null check because it generates less bytecode
@ -131,6 +144,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
// by the proto compiler
(*variables)["deprecation"] =
descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] =
descriptor->options().deprecated()
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
" is deprecated\") "
: "";
(*variables)["default_entry"] =
(*variables)["capitalized_name"] + "DefaultEntryHolder.defaultEntry";
@ -788,6 +806,87 @@ void ImmutableMapFieldLiteGenerator::GenerateBuilderMembers(
}
}
void ImmutableMapFieldLiteGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
printer->Print(
variables_,
"/**\n"
" * An uninstantiable, behaviorless type to represent the field in\n"
" * generics.\n"
" */\n"
"@kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
"class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
" : com.google.protobuf.kotlin.DslProxy()\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"$kt_deprecation$ val $kt_name$: "
"com.google.protobuf.kotlin.DslMap"
"<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" @kotlin.jvm.JvmSynthetic\n"
" @JvmName(\"get$kt_capitalized_name$Map\")\n"
" get() = com.google.protobuf.kotlin.DslMap(\n"
" $kt_dsl_builder$.${$get$capitalized_name$Map$}$()\n"
" )\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"@JvmName(\"put$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslMap"
"<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" .put(key: $kt_key_type$, value: $kt_value_type$) {\n"
" $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n"
" }\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@JvmName(\"set$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslMap"
"<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" .set(key: $kt_key_type$, value: $kt_value_type$) {\n"
" put(key, value)\n"
" }\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@JvmName(\"remove$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslMap"
"<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" .remove(key: $kt_key_type$) {\n"
" $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n"
" }\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@JvmName(\"putAll$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslMap"
"<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" .putAll(map: kotlin.collections.Map<$kt_key_type$, $kt_value_type$>) "
"{\n"
" $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n"
" }\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@JvmName(\"clear$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslMap"
"<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" .clear() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
" }\n");
}
void ImmutableMapFieldLiteGenerator::GenerateInitializationCode(
io::Printer* printer) const {
// Nothing to initialize.

@ -53,6 +53,7 @@ class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator {
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16>* output) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;

@ -1356,6 +1356,243 @@ void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) {
}
}
void ImmutableMessageGenerator::GenerateKotlinDsl(io::Printer* printer) const {
printer->Print(
"@kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
"@com.google.protobuf.kotlin.ProtoDslMarker\n");
printer->Print(
"class Dsl private constructor(\n"
" @kotlin.jvm.JvmField private val _builder: $message$.Builder\n"
") {\n"
" companion object {\n"
" @kotlin.jvm.JvmSynthetic\n"
" @kotlin.PublishedApi\n"
" internal fun _create(builder: $message$.Builder): Dsl = "
"Dsl(builder)\n"
" }\n"
"\n"
" @kotlin.jvm.JvmSynthetic\n"
" @kotlin.PublishedApi\n"
" internal fun _build(): $message$ = _builder.build()\n",
"message", name_resolver_->GetClassName(descriptor_, true));
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); i++) {
printer->Print("\n");
field_generators_.get(descriptor_->field(i))
.GenerateKotlinDslMembers(printer);
}
for (auto oneof : oneofs_) {
printer->Print(
"val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n"
" @JvmName(\"get$oneof_capitalized_name$Case\")\n"
" get() = _builder.get$oneof_capitalized_name$Case()\n\n"
"fun clear$oneof_capitalized_name$() {\n"
" _builder.clear$oneof_capitalized_name$()\n"
"}\n",
"oneof_name", context_->GetOneofGeneratorInfo(oneof)->name,
"oneof_capitalized_name",
context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "message",
name_resolver_->GetClassName(descriptor_, true));
}
if (descriptor_->extension_range_count() > 0) {
GenerateKotlinExtensions(printer);
}
printer->Outdent();
printer->Print("}\n");
}
void ImmutableMessageGenerator::GenerateKotlinMembers(
io::Printer* printer) const {
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> Unit): "
"$message$ "
"=\n"
" $message_kt$.Dsl._create($message$.newBuilder()).apply { block() "
"}._build()\n",
"camelcase_name", name_resolver_->GetKotlinFactoryName(descriptor_),
"message_kt", name_resolver_->GetKotlinExtensionsClassName(descriptor_),
"message", name_resolver_->GetClassName(descriptor_, true));
printer->Print("object $name$Kt {\n", "name", descriptor_->name());
printer->Indent();
GenerateKotlinDsl(printer);
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
if (IsMapEntry(descriptor_->nested_type(i))) continue;
ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
.GenerateKotlinMembers(printer);
}
printer->Outdent();
printer->Print("}\n");
}
void ImmutableMessageGenerator::GenerateTopLevelKotlinMembers(
io::Printer* printer) const {
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline fun $message$.copy(block: $message_kt$.Dsl.() -> Unit): "
"$message$ =\n"
" $message_kt$.Dsl._create(this.toBuilder()).apply { block() "
"}._build()\n",
"message", name_resolver_->GetClassName(descriptor_, true), "message_kt",
name_resolver_->GetKotlinExtensionsClassName(descriptor_));
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
if (IsMapEntry(descriptor_->nested_type(i))) continue;
ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
.GenerateTopLevelKotlinMembers(printer);
}
}
void ImmutableMessageGenerator::GenerateKotlinExtensions(
io::Printer* printer) const {
std::string message_name = name_resolver_->GetClassName(descriptor_, true);
printer->Print(
"@Suppress(\"UNCHECKED_CAST\")\n"
"@kotlin.jvm.JvmSynthetic\n"
"operator fun <T> get(extension: "
"com.google.protobuf.ExtensionLite<$message$, T>): T {\n"
" return if (extension.isRepeated) {\n"
" get(extension as com.google.protobuf.ExtensionLite<$message$, "
"List<*>>) as T\n"
" } else {\n"
" _builder.getExtension(extension)\n"
" }\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
"@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n"
"operator fun <E> get(\n"
" extension: com.google.protobuf.ExtensionLite<$message$, List<E>>\n"
"): com.google.protobuf.kotlin.ExtensionList<E, $message$> {\n"
" return com.google.protobuf.kotlin.ExtensionList(extension, "
"_builder.getExtension(extension))\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"operator fun contains(extension: "
"com.google.protobuf.ExtensionLite<$message$, *>): "
"Boolean {\n"
" return _builder.hasExtension(extension)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"fun clear(extension: com.google.protobuf.ExtensionLite<$message$, *>) "
"{\n"
" _builder.clearExtension(extension)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.PublishedApi\n"
"internal fun <T> setExtension(extension: "
"com.google.protobuf.ExtensionLite<$message$, T>, "
"value: T) {\n"
" _builder.setExtension(extension, value)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline operator fun <T : Comparable<T>> set(\n"
" extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
" value: T\n"
") {\n"
" setExtension(extension, value)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline operator fun set(\n"
" extension: com.google.protobuf.ExtensionLite<$message$, "
"com.google.protobuf.ByteString>,\n"
" value: com.google.protobuf.ByteString\n"
") {\n"
" setExtension(extension, value)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline operator fun <T : com.google.protobuf.MessageLite> set(\n"
" extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
" value: T\n"
") {\n"
" setExtension(extension, value)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
"$message$>.add(value: E) {\n"
" _builder.addExtension(this.extension, value)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline operator fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
"$message$>.plusAssign"
"(value: E) {\n"
" add(value)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
"$message$>.addAll(values: Iterable<E>) {\n"
" for (value in values) {\n"
" add(value)\n"
" }\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline operator fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
"$message$>.plusAssign(values: "
"Iterable<E>) {\n"
" addAll(values)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"operator fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
"$message$>.set(index: Int, value: "
"E) {\n"
" _builder.setExtension(this.extension, index, value)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline fun com.google.protobuf.kotlin.ExtensionList<*, "
"$message$>.clear() {\n"
" clear(extension)\n"
"}\n\n",
"message", message_name);
}
void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) {
printer->Print(
"private static String getTypeUrl(\n"

@ -85,6 +85,9 @@ class MessageGenerator {
// Generate code to register all contained extensions with an
// ExtensionRegistry.
virtual void GenerateExtensionRegistrationCode(io::Printer* printer) = 0;
virtual void GenerateKotlinDsl(io::Printer* printer) const = 0;
virtual void GenerateKotlinMembers(io::Printer* printer) const = 0;
virtual void GenerateTopLevelKotlinMembers(io::Printer* printer) const = 0;
protected:
const Descriptor* descriptor_;
@ -107,6 +110,9 @@ class ImmutableMessageGenerator : public MessageGenerator {
// Returns an estimate of the number of bytes the printed code will compile to
virtual int GenerateStaticVariableInitializers(io::Printer* printer);
void GenerateKotlinDsl(io::Printer* printer) const override;
void GenerateKotlinMembers(io::Printer* printer) const override;
void GenerateTopLevelKotlinMembers(io::Printer* printer) const override;
private:
void GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate);
@ -128,6 +134,7 @@ class ImmutableMessageGenerator : public MessageGenerator {
void GenerateEqualsAndHashCode(io::Printer* printer);
void GenerateParser(io::Printer* printer);
void GenerateParsingConstructor(io::Printer* printer);
void GenerateKotlinExtensions(io::Printer* printer) const;
void GenerateAnyMethods(io::Printer* printer);
Context* context_;

@ -59,6 +59,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
(*variables)["type"] =
name_resolver->GetImmutableClassName(descriptor->message_type());
(*variables)["kt_type"] = (*variables)["type"];
(*variables)["mutable_type"] =
name_resolver->GetMutableClassName(descriptor->message_type());
(*variables)["group_or_message"] =
@ -68,6 +69,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
// by the proto compiler
(*variables)["deprecation"] =
descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] =
descriptor->options().deprecated()
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
" is deprecated\") "
: "";
(*variables)["on_changed"] = "onChanged();";
(*variables)["ver"] = GeneratedCodeVersionSuffix();
(*variables)["get_parser"] =
@ -406,6 +412,32 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers(
"}\n");
}
void ImmutableMessageFieldGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$kt_deprecation$var $kt_name$: $kt_type$\n"
" @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
" get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
" @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
" set(value) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
" }\n");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"fun ${$clear$kt_capitalized_name$$}$() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}\n");
WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
printer->Print(variables_,
"fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
" return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
"}\n");
}
void ImmutableMessageFieldGenerator::GenerateFieldBuilderInitializationCode(
io::Printer* printer) const {
if (HasHasbit(descriptor_)) {
@ -1360,6 +1392,98 @@ std::string RepeatedImmutableMessageFieldGenerator::GetBoxedType() const {
return name_resolver_->GetImmutableClassName(descriptor_->message_type());
}
void RepeatedImmutableMessageFieldGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
printer->Print(
variables_,
"/**\n"
" * An uninstantiable, behaviorless type to represent the field in\n"
" * generics.\n"
" */\n"
"@kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
"class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
" : com.google.protobuf.kotlin.DslProxy()\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$kt_deprecation$ val $kt_name$: "
"com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" @kotlin.jvm.JvmSynthetic\n"
" get() = com.google.protobuf.kotlin.DslList(\n"
" $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
" )\n");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"add(value: $kt_type$) {\n"
" $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(value: $kt_type$) {\n"
" add(value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
" $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
" addAll(values)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
"operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"set(index: kotlin.Int, value: $kt_type$) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"clear() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}");
}
} // namespace java
} // namespace compiler
} // namespace protobuf

@ -81,6 +81,7 @@ class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator {
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCode(io::Printer* printer) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;
@ -146,6 +147,7 @@ class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator {
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCode(io::Printer* printer) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;

@ -59,6 +59,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
(*variables)["type"] =
name_resolver->GetImmutableClassName(descriptor->message_type());
(*variables)["kt_type"] = (*variables)["type"];
(*variables)["mutable_type"] =
name_resolver->GetMutableClassName(descriptor->message_type());
(*variables)["group_or_message"] =
@ -68,6 +69,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
// by the proto compiler
(*variables)["deprecation"] =
descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] =
descriptor->options().deprecated()
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
" is deprecated\") "
: "";
(*variables)["required"] = descriptor->is_required() ? "true" : "false";
if (HasHasbit(descriptor)) {
@ -275,6 +281,32 @@ void ImmutableMessageFieldLiteGenerator::GenerateBuilderMembers(
printer->Annotate("{", "}", descriptor_);
}
void ImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$kt_deprecation$var $kt_name$: $kt_type$\n"
" @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
" get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
" @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
" set(value) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
" }\n");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"fun ${$clear$kt_capitalized_name$$}$() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}\n");
WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
printer->Print(variables_,
"fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
" return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
"}\n");
}
void ImmutableMessageFieldLiteGenerator::GenerateFieldInfo(
io::Printer* printer, std::vector<uint16>* output) const {
WriteIntToUtf16CharSequence(descriptor_->number(), output);
@ -749,6 +781,98 @@ std::string RepeatedImmutableMessageFieldLiteGenerator::GetBoxedType() const {
return name_resolver_->GetImmutableClassName(descriptor_->message_type());
}
void RepeatedImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
printer->Print(
variables_,
"/**\n"
" * An uninstantiable, behaviorless type to represent the field in\n"
" * generics.\n"
" */\n"
"@kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
"class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
" : com.google.protobuf.kotlin.DslProxy()\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$kt_deprecation$ val $kt_name$: "
"com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" @kotlin.jvm.JvmSynthetic\n"
" get() = com.google.protobuf.kotlin.DslList(\n"
" $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
" )\n");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"add(value: $kt_type$) {\n"
" $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(value: $kt_type$) {\n"
" add(value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
" $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
" addAll(values)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
"operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"set(index: kotlin.Int, value: $kt_type$) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"clear() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}");
}
} // namespace java
} // namespace compiler
} // namespace protobuf

@ -71,6 +71,7 @@ class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator {
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16>* output) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;
@ -116,6 +117,7 @@ class RepeatedImmutableMessageFieldLiteGenerator
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16>* output) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;

@ -723,6 +723,242 @@ void ImmutableMessageLiteGenerator::GenerateInitializers(io::Printer* printer) {
}
}
void ImmutableMessageLiteGenerator::GenerateKotlinDsl(
io::Printer* printer) const {
printer->Print(
"@kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
"@com.google.protobuf.kotlin.ProtoDslMarker\n");
printer->Print(
"class Dsl private constructor(\n"
" @kotlin.jvm.JvmField private val _builder: $message$.Builder\n"
") {\n"
" companion object {\n"
" @kotlin.jvm.JvmSynthetic\n"
" @kotlin.PublishedApi\n"
" internal fun _create(builder: $message$.Builder): Dsl = "
"Dsl(builder)\n"
" }\n"
"\n"
" @kotlin.jvm.JvmSynthetic\n"
" @kotlin.PublishedApi\n"
" internal fun _build(): $message$ = _builder.build()\n",
"message", name_resolver_->GetClassName(descriptor_, true));
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); i++) {
printer->Print("\n");
field_generators_.get(descriptor_->field(i))
.GenerateKotlinDslMembers(printer);
}
for (auto oneof : oneofs_) {
printer->Print(
"val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n"
" @JvmName(\"get$oneof_capitalized_name$Case\")\n"
" get() = _builder.get$oneof_capitalized_name$Case()\n\n"
"fun clear$oneof_capitalized_name$() {\n"
" _builder.clear$oneof_capitalized_name$()\n"
"}\n",
"oneof_name", context_->GetOneofGeneratorInfo(oneof)->name,
"oneof_capitalized_name",
context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "message",
name_resolver_->GetClassName(descriptor_, true));
}
if (descriptor_->extension_range_count() > 0) {
GenerateKotlinExtensions(printer);
}
printer->Outdent();
printer->Print("}\n");
}
void ImmutableMessageLiteGenerator::GenerateKotlinMembers(
io::Printer* printer) const {
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> Unit): "
"$message$ =\n"
" $message_kt$.Dsl._create($message$.newBuilder()).apply { block() "
"}._build()\n",
"camelcase_name", name_resolver_->GetKotlinFactoryName(descriptor_),
"message_kt", name_resolver_->GetKotlinExtensionsClassName(descriptor_),
"message", name_resolver_->GetClassName(descriptor_, true));
printer->Print("object $name$Kt {\n", "name", descriptor_->name());
printer->Indent();
GenerateKotlinDsl(printer);
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
if (IsMapEntry(descriptor_->nested_type(i))) continue;
ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
.GenerateKotlinMembers(printer);
}
printer->Outdent();
printer->Print("}\n");
}
void ImmutableMessageLiteGenerator::GenerateTopLevelKotlinMembers(
io::Printer* printer) const {
printer->Print(
"inline fun $message$.copy(block: $message_kt$.Dsl.() -> Unit): "
"$message$ =\n"
" $message_kt$.Dsl._create(this.toBuilder()).apply { block() "
"}._build()\n",
"message", name_resolver_->GetClassName(descriptor_, true), "message_kt",
name_resolver_->GetKotlinExtensionsClassName(descriptor_));
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
if (IsMapEntry(descriptor_->nested_type(i))) continue;
ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
.GenerateTopLevelKotlinMembers(printer);
}
}
void ImmutableMessageLiteGenerator::GenerateKotlinExtensions(
io::Printer* printer) const {
std::string message_name = name_resolver_->GetClassName(descriptor_, true);
printer->Print(
"@Suppress(\"UNCHECKED_CAST\")\n"
"@kotlin.jvm.JvmSynthetic\n"
"operator fun <T> get(extension: "
"com.google.protobuf.ExtensionLite<$message$, T>): T {\n"
" return if (extension.isRepeated) {\n"
" get(extension as com.google.protobuf.ExtensionLite<$message$, "
"List<*>>) as T\n"
" } else {\n"
" _builder.getExtension(extension)\n"
" }\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
"@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n"
"operator fun <E> get(\n"
" extension: com.google.protobuf.ExtensionLite<$message$, List<E>>\n"
"): com.google.protobuf.kotlin.ExtensionList<E, $message$> {\n"
" return com.google.protobuf.kotlin.ExtensionList(extension, "
"_builder.getExtension(extension))\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"operator fun contains(extension: "
"com.google.protobuf.ExtensionLite<$message$, *>): "
"Boolean {\n"
" return _builder.hasExtension(extension)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"fun clear(extension: com.google.protobuf.ExtensionLite<$message$, *>) "
"{\n"
" _builder.clearExtension(extension)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.PublishedApi\n"
"internal fun <T> setExtension(extension: "
"com.google.protobuf.ExtensionLite<$message$, T>, "
"value: T) {\n"
" _builder.setExtension(extension, value)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline operator fun <T : Comparable<T>> set(\n"
" extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
" value: T\n"
") {\n"
" setExtension(extension, value)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline operator fun set(\n"
" extension: com.google.protobuf.ExtensionLite<$message$, "
"com.google.protobuf.ByteString>,\n"
" value: com.google.protobuf.ByteString\n"
") {\n"
" setExtension(extension, value)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline operator fun <T : com.google.protobuf.MessageLite> set(\n"
" extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
" value: T\n"
") {\n"
" setExtension(extension, value)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
"$message$>.add(value: E) {\n"
" _builder.addExtension(this.extension, value)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline operator fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
"$message$>.plusAssign"
"(value: E) {\n"
" add(value)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
"$message$>.addAll(values: Iterable<E>) {\n"
" for (value in values) {\n"
" add(value)\n"
" }\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline operator fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
"$message$>.plusAssign(values: "
"Iterable<E>) {\n"
" addAll(values)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"operator fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
"$message$>.set(index: Int, value: "
"E) {\n"
" _builder.setExtension(this.extension, index, value)\n"
"}\n\n",
"message", message_name);
printer->Print(
"@kotlin.jvm.JvmSynthetic\n"
"inline fun com.google.protobuf.kotlin.ExtensionList<*, "
"$message$>.clear() {\n"
" clear(extension)\n"
"}\n\n",
"message", message_name);
}
} // namespace java
} // namespace compiler
} // namespace protobuf

@ -56,6 +56,9 @@ class ImmutableMessageLiteGenerator : public MessageGenerator {
virtual void GenerateStaticVariables(io::Printer* printer,
int* bytecode_estimate);
virtual int GenerateStaticVariableInitializers(io::Printer* printer);
void GenerateKotlinDsl(io::Printer* printer) const override;
void GenerateKotlinMembers(io::Printer* printer) const override;
void GenerateTopLevelKotlinMembers(io::Printer* printer) const override;
private:
void GenerateParseFromMethods(io::Printer* printer);
@ -66,6 +69,7 @@ class ImmutableMessageLiteGenerator : public MessageGenerator {
void GenerateParser(io::Printer* printer);
void GenerateConstructor(io::Printer* printer);
void GenerateDynamicMethodNewBuildMessageInfo(io::Printer* printer);
void GenerateKotlinExtensions(io::Printer* printer) const;
Context* context_;
ClassNameResolver* name_resolver_;

@ -69,6 +69,16 @@ std::string ClassNameWithoutPackage(const Descriptor* descriptor,
return StripPackageName(descriptor->full_name(), descriptor->file());
}
std::string ClassNameWithoutPackageKotlin(const Descriptor* descriptor) {
std::string result = descriptor->name();
const Descriptor* temp = descriptor->containing_type();
while (temp) {
result = temp->name() + "Kt." + result;
temp = temp->containing_type();
}
return result;
}
// Get the name of an enum's Java class without package name prefix.
std::string ClassNameWithoutPackage(const EnumDescriptor* descriptor,
@ -316,6 +326,12 @@ std::string ClassNameResolver::GetExtensionIdentifierName(
descriptor->name();
}
std::string ClassNameResolver::GetKotlinFactoryName(
const Descriptor* descriptor) {
std::string name = ToCamelCase(descriptor->name(), /* lower_first = */ true);
return IsForbiddenKotlin(name) ? name + "_" : name;
}
std::string ClassNameResolver::GetJavaImmutableClassName(
const Descriptor* descriptor) {
return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, true),
@ -328,6 +344,12 @@ std::string ClassNameResolver::GetJavaImmutableClassName(
descriptor->file(), true);
}
std::string ClassNameResolver::GetKotlinExtensionsClassName(
const Descriptor* descriptor) {
return GetClassFullName(ClassNameWithoutPackageKotlin(descriptor),
descriptor->file(), true, true, true);
}
} // namespace java
} // namespace compiler

@ -115,6 +115,8 @@ class ClassNameResolver {
// com.package.OuterClass$OuterMessage$InnerMessage
std::string GetJavaImmutableClassName(const Descriptor* descriptor);
std::string GetJavaImmutableClassName(const EnumDescriptor* descriptor);
std::string GetKotlinFactoryName(const Descriptor* descriptor);
std::string GetKotlinExtensionsClassName(const Descriptor* descriptor);
private:
// Get the full name of a Java class by prepending the Java package name
// or outer class name.

@ -66,6 +66,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["type"] = PrimitiveTypeName(javaType);
(*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType);
(*variables)["kt_type"] = KotlinTypeName(javaType);
(*variables)["field_type"] = (*variables)["type"];
if (javaType == JAVATYPE_BOOLEAN || javaType == JAVATYPE_DOUBLE ||
@ -127,6 +128,11 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
// by the proto compiler
(*variables)["deprecation"] =
descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] =
descriptor->options().deprecated()
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
" is deprecated\") "
: "";
int fixed_size = FixedSize(GetType(descriptor));
if (fixed_size != -1) {
(*variables)["fixed_size"] = StrCat(fixed_size);
@ -296,6 +302,33 @@ void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
"}\n");
}
void ImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$kt_deprecation$var $kt_name$: $kt_type$\n"
" @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
" get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
" @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
" set(value) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
" }\n");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"fun ${$clear$kt_capitalized_name$$}$() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}\n");
if (HasHazzer(descriptor_)) {
WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
printer->Print(variables_,
"fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
" return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
"}\n");
}
}
void ImmutablePrimitiveFieldGenerator::GenerateFieldBuilderInitializationCode(
io::Printer* printer) const {
@ -791,6 +824,98 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
printer->Annotate("{", "}", descriptor_);
}
void RepeatedImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
printer->Print(
variables_,
"/**\n"
" * An uninstantiable, behaviorless type to represent the field in\n"
" * generics.\n"
" */\n"
"@kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
"class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
" : com.google.protobuf.kotlin.DslProxy()\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$kt_deprecation$ val $kt_name$: "
"com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" @kotlin.jvm.JvmSynthetic\n"
" get() = com.google.protobuf.kotlin.DslList(\n"
" $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
" )\n");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"add(value: $kt_type$) {\n"
" $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(value: $kt_type$) {\n"
" add(value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
" $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
" addAll(values)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
"operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"set(index: kotlin.Int, value: $kt_type$) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"clear() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}");
}
void RepeatedImmutablePrimitiveFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
// noop for primitives

@ -81,6 +81,7 @@ class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator {
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCode(io::Printer* printer) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;
@ -139,6 +140,7 @@ class RepeatedImmutablePrimitiveFieldGenerator
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCode(io::Printer* printer) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;

@ -73,6 +73,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
JavaType javaType = GetJavaType(descriptor);
(*variables)["type"] = PrimitiveTypeName(javaType);
(*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType);
(*variables)["kt_type"] = KotlinTypeName(javaType);
(*variables)["field_type"] = (*variables)["type"];
(*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
(*variables)["capitalized_type"] =
@ -135,6 +136,11 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
// by the proto compiler
(*variables)["deprecation"] =
descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] =
descriptor->options().deprecated()
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
" is deprecated\") "
: "";
int fixed_size = FixedSize(GetType(descriptor));
if (fixed_size != -1) {
(*variables)["fixed_size"] = StrCat(fixed_size);
@ -301,6 +307,33 @@ void ImmutablePrimitiveFieldLiteGenerator::GenerateBuilderMembers(
printer->Annotate("{", "}", descriptor_);
}
void ImmutablePrimitiveFieldLiteGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$kt_deprecation$var $kt_name$: $kt_type$\n"
" @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
" get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
" @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
" set(value) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
" }\n");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"fun ${$clear$kt_capitalized_name$$}$() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}\n");
if (HasHazzer(descriptor_)) {
WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
printer->Print(variables_,
"fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
" return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
"}\n");
}
}
void ImmutablePrimitiveFieldLiteGenerator::GenerateFieldInfo(
io::Printer* printer, std::vector<uint16>* output) const {
@ -613,6 +646,98 @@ void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateBuilderMembers(
printer->Annotate("{", "}", descriptor_);
}
void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
printer->Print(
variables_,
"/**\n"
" * An uninstantiable, behaviorless type to represent the field in\n"
" * generics.\n"
" */\n"
"@kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
"class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
" : com.google.protobuf.kotlin.DslProxy()\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$kt_deprecation$ val $kt_name$: "
"com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
" @kotlin.jvm.JvmSynthetic\n"
" get() = com.google.protobuf.kotlin.DslList(\n"
" $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
" )\n");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"add(value: $kt_type$) {\n"
" $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(value: $kt_type$) {\n"
" add(value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
" $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
" addAll(values)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
"operator fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"set(index: kotlin.Int, value: $kt_type$) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
"clear() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}");
}
void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateFieldInfo(
io::Printer* printer, std::vector<uint16>* output) const {
WriteIntToUtf16CharSequence(descriptor_->number(), output);

@ -71,6 +71,7 @@ class ImmutablePrimitiveFieldLiteGenerator
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16>* output) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;
@ -117,6 +118,7 @@ class RepeatedImmutablePrimitiveFieldLiteGenerator
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16>* output) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;

@ -88,6 +88,11 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
// by the proto compiler
(*variables)["deprecation"] =
descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] =
descriptor->options().deprecated()
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
" is deprecated\") "
: "";
(*variables)["on_changed"] = "onChanged();";
if (HasHasbit(descriptor)) {
@ -365,6 +370,34 @@ void ImmutableStringFieldGenerator::GenerateBuilderMembers(
"}\n");
}
void ImmutableStringFieldGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$kt_deprecation$var $kt_name$: kotlin.String\n"
" @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
" get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
" @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
" set(value) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
" }\n");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"fun ${$clear$kt_capitalized_name$$}$() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}\n");
if (HasHazzer(descriptor_)) {
WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
printer->Print(variables_,
"fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
" return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
"}\n");
}
}
void ImmutableStringFieldGenerator::GenerateFieldBuilderInitializationCode(
io::Printer* printer) const {
// noop for primitives
@ -914,6 +947,107 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers(
"}\n");
}
void RepeatedImmutableStringFieldGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
printer->Print(
variables_,
"/**\n"
" * An uninstantiable, behaviorless type to represent the field in\n"
" * generics.\n"
" */\n"
"@kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
"class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
" : com.google.protobuf.kotlin.DslProxy()\n");
// property for List<String>
WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
printer->Print(
variables_,
"val $kt_name$: "
"com.google.protobuf.kotlin.DslList"
"<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>\n"
" @kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
" get() = com.google.protobuf.kotlin.DslList(\n"
" $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
" )\n");
// List<String>.add(String)
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
"add(value: kotlin.String) {\n"
" $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
"}\n");
// List<String> += String
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
"operator fun com.google.protobuf.kotlin.DslList"
"<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(value: kotlin.String) {\n"
" $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
"}\n");
// List<String>.addAll(Iterable<String>)
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
"addAll(values: kotlin.collections.Iterable<kotlin.String>) {\n"
" $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
"}\n");
// List<String> += Iterable<String>
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
"operator fun com.google.protobuf.kotlin.DslList"
"<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(values: kotlin.collections.Iterable<kotlin.String>) {\n"
" $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
"}\n");
// List<String>[Int] = String
WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
"operator fun com.google.protobuf.kotlin.DslList"
"<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
"set(index: kotlin.Int, value: kotlin.String) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
"clear() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}");
}
void RepeatedImmutableStringFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
// noop for primitives

@ -81,6 +81,7 @@ class ImmutableStringFieldGenerator : public ImmutableFieldGenerator {
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCode(io::Printer* printer) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;
@ -137,6 +138,7 @@ class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator {
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCode(io::Printer* printer) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;

@ -83,6 +83,11 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
// by the proto compiler
(*variables)["deprecation"] =
descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
(*variables)["kt_deprecation"] =
descriptor->options().deprecated()
? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
" is deprecated\") "
: "";
(*variables)["required"] = descriptor->is_required() ? "true" : "false";
if (HasHasbit(descriptor)) {
@ -301,6 +306,34 @@ void ImmutableStringFieldLiteGenerator::GenerateBuilderMembers(
printer->Annotate("{", "}", descriptor_);
}
void ImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$kt_deprecation$var $kt_name$: kotlin.String\n"
" @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
" get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
" @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
" set(value) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
" }\n");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"fun ${$clear$kt_capitalized_name$$}$() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}\n");
if (HasHazzer(descriptor_)) {
WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
printer->Print(variables_,
"fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
" return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
"}\n");
}
}
void ImmutableStringFieldLiteGenerator::GenerateFieldInfo(
io::Printer* printer, std::vector<uint16>* output) const {
WriteIntToUtf16CharSequence(descriptor_->number(), output);
@ -701,6 +734,107 @@ void RepeatedImmutableStringFieldLiteGenerator::GenerateBuilderMembers(
printer->Annotate("{", "}", descriptor_);
}
void RepeatedImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers(
io::Printer* printer) const {
printer->Print(
variables_,
"/**\n"
" * An uninstantiable, behaviorless type to represent the field in\n"
" * generics.\n"
" */\n"
"@kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
"class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
" : com.google.protobuf.kotlin.DslProxy()\n");
// property for List<String>
WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
printer->Print(
variables_,
"val $kt_name$: "
"com.google.protobuf.kotlin.DslList"
"<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>\n"
" @kotlin.OptIn"
"(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
" get() = com.google.protobuf.kotlin.DslList(\n"
" $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
" )\n");
// List<String>.add(String)
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
"add(value: kotlin.String) {\n"
" $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
"}\n");
// List<String> += String
WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslList"
"<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(value: kotlin.String) {\n"
" add(value)\n"
"}\n");
// List<String>.addAll(Iterable<String>)
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
"addAll(values: kotlin.collections.Iterable<kotlin.String>) {\n"
" $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
"}\n");
// List<String> += Iterable<String>
WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
"inline operator fun com.google.protobuf.kotlin.DslList"
"<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
"plusAssign(values: kotlin.collections.Iterable<kotlin.String>) {\n"
" addAll(values)\n"
"}\n");
// List<String>[Int] = String
WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
/* builder */ false);
printer->Print(
variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
"operator fun com.google.protobuf.kotlin.DslList"
"<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
"set(index: kotlin.Int, value: kotlin.String) {\n"
" $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
"}");
WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
/* builder */ false);
printer->Print(variables_,
"@kotlin.jvm.JvmSynthetic\n"
"@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
"fun com.google.protobuf.kotlin.DslList"
"<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
"clear() {\n"
" $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
"}");
}
void RepeatedImmutableStringFieldLiteGenerator::GenerateFieldInfo(
io::Printer* printer, std::vector<uint16>* output) const {
WriteIntToUtf16CharSequence(descriptor_->number(), output);

@ -72,6 +72,7 @@ class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator {
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16>* output) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;
@ -116,6 +117,7 @@ class RepeatedImmutableStringFieldLiteGenerator
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16>* output) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;

@ -0,0 +1,20 @@
load("//tools/build_defs/testing:bzl_library.bzl", "bzl_library")
licenses(["notice"])
bzl_library(
name = "kt_jvm_proto_library_helper",
srcs = ["kt_jvm_proto_library.internal.bzl"],
visibility = ["//visibility:private"],
deps = [
"//tools/build_defs/kotlin/release/rules:android_jvm_compile_bzl",
"//tools/build_defs/kotlin/release/toolchains/kotlin_jvm:toolchain_bzl",
],
)
bzl_library(
name = "kt_jvm_proto_library",
srcs = ["kt_jvm_proto_library.bzl"],
visibility = ["//visibility:private"],
deps = [":kt_jvm_proto_library_helper"],
)

@ -0,0 +1,140 @@
"""Definitions for Kotlin proto libraries."""
load(":kt_jvm_proto_library.internal.bzl", _kt_proto_library_helper = "kt_proto_library_helper")
load("//devtools/build_cleaner/skylark:build_defs.bzl", "register_extension_info")
def _lite_proto_name(name):
return ":%s_DO_NOT_DEPEND_java_lite_proto" % name
def _proto_name(name):
return ":%s_DO_NOT_DEPEND_java_proto" % name
def kt_jvm_lite_proto_library(
name,
deps = None,
tags = None,
testonly = None,
compatible_with = None,
restricted_to = None,
visibility = None,
deprecation = None,
features = []):
"""
This rule generates and compiles lite Java and Kotlin APIs for a specified proto_library.
Args:
name: A name for the target
deps: One or more proto_library targets
tags: List of string tags passed to generated targets.
testonly: Whether this target is intended only for tests.
compatible_with: Standard attribute, see http://go/be-common#common.compatible_with
restricted_to: Standard attribute, see http://go/be-common#common.restricted_to
visibility: A list of targets allowed to depend on this rule.
deprecation: Standard attribute, see http://go/be-common#common.deprecation
features: Features enabled.
"""
tags = (tags or []) + ["kt_jvm_lite_proto_library"]
native.java_lite_proto_library(
name = _lite_proto_name(name)[1:],
deps = deps,
testonly = testonly,
compatible_with = compatible_with,
visibility = ["//visibility:private"],
restricted_to = restricted_to,
tags = tags + ["avoid_dep"],
deprecation = deprecation,
features = features,
)
_kt_proto_library_helper(
name = name,
proto_deps = deps,
deps = [
_lite_proto_name(name),
"//java/com/google/protobuf:protobuf_lite",
"//java/com/google/protobuf/kotlin:only_for_use_in_proto_generated_code_its_generator_and_tests",
"//java/com/google/protobuf/kotlin:shared_runtime",
],
exports = [_lite_proto_name(name)],
testonly = testonly,
compatible_with = compatible_with,
restricted_to = restricted_to,
constraints = ["android"],
tags = tags,
variant = "lite",
visibility = visibility,
deprecation = deprecation,
features = features,
)
def kt_jvm_proto_library(
name,
deps = None,
tags = None,
testonly = None,
compatible_with = None,
restricted_to = None,
visibility = None,
deprecation = None,
features = []):
"""
This rule generates and compiles full Java and Kotlin APIs for a specified proto_library.
Args:
name: A name for the target
deps: One or more proto_library targets
tags: List of string tags passed to generated targets.
testonly: Whether this target is intended only for tests.
compatible_with: Standard attribute, see http://go/be-common#common.compatible_with
restricted_to: Standard attribute, see http://go/be-common#common.restricted_to
visibility: A list of targets allowed to depend on this rule.
deprecation: Standard attribute, see http://go/be-common#common.deprecation
features: Features enabled.
"""
tags = (tags or []) + ["kt_jvm_proto_library"]
native.java_proto_library(
name = _proto_name(name)[1:],
deps = deps,
testonly = testonly,
compatible_with = compatible_with,
visibility = ["//visibility:private"],
restricted_to = restricted_to,
tags = tags + ["avoid_dep"],
deprecation = deprecation,
features = features,
)
_kt_proto_library_helper(
name = name,
proto_deps = deps,
deps = [
_proto_name(name),
"//java/com/google/protobuf",
"//java/com/google/protobuf/kotlin:only_for_use_in_proto_generated_code_its_generator_and_tests",
"//java/com/google/protobuf/kotlin:shared_runtime",
],
exports = [_proto_name(name)],
testonly = testonly,
compatible_with = compatible_with,
constraints = [],
restricted_to = restricted_to,
tags = tags,
variant = "full",
visibility = visibility,
deprecation = deprecation,
features = features,
)
register_extension_info(
extension = kt_jvm_proto_library,
label_regex_for_dep = "{extension_name}",
)
register_extension_info(
extension = kt_jvm_lite_proto_library,
label_regex_for_dep = "{extension_name}",
)

@ -0,0 +1,177 @@
"""Definitions for internals of Kotlin proto libraries."""
load("//tools/build_defs/kotlin/release/rules:common.bzl", "common")
load(
"//tools/build_defs/kotlin/release/rules:dep_checks_aspect.bzl",
"KtForbiddenInfo",
"dep_checks_aspect",
)
load(
"//tools/build_defs/kotlin/release/toolchains/kotlin_jvm:toolchain.bzl",
_toolchain = "toolchain",
)
def _get_real_short_path(file):
"""Returns the correct short path file name to be used by protoc."""
short_path = file.short_path
if short_path.startswith("../"):
second_slash = short_path.index("/", 3)
short_path = short_path[second_slash + 1:]
virtual_imports = "_virtual_imports/"
if virtual_imports in short_path:
short_path = short_path.split(virtual_imports)[1].split("/", 1)[1]
return short_path
def _kt_proto_extensions_impl(ctx):
for dep in ctx.attr.proto_deps + ctx.attr.deps + ctx.attr.exports:
if dep[KtForbiddenInfo].forbidden:
fail("""Not allowed to depend on %s from Kotlin code, see go/kotlin/build-rules#restrictions:
%s""" % (dep.label, "\n".join(dep[KtForbiddenInfo].forbidden)))
transitive_set = depset(
transitive =
[dep[ProtoInfo].transitive_descriptor_sets for dep in ctx.attr.proto_deps],
)
proto_sources = []
for dep in ctx.attr.proto_deps:
for file in dep[ProtoInfo].direct_sources:
proto_sources.append(_get_real_short_path(file))
gen_src_dir = ctx.actions.declare_directory(ctx.label.name + "/ktproto")
codegen_params = "lite:" if ctx.attr.variant == "lite" else ""
protoc_args = ctx.actions.args()
protoc_args.add("--kotlin_out=" + codegen_params + gen_src_dir.path)
protoc_args.add_joined(
transitive_set,
join_with = ctx.configuration.host_path_separator,
format_joined = "--descriptor_set_in=%s",
)
protoc_args.add_all(proto_sources)
ctx.actions.run(
inputs = depset(transitive = [transitive_set]),
outputs = [gen_src_dir],
executable = ctx.executable._protoc,
arguments = [protoc_args],
progress_message = "Generating kotlin proto extensions for " +
", ".join([
str(dep.label)
for dep in ctx.attr.proto_deps
]),
)
kt_toolchain = _toolchain.get(ctx)
compiler_plugins = [
kt_toolchain.marker_plugin,
kt_toolchain.strictdeps_plugin,
]
result = common.kt_jvm_library(
ctx,
srcs = [gen_src_dir],
output = ctx.outputs.jar,
deps = [dep[JavaInfo] for dep in ctx.attr.deps],
exports = [dep[JavaInfo] for dep in ctx.attr.exports],
kotlincopts = ["-Xopt-in=kotlin.RequiresOptIn", "-nowarn"],
kt_toolchain = kt_toolchain,
java_toolchain = ctx.attr._java_toolchain,
compiler_plugins = compiler_plugins,
android_compatible = "android" in ctx.attr.constraints,
enforce_strict_deps = False,
)
java_info = java_common.add_constraints(
result.java_info,
constraints = ctx.attr.constraints,
)
transitive_runfiles = []
for p in common.collect_providers(DefaultInfo, ctx.attr.deps + ctx.attr.exports):
transitive_runfiles.append(p.data_runfiles.files)
transitive_runfiles.append(p.default_runfiles.files)
runfiles = ctx.runfiles(
files = [ctx.outputs.jar],
transitive_files = depset(transitive = transitive_runfiles),
collect_default = True,
)
return [
java_info,
OutputGroupInfo(_validation = depset(result.validations)),
DefaultInfo(
files = depset([ctx.outputs.jar]),
runfiles = runfiles,
),
ProguardSpecProvider(depset(ctx.files._proguard_specs)),
]
kt_proto_library_helper = rule(
doc = """
This is a helper rule to combine the kotlin code generation work
of kt_jvm_proto_library and kt_jvm_lite_proto_library.
It generates Kotlin proto code with the protoc compiler using the
--kotlin_out flag and compiles that Kotlin code. It requires as a dependency
a proto_library and either a java_proto_library or java_lite_proto_library.
""",
attrs = dict(
proto_deps = attr.label_list(
providers = [ProtoInfo],
aspects = [dep_checks_aspect],
),
deps = attr.label_list(
providers = [JavaInfo],
aspects = [dep_checks_aspect],
),
exports = attr.label_list(
allow_rules = ["java_proto_library", "java_lite_proto_library"],
aspects = [dep_checks_aspect],
),
constraints = attr.string_list(
doc = """Extra constraints imposed on this library, most commonly, 'android'. Constraints
typically indicate that the library may be used in binaries running outside of
Google production services. See go/be-java#java_library.constraints for details on
supported constraints and what they mean. Note that all Java and Kotlin `deps` are
required to carry compatible constraints.""",
),
variant = attr.string(
mandatory = True,
values = ["lite", "full"],
doc = """Indicator of which Kotlin proto runtime to use.""",
),
_protoc = attr.label(
default = Label("//net/proto2/compiler/public:protocol_compiler"),
cfg = "host",
executable = True,
),
_java_toolchain = attr.label(
default = Label(
"//tools/jdk:current_java_toolchain",
),
),
_coverage_instrumenter = attr.label(
default = Label("//tools/build_defs/kotlin/release/rules:kt_coverage_instrumenter"),
cfg = "host",
executable = True,
),
_coverage_runtime = attr.label(
default = Label("//third_party/java/jacoco:blaze-agent"),
),
_toolchain = attr.label(
default = Label(
"//tools/build_defs/kotlin/release/toolchains/kotlin_jvm:kt_jvm_toolchain_internal_DO_NOT_USE",
),
),
_proguard_specs = attr.label_list(
allow_files = [".pgcfg"],
default = ["//java/com/google/protobuf/kotlin:kt_proto.pgcfg"],
),
),
fragments = ["java"],
outputs = dict(
jar = "lib%{name}.ktproto.jar",
),
provides = [JavaInfo],
implementation = _kt_proto_extensions_impl,
toolchains = [_toolchain.type],
)
Loading…
Cancel
Save