Merge pull request #8272 from deannagarcia/kotlinProtos

Opensourcing kotlin protos
pull/8521/head
deannagarcia 4 years ago committed by GitHub
commit 76188afb94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .github/workflows/codespell.yml
  2. 1
      BUILD
  3. 29
      Makefile.am
  4. 1
      cmake/extract_includes.bat.in
  5. 1
      cmake/libprotoc.cmake
  6. 5
      java/README.md
  7. 19
      java/kotlin-lite/generate-sources-build.xml
  8. 34
      java/kotlin-lite/generate-test-sources-build.xml
  9. 25
      java/kotlin-lite/lite.awk
  10. 284
      java/kotlin-lite/pom.xml
  11. 7
      java/kotlin-lite/process-lite-sources-build.xml
  12. 60
      java/kotlin-lite/src/test/kotlin/com/google/protobuf/ExtendableMessageLiteExtensionsTest.kt
  13. 993
      java/kotlin-lite/src/test/kotlin/com/google/protobuf/Proto2LiteTest.kt
  14. 20
      java/kotlin/generate-sources-build.xml
  15. 34
      java/kotlin/generate-test-sources-build.xml
  16. 240
      java/kotlin/pom.xml
  17. 27
      java/kotlin/src/main/kotlin/com/google/protobuf/DslList.kt
  18. 30
      java/kotlin/src/main/kotlin/com/google/protobuf/DslMap.kt
  19. 12
      java/kotlin/src/main/kotlin/com/google/protobuf/DslProxy.kt
  20. 26
      java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt
  21. 28
      java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt
  22. 27
      java/kotlin/src/main/kotlin/com/google/protobuf/ExtensionList.kt
  23. 18
      java/kotlin/src/main/kotlin/com/google/protobuf/OnlyForUseByGeneratedProtoCode.kt
  24. 10
      java/kotlin/src/main/kotlin/com/google/protobuf/ProtoDslMarker.kt
  25. 39
      java/kotlin/src/main/kotlin/com/google/protobuf/UnmodifiableCollections.kt
  26. 98
      java/kotlin/src/test/kotlin/com/google/protobuf/DslListTest.kt
  27. 164
      java/kotlin/src/test/kotlin/com/google/protobuf/DslMapTest.kt
  28. 60
      java/kotlin/src/test/kotlin/com/google/protobuf/ExtendableMessageExtensionsTest.kt
  29. 125
      java/kotlin/src/test/kotlin/com/google/protobuf/ExtensionListTest.kt
  30. 891
      java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt
  31. 340
      java/kotlin/src/test/kotlin/com/google/protobuf/Proto3Test.kt
  32. 62
      java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto2.proto
  33. 76
      java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto3.proto
  34. 16
      java/kotlin/src/test/proto/com/google/protobuf/example_extensible_message.proto
  35. 12
      java/kotlin/src/test/proto/com/google/protobuf/multiple_files_proto3.proto
  36. 2
      src/Makefile.am
  37. 126
      src/google/protobuf/compiler/java/java_enum_field.cc
  38. 2
      src/google/protobuf/compiler/java/java_enum_field.h
  39. 126
      src/google/protobuf/compiler/java/java_enum_field_lite.cc
  40. 2
      src/google/protobuf/compiler/java/java_enum_field_lite.h
  41. 5
      src/google/protobuf/compiler/java/java_field.cc
  42. 2
      src/google/protobuf/compiler/java/java_field.h
  43. 47
      src/google/protobuf/compiler/java/java_file.cc
  44. 5
      src/google/protobuf/compiler/java/java_file.h
  45. 76
      src/google/protobuf/compiler/java/java_helpers.cc
  46. 11
      src/google/protobuf/compiler/java/java_helpers.h
  47. 130
      src/google/protobuf/compiler/java/java_kotlin_generator.cc
  48. 40
      src/google/protobuf/compiler/java/java_kotlin_generator.h
  49. 99
      src/google/protobuf/compiler/java/java_map_field.cc
  50. 1
      src/google/protobuf/compiler/java/java_map_field.h
  51. 99
      src/google/protobuf/compiler/java/java_map_field_lite.cc
  52. 1
      src/google/protobuf/compiler/java/java_map_field_lite.h
  53. 237
      src/google/protobuf/compiler/java/java_message.cc
  54. 7
      src/google/protobuf/compiler/java/java_message.h
  55. 124
      src/google/protobuf/compiler/java/java_message_field.cc
  56. 2
      src/google/protobuf/compiler/java/java_message_field.h
  57. 124
      src/google/protobuf/compiler/java/java_message_field_lite.cc
  58. 2
      src/google/protobuf/compiler/java/java_message_field_lite.h
  59. 236
      src/google/protobuf/compiler/java/java_message_lite.cc
  60. 4
      src/google/protobuf/compiler/java/java_message_lite.h
  61. 22
      src/google/protobuf/compiler/java/java_name_resolver.cc
  62. 2
      src/google/protobuf/compiler/java/java_name_resolver.h
  63. 125
      src/google/protobuf/compiler/java/java_primitive_field.cc
  64. 2
      src/google/protobuf/compiler/java/java_primitive_field.h
  65. 125
      src/google/protobuf/compiler/java/java_primitive_field_lite.cc
  66. 4
      src/google/protobuf/compiler/java/java_primitive_field_lite.h
  67. 134
      src/google/protobuf/compiler/java/java_string_field.cc
  68. 2
      src/google/protobuf/compiler/java/java_string_field.h
  69. 134
      src/google/protobuf/compiler/java/java_string_field_lite.cc
  70. 2
      src/google/protobuf/compiler/java/java_string_field_lite.h
  71. 5
      src/google/protobuf/compiler/main.cc

@ -12,5 +12,5 @@ jobs:
- uses: codespell-project/actions-codespell@master
with:
check_filenames: true
skip: ./.git,./conformance/third_party,*.snk,*.pb,*.pb.cc,*.pb.h,./src/google/protobuf/testdata,./objectivec/Tests,./python/compatibility_tests/v2.5.0/tests/google/protobuf/internal,./.github/workflows/codespell.yml
ignore_words_list: "alow,alse,ba,cleare,copyable,cloneable,dedup,dur,errorprone,files',fo,fundementals,hel,importd,inout,leapyear,nd,nin,ois,ons,parseable,process',te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od,OptIn"
skip: ./.git,./conformance/third_party,*.snk,*.pb,*.pb.cc,*.pb.h,./src/google/protobuf/testdata,./objectivec/Tests,./python/compatibility_tests/v2.5.0/tests/google/protobuf/internal,./github/workflows/codespell.yml
ignore_words_list: "alow,alse,ba,cleare,copyable,cloneable,dedup,dur,errorprone,files',fo,fundementals,hel,importd,inout,leapyear,nd,nin,ois,ons,parseable,process',te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od,optin"

@ -403,6 +403,7 @@ cc_library(
"src/google/protobuf/compiler/java/java_generator.cc",
"src/google/protobuf/compiler/java/java_generator_factory.cc",
"src/google/protobuf/compiler/java/java_helpers.cc",
"src/google/protobuf/compiler/java/java_kotlin_generator.cc",
"src/google/protobuf/compiler/java/java_map_field.cc",
"src/google/protobuf/compiler/java/java_map_field_lite.cc",
"src/google/protobuf/compiler/java/java_message.cc",

@ -530,6 +530,35 @@ java_EXTRA_DIST=
java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto \
java/core/src/test/proto/com/google/protobuf/test_custom_options.proto \
java/core/src/test/proto/com/google/protobuf/wrappers_test.proto \
java/kotlin/generate-sources-build.xml \
java/kotlin/generate-test-sources-build.xml \
java/kotlin/pom.xml \
java/kotlin/src/main/kotlin/com/google/protobuf/DslList.kt \
java/kotlin/src/main/kotlin/com/google/protobuf/DslMap.kt \
java/kotlin/src/main/kotlin/com/google/protobuf/DslProxy.kt \
java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt \
java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt\
java/kotlin/src/main/kotlin/com/google/protobuf/ExtensionList.kt \
java/kotlin/src/main/kotlin/com/google/protobuf/OnlyForUseByGeneratedProtoCode.kt\
java/kotlin/src/main/kotlin/com/google/protobuf/ProtoDslMarker.kt \
java/kotlin/src/main/kotlin/com/google/protobuf/UnmodifiableCollections.kt \
java/kotlin/src/test/kotlin/com/google/protobuf/DslListTest.kt \
java/kotlin/src/test/kotlin/com/google/protobuf/DslMapTest.kt \
java/kotlin/src/test/kotlin/com/google/protobuf/ExtendableMessageExtensionsTest.kt\
java/kotlin/src/test/kotlin/com/google/protobuf/ExtensionListTest.kt \
java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt \
java/kotlin/src/test/kotlin/com/google/protobuf/Proto3Test.kt \
java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto2.proto \
java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto3.proto \
java/kotlin/src/test/proto/com/google/protobuf/example_extensible_message.proto \
java/kotlin/src/test/proto/com/google/protobuf/multiple_files_proto3.proto \
java/kotlin-lite/generate-sources-build.xml \
java/kotlin-lite/generate-test-sources-build.xml \
java/kotlin-lite/lite.awk \
java/kotlin-lite/pom.xml \
java/kotlin-lite/process-lite-sources-build.xml \
java/kotlin-lite/src/test/kotlin/com/google/protobuf/ExtendableMessageLiteExtensionsTest.kt\
java/kotlin-lite/src/test/kotlin/com/google/protobuf/Proto2LiteTest.kt \
java/lite.md \
java/lite/BUILD \
java/lite/generate-sources-build.xml \

@ -26,6 +26,7 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\cshar
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_names.h" include\google\protobuf\compiler\csharp\csharp_names.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\importer.h" include\google\protobuf\compiler\importer.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_generator.h" include\google\protobuf\compiler\java\java_generator.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_kotlin_generator.h" include\google\protobuf\compiler\java\java_kotlin_generator.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_names.h" include\google\protobuf\compiler\java\java_names.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\js\js_generator.h" include\google\protobuf\compiler\js\js_generator.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\js\well_known_types_embed.h" include\google\protobuf\compiler\js\well_known_types_embed.h

@ -45,6 +45,7 @@ set(libprotoc_files
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator_factory.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_helpers.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_kotlin_generator.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_map_field.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_map_field_lite.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message.cc

@ -178,3 +178,8 @@ The complete documentation for Protocol Buffers is available via the
web at:
https://developers.google.com/protocol-buffers/
## Kotlin Protocol Buffers
Code to support more idiomatic Kotlin protocol buffers has been added to the
repository, and Kotlin support will be launched in the next numbered release.

@ -0,0 +1,19 @@
<project name="generate-sources">
<echo message="Running protoc ..."/>
<mkdir dir="${generated.sources.dir}"/>
<exec executable="${protoc}">
<arg value="--kotlin_out=lite:${generated.sources.dir}"/>
<arg value="--proto_path=${protobuf.source.dir}"/>
<arg value="${protobuf.source.dir}/google/protobuf/any.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/api.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/duration.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/empty.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/field_mask.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/source_context.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/struct.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/timestamp.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/type.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/wrappers.proto"/>
</exec>
</project>

@ -0,0 +1,34 @@
<project name="generate-test-sources">
<mkdir dir="${generated.testsources.dir}"/>
<exec executable="${protoc}">
<arg value="--java_out=lite:${generated.testsources.dir}"/>
<arg value="--proto_path=${protobuf.source.dir}"/>
<arg value="--proto_path=${protobuf.basedir}/java/kotlin/${test.proto.dir}"/>
<arg value="--experimental_allow_proto3_optional"/>
<arg value="${protobuf.source.dir}/google/protobuf/map_lite_unittest.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_import.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_import_lite.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public_lite.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_lite.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3.proto"/>
<arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/evil_names_proto2.proto"/>
<arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/evil_names_proto3.proto"/>
<arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/example_extensible_message.proto"/>
<arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/multiple_files_proto3.proto"/>
</exec>
<exec executable="${protoc}">
<arg value="--kotlin_out=lite:${generated.testsources.dir}"/>
<arg value="--proto_path=${protobuf.source.dir}"/>
<arg value="--proto_path=${protobuf.basedir}/java/kotlin/${test.proto.dir}"/>
<arg value="--experimental_allow_proto3_optional"/>
<arg value="${protobuf.source.dir}/google/protobuf/map_lite_unittest.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_lite.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3.proto"/>
<arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/evil_names_proto2.proto"/>
<arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/evil_names_proto3.proto"/>
<arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/example_extensible_message.proto"/>
<arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/multiple_files_proto3.proto"/>
</exec>
</project>

@ -0,0 +1,25 @@
# Remove code enclosed by "BEGIN FULL-RUNTIME" and "END FULL-RUNTIME" to
# create the lite-only version of a test file.
BEGIN {
in_full_runtime = 0;
}
/BEGIN FULL-RUNTIME/ {
in_full_runtime = 1;
next;
}
/END FULL-RUNTIME/ {
in_full_runtime = 0;
next;
}
in_full_runtime {
# Skip full runtime code path.
next;
}
{
print;
}

@ -0,0 +1,284 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.15.6</version>
</parent>
<artifactId>protobuf-kotlin-lite</artifactId>
<packaging>bundle</packaging>
<name>Protocol Buffers [Lite]</name>
<description>
Lite version of Protocol Buffers library. This version is optimized for code size, but does
not guarantee API/ABI stability.
</description>
<properties>
<kotlin.version>1.4.31</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>protobuf-javalite</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymockclassextension</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<!-- Include core protos in the bundle as resources -->
<resources>
<resource>
<directory>${protobuf.source.dir}</directory>
<includes>
<include>google/protobuf/any.proto</include>
<include>google/protobuf/api.proto</include>
<include>google/protobuf/duration.proto</include>
<include>google/protobuf/empty.proto</include>
<include>google/protobuf/field_mask.proto</include>
<include>google/protobuf/source_context.proto</include>
<include>google/protobuf/struct.proto</include>
<include>google/protobuf/timestamp.proto</include>
<include>google/protobuf/type.proto</include>
<include>google/protobuf/wrappers.proto</include>
</includes>
</resource>
</resources>
<testResources>
<testResource>
<directory>${protobuf.source.dir}</directory>
<includes>
<include>google/protobuf/testdata/golden_message_oneof_implemented</include>
<include>google/protobuf/testdata/golden_packed_fields_message</include>
</includes>
</testResource>
</testResources>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy-kotlin-source-files</id>
<phase>generate-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${generated.sources.dir}/com/google/protobuf</outputDirectory>
<resources>
<resource>
<directory>${basedir}/../kotlin/src/main/kotlin/com/google/protobuf</directory>
<includes>
<include>DslList.kt</include>
<include>DslMap.kt</include>
<include>DslProxy.kt</include>
<include>ExtendableMessageLiteExtensions.kt</include>
<include>ExtensionList.kt</include>
<include>OnlyForUseByGeneratedProtoCode.kt</include>
<include>ProtoDslMarker.kt</include>
<include>UnmodifiableCollections.kt</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy-test-source-files</id>
<phase>generate-test-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${generated.testsources.dir}/com/google/protobuf</outputDirectory>
<resources>
<resource>
<directory>${basedir}/../core/src/test/java/com/google/protobuf</directory>
<includes>
<include>TestUtilLite.java</include>
</includes>
</resource>
<resource>
<directory>${basedir}/../kotlin/src/test/kotlin/com/google/protobuf</directory>
<excludes>
<exclude>ExtendableMessageExtensionsTest.kt</exclude>
<exclude>Proto2Test.kt</exclude>
<exclude>ProtoUtil.java</exclude>
</excludes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Use Antrun plugin to generate sources with protoc -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<!-- Generate core protos -->
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<target>
<ant antfile="generate-sources-build.xml"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<!-- Generate the test protos -->
<execution>
<id>generate-test-sources</id>
<phase>generate-test-sources</phase>
<configuration>
<target>
<ant antfile="generate-test-sources-build.xml"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>process-lite-sources</id>
<phase>generate-test-sources</phase>
<configuration>
<target>
<ant antfile="process-lite-sources-build.xml"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-generated-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${generated.sources.dir}</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-generated-test-sources</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>${generated.testsources.dir}</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<id>compile</id>
<goals> <goal>compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${generated.sources.dir}</sourceDir>
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals> <goal>test-compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
<sourceDir>${generated.testsources.dir}</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<!-- OSGI bundle configuration -->
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Automatic-Module-Name>com.google.protobuf</Automatic-Module-Name> <!-- Java9+ Jigsaw module name -->
<Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
<Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
<Export-Package>com.google.protobuf;version=${project.version}</Export-Package>
<Import-Package>sun.misc;resolution:=optional,*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,7 @@
<project name="process-lite-sources">
<exec executable="awk" output="${generated.testsources.dir}/com/google/protobuf/TestUtil.java">
<arg value="-f" />
<arg value="${basedir}/lite.awk" />
<arg value="${basedir}/../core/src/test/java/com/google/protobuf/TestUtil.java" />
</exec>
</project>

@ -0,0 +1,60 @@
package com.google.protobuf.kotlin
import com.google.common.truth.Truth.assertThat
import example_extensible_message.ExampleExtensibleMessage
import example_extensible_message.ExampleExtensibleMessageOuterClass 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,993 @@
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 evil_names_proto2.EvilNamesProto2OuterClass.EvilNamesProto2
import evil_names_proto2.EvilNamesProto2OuterClass.HardKeywordsAllTypes
import evil_names_proto2.EvilNamesProto2OuterClass.Interface
import evil_names_proto2.HardKeywordsAllTypesKt
import evil_names_proto2.evilNamesProto2
import evil_names_proto2.hardKeywordsAllTypes
import evil_names_proto2.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 protobuf_unittest.MapLiteUnittest.MapEnumLite
import protobuf_unittest.MapLiteUnittest.TestMapLite
import protobuf_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].add(301)
this[UnittestLite.repeatedInt64ExtensionLite].add(302L)
this[UnittestLite.repeatedUint32ExtensionLite].add(303)
this[UnittestLite.repeatedUint64ExtensionLite].add(304L)
this[UnittestLite.repeatedSint32ExtensionLite].add(305)
this[UnittestLite.repeatedSint64ExtensionLite].add(306L)
this[UnittestLite.repeatedFixed32ExtensionLite].add(307)
this[UnittestLite.repeatedFixed64ExtensionLite].add(308L)
this[UnittestLite.repeatedSfixed32ExtensionLite].add(309)
this[UnittestLite.repeatedSfixed64ExtensionLite].add(310L)
this[UnittestLite.repeatedFloatExtensionLite].add(311F)
this[UnittestLite.repeatedDoubleExtensionLite].add(312.0)
this[UnittestLite.repeatedBoolExtensionLite].add(false)
this[UnittestLite.repeatedStringExtensionLite].add("315")
this[UnittestLite.repeatedBytesExtensionLite].add(toBytes("316"))
this[UnittestLite.repeatedGroupExtensionLite].add(repeatedGroupExtensionLite { a = 317 })
this[UnittestLite.repeatedNestedMessageExtensionLite].add(
TestAllTypesLiteKt.nestedMessage { bb = 318 }
)
this[UnittestLite.repeatedForeignMessageExtensionLite].add(foreignMessageLite { c = 319 })
this[UnittestLite.repeatedImportMessageExtensionLite].add(
ImportMessageLite.newBuilder().setD(320).build()
)
this[UnittestLite.repeatedLazyMessageExtensionLite].add(
TestAllTypesLiteKt.nestedMessage { bb = 327 }
)
this[UnittestLite.repeatedNestedEnumExtensionLite].add(NestedEnum.BAZ)
this[UnittestLite.repeatedForeignEnumExtensionLite].add(ForeignEnumLite.FOREIGN_LITE_BAZ)
this[UnittestLite.repeatedImportEnumExtensionLite].add(ImportEnumLite.IMPORT_LITE_BAZ)
this[UnittestLite.repeatedStringPieceExtensionLite].add("324")
this[UnittestLite.repeatedCordExtensionLite].add("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].addAll(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].addAll(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].addAll(
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].addAll(
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].addAll(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,20 @@
<project name="generate-sources">
<echo message="Running protoc ..."/>
<mkdir dir="${generated.sources.dir}"/>
<exec executable="${protoc}">
<arg value="--kotlin_out=${generated.sources.dir}"/>
<arg value="--proto_path=${protobuf.source.dir}"/>
<arg value="${protobuf.source.dir}/google/protobuf/any.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/api.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/descriptor.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/duration.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/empty.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/field_mask.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/source_context.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/struct.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/timestamp.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/type.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/wrappers.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/compiler/plugin.proto"/>
</exec>
</project>

@ -0,0 +1,34 @@
<project name="generate-test-sources">
<mkdir dir="${generated.testsources.dir}"/>
<exec executable="${protoc}">
<arg value="--java_out=${generated.testsources.dir}"/>
<arg value="--proto_path=${protobuf.source.dir}"/>
<arg value="--proto_path=${test.proto.dir}"/>
<arg value="--experimental_allow_proto3_optional"/>
<arg value="${protobuf.source.dir}/google/protobuf/map_proto2_unittest.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_import.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_import_lite.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public_lite.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_lite.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3.proto"/>
<arg value="${test.proto.dir}/com/google/protobuf/evil_names_proto2.proto"/>
<arg value="${test.proto.dir}/com/google/protobuf/evil_names_proto3.proto"/>
<arg value="${test.proto.dir}/com/google/protobuf/example_extensible_message.proto"/>
<arg value="${test.proto.dir}/com/google/protobuf/multiple_files_proto3.proto"/>
</exec>
<exec executable="${protoc}">
<arg value="--kotlin_out=${generated.testsources.dir}"/>
<arg value="--proto_path=${protobuf.source.dir}"/>
<arg value="--proto_path=${test.proto.dir}"/>
<arg value="--experimental_allow_proto3_optional"/>
<arg value="${protobuf.source.dir}/google/protobuf/map_proto2_unittest.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3.proto"/>
<arg value="${test.proto.dir}/com/google/protobuf/evil_names_proto2.proto"/>
<arg value="${test.proto.dir}/com/google/protobuf/evil_names_proto3.proto"/>
<arg value="${test.proto.dir}/com/google/protobuf/multiple_files_proto3.proto"/>
</exec>
</project>

@ -0,0 +1,240 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.15.6</version>
</parent>
<artifactId>protobuf-kotlin</artifactId>
<packaging>bundle</packaging>
<name>Protocol Buffers [Core]</name>
<description>
Core Protocol Buffers library. Protocol Buffers are a way of encoding structured data in an
efficient yet extensible format.
</description>
<properties>
<kotlin.version>1.4.31</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymockclassextension</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<!-- Include core protos in the bundle as resources -->
<resources>
<resource>
<directory>${protobuf.source.dir}</directory>
<includes>
<include>google/protobuf/any.proto</include>
<include>google/protobuf/api.proto</include>
<include>google/protobuf/descriptor.proto</include>
<include>google/protobuf/duration.proto</include>
<include>google/protobuf/empty.proto</include>
<include>google/protobuf/field_mask.proto</include>
<include>google/protobuf/source_context.proto</include>
<include>google/protobuf/struct.proto</include>
<include>google/protobuf/timestamp.proto</include>
<include>google/protobuf/type.proto</include>
<include>google/protobuf/wrappers.proto</include>
<include>google/protobuf/compiler/plugin.proto</include>
</includes>
</resource>
</resources>
<testResources>
<testResource>
<directory>${protobuf.source.dir}</directory>
<includes>
<include>google/protobuf/testdata/golden_message_oneof_implemented</include>
<include>google/protobuf/testdata/golden_packed_fields_message</include>
</includes>
</testResource>
</testResources>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy-test-source-files</id>
<phase>generate-test-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${generated.testsources.dir}/com/google/protobuf</outputDirectory>
<resources>
<resource>
<directory>${basedir}/../core/src/test/java/com/google/protobuf</directory>
<includes>
<include>TestUtil.java</include>
<include>TestUtilLite.java</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Use Antrun plugin to generate sources with protoc -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<!-- Generate core protos -->
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<target>
<ant antfile="generate-sources-build.xml"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<!-- Generate the test protos -->
<execution>
<id>generate-test-sources</id>
<phase>generate-test-sources</phase>
<configuration>
<target>
<ant antfile="generate-test-sources-build.xml"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Add the generated sources to the build -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-generated-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${generated.sources.dir}</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-generated-test-sources</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>${generated.testsources.dir}</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<id>compile</id>
<goals> <goal>compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${generated.sources.dir}</sourceDir>
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals> <goal>test-compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
<sourceDir>${generated.testsources.dir}</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<!-- OSGI bundle configuration -->
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Automatic-Module-Name>com.google.protobuf</Automatic-Module-Name> <!-- Java9+ Jigsaw module name -->
<Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
<Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
<Export-Package>com.google.protobuf;version=${project.version}</Export-Package>
<Import-Package>sun.misc;resolution:=optional,*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,27 @@
package com.google.protobuf.kotlin
/**
* A simple wrapper around a [List] with an extra generic parameter that can be used to disambiguate
* extension methods.
*
* <p>This class is used by Kotlin protocol buffer extensions, and its constructor is public only
* because generated message code is in a different compilation unit. Others should not use this
* class directly in any way.
*/
@Suppress("unused") // the unused type parameter
class DslList<E, P : DslProxy> @OnlyForUseByGeneratedProtoCode constructor(
private val delegate: List<E>
) : List<E> by delegate {
override fun iterator(): Iterator<E> = UnmodifiableIterator(delegate.iterator())
override fun listIterator(): ListIterator<E> = UnmodifiableListIterator(delegate.listIterator())
override fun listIterator(index: Int): ListIterator<E> =
UnmodifiableListIterator(delegate.listIterator(index))
override fun equals(other: Any?): Boolean = delegate == other
override fun hashCode(): Int = delegate.hashCode()
override fun toString(): String = delegate.toString()
}

@ -0,0 +1,30 @@
package com.google.protobuf.kotlin
/**
* A simple wrapper around a [Map] with an extra generic parameter that can be used to disambiguate
* extension methods.
*
* <p>This class is used by Kotlin protocol buffer extensions, and its constructor is public only
* because generated message code is in a different compilation unit. Others should not use this
* class directly in any way.
*/
@Suppress("unused") // the unused type parameter
class DslMap<K, V, P : DslProxy> @OnlyForUseByGeneratedProtoCode constructor(
private val delegate: Map<K, V>
) : Map<K, V> by delegate {
// We allocate the wrappers on calls to get, not with lazy {...}, because lazy allocates
// a few objects up front, and any kind of query operation on this object should be rare.
override val entries: Set<Map.Entry<K, V>>
get() = UnmodifiableMapEntries(delegate.entries)
override val keys: Set<K>
get() = UnmodifiableSet(delegate.keys)
override val values: Collection<V>
get() = UnmodifiableCollection(delegate.values)
override fun equals(other: Any?): Boolean = delegate == other
override fun hashCode(): Int = delegate.hashCode()
override fun toString(): String = delegate.toString()
}

@ -0,0 +1,12 @@
package com.google.protobuf.kotlin
/**
* A type meaningful only for its existence, never intended to be instantiated. For example,
* a `DslList<Int, FooProxy>` can be given different extension methods than a
* `DslList<Int, BarProxy>`.
*/
abstract class DslProxy @OnlyForUseByGeneratedProtoCode protected constructor() {
init {
throw UnsupportedOperationException("A DslProxy should never be instantiated")
}
}

@ -0,0 +1,26 @@
package com.google.protobuf.kotlin
import com.google.protobuf.ExtensionLite
import com.google.protobuf.GeneratedMessageV3
/** Sets the current value of the proto extension in this builder.*/
operator fun <
M : GeneratedMessageV3.ExtendableMessage<M>,
B : GeneratedMessageV3.ExtendableBuilder<M, B>,
T : Any
> B.set(extension: ExtensionLite<M, T>, value: T) {
setExtension(extension, value)
}
/** Gets the current value of the proto extension. */
operator fun <
M : GeneratedMessageV3.ExtendableMessage<M>,
MorBT : GeneratedMessageV3.ExtendableMessageOrBuilder<M>,
T : Any
> MorBT.get(extension: ExtensionLite<M, T>): T = getExtension(extension)
/** Returns true if the specified extension is set on this builder. */
operator fun <
M : GeneratedMessageV3.ExtendableMessage<M>,
MorBT : GeneratedMessageV3.ExtendableMessageOrBuilder<M>
> MorBT.contains(extension: ExtensionLite<M, *>): Boolean = hasExtension(extension)

@ -0,0 +1,28 @@
package com.google.protobuf.kotlin
import com.google.protobuf.ExtensionLite
import com.google.protobuf.GeneratedMessageLite
/** Gets the value of the proto extension. */
operator fun <
M : GeneratedMessageLite.ExtendableMessage<M, *>,
MOrBT : GeneratedMessageLite.ExtendableMessageOrBuilder<M, *>,
T : Any
> MOrBT.get(extension: ExtensionLite<M, T>): T = getExtension(extension)
/** Sets the current value of the proto extension in this builder. */
operator fun <
M : GeneratedMessageLite.ExtendableMessage<M, B>,
B : GeneratedMessageLite.ExtendableBuilder<M, B>,
T : Any
> B.set(extension: ExtensionLite<M, T>, value: T) {
setExtension(extension, value)
}
/** Returns true if the specified extension is set. */
operator fun <
M : GeneratedMessageLite.ExtendableMessage<M, *>,
MorBT : GeneratedMessageLite.ExtendableMessageOrBuilder<M, *>
> MorBT.contains(
extension: ExtensionLite<M, *>
): Boolean = hasExtension(extension)

@ -0,0 +1,27 @@
package com.google.protobuf.kotlin
import com.google.protobuf.ExtensionLite
import com.google.protobuf.MessageLite
/**
* Implementation for ExtensionList and ExtensionListLite. Like [DslList], represents an
* unmodifiable view of a repeated proto field -- in this case, an extension field -- but
* supports querying the extension.
*/
class ExtensionList<E, M : MessageLite> @OnlyForUseByGeneratedProtoCode constructor(
val extension: ExtensionLite<M, List<E>>,
@JvmField private val delegate: List<E>
) : List<E> by delegate {
override fun iterator(): Iterator<E> = UnmodifiableIterator(delegate.iterator())
override fun listIterator(): ListIterator<E> = UnmodifiableListIterator(delegate.listIterator())
override fun listIterator(index: Int): ListIterator<E> =
UnmodifiableListIterator(delegate.listIterator(index))
override fun equals(other: Any?): Boolean = delegate == other
override fun hashCode(): Int = delegate.hashCode()
override fun toString(): String = delegate.toString()
}

@ -0,0 +1,18 @@
package com.google.protobuf.kotlin
/**
* Opt-in annotation to make it difficult to accidentally use APIs only intended for use by proto
* generated code. See https://kotlinlang.org/docs/reference/opt-in-requirements.html for details
* on how this API works.
*/
@RequiresOptIn(
message =
"""
This API is only intended for use by generated protobuf code, the code generator, and their own
tests. If this does not describe your code, you should not be using this API.
""",
level = RequiresOptIn.Level.ERROR
)
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.CONSTRUCTOR, AnnotationTarget.ANNOTATION_CLASS)
annotation class OnlyForUseByGeneratedProtoCode

@ -0,0 +1,10 @@
package com.google.protobuf.kotlin
/**
* Indicates an API that is part of a DSL to generate protocol buffer messages.
*/
@DslMarker
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
@OnlyForUseByGeneratedProtoCode
annotation class ProtoDslMarker

@ -0,0 +1,39 @@
package com.google.protobuf.kotlin
/** Wraps an [Iterator] and makes it unmodifiable even from Java. */
internal class UnmodifiableIterator<E>(delegate: Iterator<E>) : Iterator<E> by delegate
/** Wraps a [ListIterator] and makes it unmodifiable even from Java. */
internal class UnmodifiableListIterator<E>(
delegate: ListIterator<E>
) : ListIterator<E> by delegate
/** Wraps a [Collection] and makes it unmodifiable even from Java. */
internal open class UnmodifiableCollection<E>(
private val delegate: Collection<E>
) : Collection<E> by delegate {
override fun iterator(): Iterator<E> = UnmodifiableIterator(delegate.iterator())
}
/** Wraps a [Set] and makes it unmodifiable even from Java. */
internal class UnmodifiableSet<E>(
delegate: Collection<E>
) : UnmodifiableCollection<E>(delegate), Set<E>
/** Wraps a [Map.Entry] and makes it unmodifiable even from Java. */
internal class UnmodifiableMapEntry<K, V>(delegate: Map.Entry<K, V>) : Map.Entry<K, V> by delegate
/** Wraps a [Set] of map entries and makes it unmodifiable even from Java. */
internal class UnmodifiableMapEntries<K, V>(
private val delegate: Set<Map.Entry<K, V>>
) : UnmodifiableCollection<Map.Entry<K, V>>(delegate), Set<Map.Entry<K, V>> {
// Is this overkill? Probably.
override fun iterator(): Iterator<Map.Entry<K, V>> {
val itr = delegate.iterator()
return object : Iterator<Map.Entry<K, V>> by itr {
override fun next(): Map.Entry<K, V> = UnmodifiableMapEntry(itr.next())
}
}
}

@ -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 example_extensible_message.ExampleExtensibleMessage
import example_extensible_message.ExampleExtensibleMessageOuterClass 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,125 @@
package com.google.protobuf.kotlin
import com.google.common.testing.EqualsTester
import com.google.common.truth.Truth.assertThat
import example_extensible_message.ExampleExtensibleMessage
import example_extensible_message.ExampleExtensibleMessageOuterClass 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,891 @@
package com.google.protobuf.kotlin
import com.google.common.truth.Truth.assertThat
import com.google.protobuf.TestUtil
import com.google.protobuf.TestUtil.toBytes
import evil_names_proto2.EvilNamesProto2OuterClass.EvilNamesProto2
import evil_names_proto2.EvilNamesProto2OuterClass.HardKeywordsAllTypes
import evil_names_proto2.EvilNamesProto2OuterClass.Interface
import evil_names_proto2.HardKeywordsAllTypesKt
import evil_names_proto2.evilNamesProto2
import evil_names_proto2.hardKeywordsAllTypes
import evil_names_proto2.interface_
import com.google.protobuf.test.UnittestImport.ImportEnum
import com.google.protobuf.test.UnittestImport.ImportMessage
import com.google.protobuf.test.UnittestImportPublic.PublicImportMessage
import protobuf_unittest.MapProto2Unittest.Proto2MapEnum
import protobuf_unittest.MapProto2Unittest.TestEnumMap
import protobuf_unittest.MapProto2Unittest.TestIntIntMap
import protobuf_unittest.MapProto2Unittest.TestMaps
import protobuf_unittest.TestAllTypesKt
import protobuf_unittest.TestAllTypesKt.nestedMessage
import protobuf_unittest.UnittestProto
import protobuf_unittest.UnittestProto.ForeignEnum
import protobuf_unittest.UnittestProto.TestAllTypes
import protobuf_unittest.UnittestProto.TestAllTypes.NestedEnum
import protobuf_unittest.UnittestProto.TestEmptyMessage
import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions
import protobuf_unittest.copy
import protobuf_unittest.foreignMessage
import protobuf_unittest.optionalGroupExtension
import protobuf_unittest.repeatedGroupExtension
import protobuf_unittest.testAllExtensions
import protobuf_unittest.testAllTypes
import protobuf_unittest.testEmptyMessage
import protobuf_unittest.testEmptyMessageWithExtensions
import protobuf_unittest.testEnumMap
import protobuf_unittest.testIntIntMap
import protobuf_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].add(301)
this[UnittestProto.repeatedInt64Extension].add(302L)
this[UnittestProto.repeatedUint32Extension].add(303)
this[UnittestProto.repeatedUint64Extension].add(304L)
this[UnittestProto.repeatedSint32Extension].add(305)
this[UnittestProto.repeatedSint64Extension].add(306L)
this[UnittestProto.repeatedFixed32Extension].add(307)
this[UnittestProto.repeatedFixed64Extension].add(308L)
this[UnittestProto.repeatedSfixed32Extension].add(309)
this[UnittestProto.repeatedSfixed64Extension].add(310L)
this[UnittestProto.repeatedFloatExtension].add(311F)
this[UnittestProto.repeatedDoubleExtension].add(312.0)
this[UnittestProto.repeatedBoolExtension].add(false)
this[UnittestProto.repeatedStringExtension].add("315")
this[UnittestProto.repeatedBytesExtension].add(toBytes("316"))
this[UnittestProto.repeatedGroupExtension].add(repeatedGroupExtension { a = 317 })
this[UnittestProto.repeatedNestedMessageExtension]
.add(TestAllTypesKt.nestedMessage { bb = 318 })
this[UnittestProto.repeatedForeignMessageExtension].add(foreignMessage { c = 319 })
this[UnittestProto.repeatedImportMessageExtension]
.add(ImportMessage.newBuilder().setD(320).build())
this[UnittestProto.repeatedLazyMessageExtension]
.add(TestAllTypesKt.nestedMessage { bb = 327 })
this[UnittestProto.repeatedNestedEnumExtension].add(NestedEnum.BAZ)
this[UnittestProto.repeatedForeignEnumExtension].add(ForeignEnum.FOREIGN_BAZ)
this[UnittestProto.repeatedImportEnumExtension].add(ImportEnum.IMPORT_BAZ)
this[UnittestProto.repeatedStringPieceExtension].add("324")
this[UnittestProto.repeatedCordExtension].add("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 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,340 @@
package com.google.protobuf.kotlin
import com.google.common.truth.Truth.assertThat
import evil_names_proto3.EvilNamesProto3OuterClass.EvilNamesProto3
import evil_names_proto3.EvilNamesProto3OuterClass.HardKeywordsAllTypes
import evil_names_proto3.EvilNamesProto3OuterClass.Class
import evil_names_proto3.HardKeywordsAllTypesKt
import evil_names_proto3.class_
import evil_names_proto3.evilNamesProto3
import evil_names_proto3.hardKeywordsAllTypes
import multiple_files_proto3.MultipleFilesMessageA
import multiple_files_proto3.MultipleFilesMessageB
import multiple_files_proto3.multipleFilesMessageA
import multiple_files_proto3.multipleFilesMessageB
import proto3_unittest.UnittestProto3
import proto3_unittest.TestAllTypesKt
import proto3_unittest.TestAllTypesKt.nestedMessage
import proto3_unittest.UnittestProto3.TestAllTypes
import proto3_unittest.UnittestProto3.TestAllTypes.NestedEnum
import proto3_unittest.UnittestProto3.TestEmptyMessage
import proto3_unittest.copy
import proto3_unittest.testAllTypes
import 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(
multipleFilesMessageA {}
).isEqualTo(
MultipleFilesMessageA.newBuilder().build()
)
assertThat(
multipleFilesMessageB {}
).isEqualTo(
MultipleFilesMessageB.newBuilder().build()
)
}
}

@ -0,0 +1,62 @@
syntax = "proto2";
package evil_names_proto2;
option java_package = "evil_names_proto2";
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,76 @@
syntax = "proto3";
package evil_names_proto3;
option java_package = "evil_names_proto3";
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,16 @@
syntax = "proto2";
package example_extensible_message;
option java_package = "example_extensible_message";
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;
}

@ -0,0 +1,12 @@
syntax = "proto3";
package multiple_files_proto3;
option java_package = "multiple_files_proto3";
option java_multiple_files = true;
enum NestedEnum { FOO = 0; }
message MultipleFilesMessageA {}
message MultipleFilesMessageB {}

@ -150,6 +150,7 @@ nobase_include_HEADERS = \
google/protobuf/compiler/csharp/csharp_generator.h \
google/protobuf/compiler/csharp/csharp_names.h \
google/protobuf/compiler/java/java_generator.h \
google/protobuf/compiler/java/java_kotlin_generator.h \
google/protobuf/compiler/java/java_names.h \
google/protobuf/compiler/js/js_generator.h \
google/protobuf/compiler/js/well_known_types_embed.h \
@ -376,6 +377,7 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/java/java_generator_factory.h \
google/protobuf/compiler/java/java_helpers.cc \
google/protobuf/compiler/java/java_helpers.h \
google/protobuf/compiler/java/java_kotlin_generator.cc \
google/protobuf/compiler/java/java_map_field.cc \
google/protobuf/compiler/java/java_map_field.h \
google/protobuf/compiler/java/java_map_field_lite.cc \

@ -63,6 +63,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);
@ -76,6 +77,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.
@ -270,6 +276,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
@ -1037,6 +1071,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;

@ -70,6 +70,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);
@ -83,6 +84,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)) {
@ -275,6 +281,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_)) {
@ -774,6 +808,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());
}

@ -73,6 +73,7 @@ class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator {
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16_t>* output) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;
@ -118,6 +119,7 @@ class RepeatedImmutableEnumFieldLiteGenerator
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16_t>* 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,

@ -84,6 +84,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;
@ -106,6 +107,7 @@ class ImmutableFieldLiteGenerator {
virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
virtual void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16_t>* 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

@ -91,6 +91,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]) {
@ -156,6 +167,38 @@ void PrintEnumVerifierLogic(io::Printer* printer,
StrCat(enum_verifier_string, terminating_string).c_str());
}
std::string ToCamelCase(const std::string& input, bool lower_first) {
bool capitalize_next = !lower_first;
std::string result;
result.reserve(input.size());
for (char i : input) {
if (i == '_') {
capitalize_next = true;
} else if (capitalize_next) {
result.push_back(ToUpperCh(i));
capitalize_next = false;
} else {
result.push_back(i);
}
}
// Lower-case the first letter.
if (lower_first && !result.empty()) {
result[0] = ToLowerCh(result[0]);
}
return result;
}
char ToUpperCh(char ch) {
return (ch >= 'a' && ch <= 'z') ? (ch - 'a' + 'A') : ch;
}
char ToLowerCh(char ch) {
return (ch >= 'A' && ch <= 'Z') ? (ch - 'A' + 'a') : ch;
}
std::string UnderscoresToCamelCase(const std::string& input,
bool cap_next_letter) {
GOOGLE_CHECK(!input.empty());
@ -217,6 +260,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);
@ -423,6 +470,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.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return NULL;
}
std::string GetOneofStoredType(const FieldDescriptor* field) {
const JavaType javaType = GetJavaType(field);

@ -53,6 +53,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
@ -73,6 +74,13 @@ void PrintEnumVerifierLogic(io::Printer* printer,
const char* var_name,
const char* terminating_string, bool enforce_lite);
// Converts a name to camel-case. If cap_first_letter is true, capitalize the
// first letter.
std::string ToCamelCase(const std::string& input, bool lower_first);
char ToUpperCh(char ch);
char ToLowerCh(char ch);
// Converts a name to camel-case. If cap_first_letter is true, capitalize the
// first letter.
std::string UnderscoresToCamelCase(const std::string& name,
@ -216,6 +224,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 <google/protobuf/compiler/java/java_kotlin_generator.h>
#include <memory>
#include <google/protobuf/compiler/java/java_file.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/compiler/java/java_options.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
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(new 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 protobuf
} // namespace google

@ -0,0 +1,40 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_KOTLIN_GENERATOR_H_
#define GOOGLE_PROTOBUF_COMPILER_JAVA_KOTLIN_GENERATOR_H_
#include <string>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace compiler {
namespace java {
// CodeGenerator implementation which generates Kotlin code. If you create your
// own protocol compiler binary and you want it to support Kotlin output, you
// can do so by registering an instance of this CodeGenerator with the
// CommandLineInterface in your main() function.
class PROTOC_EXPORT KotlinGenerator : public CodeGenerator {
public:
KotlinGenerator();
~KotlinGenerator() override;
// implements CodeGenerator ----------------------------------------
bool Generate(const FileDescriptor* file, const std::string& parameter,
GeneratorContext* context, std::string* error) const override;
uint64_t GetSupportedFeatures() const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(KotlinGenerator);
};
} // namespace java
} // namespace compiler
} // namespace protobuf
} // namespace google
#include <google/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_KOTLIN_GENERATOR_H_

@ -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;

@ -71,6 +71,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()));
@ -92,6 +103,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
@ -137,6 +150,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";
@ -794,6 +812,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.

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

@ -1358,6 +1358,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_;

@ -60,6 +60,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"] =
@ -69,6 +70,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"] =
@ -407,6 +413,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_)) {
@ -1361,6 +1393,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;

@ -61,6 +61,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"] =
@ -70,6 +71,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)) {
@ -277,6 +283,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_t>* output) const {
WriteIntToUtf16CharSequence(descriptor_->number(), output);
@ -751,6 +783,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

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

@ -724,6 +724,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.

@ -68,6 +68,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 ||
@ -129,6 +130,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);
@ -298,6 +304,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 {
@ -793,6 +826,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;

@ -74,6 +74,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"] =
@ -137,6 +138,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);
@ -303,6 +309,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_t>* output) const {
@ -615,6 +648,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_t>* output) const {
WriteIntToUtf16CharSequence(descriptor_->number(), output);

@ -73,6 +73,7 @@ class ImmutablePrimitiveFieldLiteGenerator
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16_t>* output) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;
@ -119,7 +120,8 @@ class RepeatedImmutablePrimitiveFieldLiteGenerator
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateFieldInfo(io::Printer* printer,
std::vector<uint16_t>* output) const;
void GenerateKotlinDslMembers(io::Printer* printer) const;
std::string GetBoxedType() const;
private:

@ -90,6 +90,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)) {
@ -367,6 +372,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
@ -916,6 +949,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;

@ -86,6 +86,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)) {
@ -304,6 +309,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_t>* output) const {
WriteIntToUtf16CharSequence(descriptor_->number(), output);
@ -704,6 +737,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_t>* output) const {
WriteIntToUtf16CharSequence(descriptor_->number(), output);

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

@ -30,6 +30,7 @@
#include <google/protobuf/compiler/cpp/cpp_generator.h>
#include <google/protobuf/compiler/java/java_generator.h>
#include <google/protobuf/compiler/java/java_kotlin_generator.h>
#include <google/protobuf/compiler/js/js_generator.h>
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/compiler/python/python_generator.h>
@ -64,6 +65,10 @@ int ProtobufMain(int argc, char* argv[]) {
cli.RegisterGenerator("--java_out", "--java_opt", &java_generator,
"Generate Java source file.");
// Proto2 Kotlin
java::KotlinGenerator kt_generator;
cli.RegisterGenerator("--kotlin_out", "--kotlin_opt", &kt_generator,
"Generate Kotlin file.");
// Proto2 Python

Loading…
Cancel
Save