Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate unrecognized constant for enums if option is true #2885

Merged
merged 3 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions wire-kotlin-generator/api/wire-kotlin-generator.api
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
public final class com/squareup/wire/kotlin/KotlinGenerator {
public static final field Companion Lcom/squareup/wire/kotlin/KotlinGenerator$Companion;
public synthetic fun <init> (Lcom/squareup/wire/schema/Schema;Ljava/util/Map;Ljava/util/Map;Lcom/squareup/wire/schema/Profile;ZZZZLcom/squareup/wire/kotlin/RpcCallStyle;Lcom/squareup/wire/kotlin/RpcRole;ILjava/lang/String;ZZLkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Lcom/squareup/wire/schema/Schema;Ljava/util/Map;Ljava/util/Map;Lcom/squareup/wire/schema/Profile;ZZZZLcom/squareup/wire/kotlin/RpcCallStyle;Lcom/squareup/wire/kotlin/RpcRole;ILjava/lang/String;ZZZLkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun generateOptionType (Lcom/squareup/wire/schema/Extend;Lcom/squareup/wire/schema/Field;)Lcom/squareup/kotlinpoet/TypeSpec;
public final fun generateServiceTypeSpecs (Lcom/squareup/wire/schema/Service;Lcom/squareup/wire/schema/Rpc;)Ljava/util/Map;
public static synthetic fun generateServiceTypeSpecs$default (Lcom/squareup/wire/kotlin/KotlinGenerator;Lcom/squareup/wire/schema/Service;Lcom/squareup/wire/schema/Rpc;ILjava/lang/Object;)Ljava/util/Map;
Expand All @@ -9,14 +9,14 @@ public final class com/squareup/wire/kotlin/KotlinGenerator {
public static synthetic fun generatedServiceName$default (Lcom/squareup/wire/kotlin/KotlinGenerator;Lcom/squareup/wire/schema/Service;Lcom/squareup/wire/schema/Rpc;ZILjava/lang/Object;)Lcom/squareup/kotlinpoet/ClassName;
public final fun generatedTypeName (Lcom/squareup/wire/schema/ProtoMember;)Lcom/squareup/kotlinpoet/ClassName;
public final fun generatedTypeName (Lcom/squareup/wire/schema/Type;)Lcom/squareup/kotlinpoet/ClassName;
public static final fun get (Lcom/squareup/wire/schema/Schema;Lcom/squareup/wire/schema/Profile;ZZZZLcom/squareup/wire/kotlin/RpcCallStyle;Lcom/squareup/wire/kotlin/RpcRole;ILjava/lang/String;ZZ)Lcom/squareup/wire/kotlin/KotlinGenerator;
public static final fun get (Lcom/squareup/wire/schema/Schema;Lcom/squareup/wire/schema/Profile;ZZZZLcom/squareup/wire/kotlin/RpcCallStyle;Lcom/squareup/wire/kotlin/RpcRole;ILjava/lang/String;ZZZ)Lcom/squareup/wire/kotlin/KotlinGenerator;
public final fun getSchema ()Lcom/squareup/wire/schema/Schema;
}

public final class com/squareup/wire/kotlin/KotlinGenerator$Companion {
public final fun builtInType (Lcom/squareup/wire/schema/ProtoType;)Z
public final fun get (Lcom/squareup/wire/schema/Schema;Lcom/squareup/wire/schema/Profile;ZZZZLcom/squareup/wire/kotlin/RpcCallStyle;Lcom/squareup/wire/kotlin/RpcRole;ILjava/lang/String;ZZ)Lcom/squareup/wire/kotlin/KotlinGenerator;
public static synthetic fun get$default (Lcom/squareup/wire/kotlin/KotlinGenerator$Companion;Lcom/squareup/wire/schema/Schema;Lcom/squareup/wire/schema/Profile;ZZZZLcom/squareup/wire/kotlin/RpcCallStyle;Lcom/squareup/wire/kotlin/RpcRole;ILjava/lang/String;ZZILjava/lang/Object;)Lcom/squareup/wire/kotlin/KotlinGenerator;
public final fun get (Lcom/squareup/wire/schema/Schema;Lcom/squareup/wire/schema/Profile;ZZZZLcom/squareup/wire/kotlin/RpcCallStyle;Lcom/squareup/wire/kotlin/RpcRole;ILjava/lang/String;ZZZ)Lcom/squareup/wire/kotlin/KotlinGenerator;
public static synthetic fun get$default (Lcom/squareup/wire/kotlin/KotlinGenerator$Companion;Lcom/squareup/wire/schema/Schema;Lcom/squareup/wire/schema/Profile;ZZZZLcom/squareup/wire/kotlin/RpcCallStyle;Lcom/squareup/wire/kotlin/RpcRole;ILjava/lang/String;ZZZILjava/lang/Object;)Lcom/squareup/wire/kotlin/KotlinGenerator;
}

public final class com/squareup/wire/kotlin/KotlinSchemaHandler : com/squareup/wire/schema/SchemaHandler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ class KotlinGenerator private constructor(
private val nameSuffix: String?,
private val buildersOnly: Boolean,
private val escapeKotlinKeywords: Boolean,
/**
* If true, generated enums will have an extra `UNRECOGNIZED` constant with a value of `-1`. This
* only applies to enum which syntax is proto3.
*/
private val generateUnrecognizedEnumConstant: Boolean,
) {
private val nameAllocatorStore = mutableMapOf<Type, NameAllocator>()

Expand Down Expand Up @@ -2214,6 +2219,24 @@ class KotlinGenerator private constructor(
* }
*/
private fun generateEnum(enum: EnumType): TypeSpec {
@Suppress("NAME_SHADOWING")
val enum =
if (enum.syntax == Syntax.PROTO_3 && generateUnrecognizedEnumConstant) {
enum.copy(
constants = enum.constants + listOf(
EnumConstant(
location = enum.location,
name = "UNRECOGNIZED",
tag = -1,
documentation = "",
options = Options(optionType = ENUM_OPTIONS, optionElements = listOf()),
),
),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super-nit: the order perhaps does not matter but does protoc list -1 tag first?

Suggested change
constants = enum.constants + listOf(
EnumConstant(
location = enum.location,
name = "UNRECOGNIZED",
tag = -1,
documentation = "",
options = Options(optionType = ENUM_OPTIONS, optionElements = listOf()),
),
),
constants = listOf(
EnumConstant(
location = enum.location,
name = "UNRECOGNIZED",
tag = -1,
documentation = "",
options = Options(optionType = ENUM_OPTIONS, optionElements = listOf()),
),
) + enum.constants,

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

protoc adds it at the end. But it doesn't matter really. We can put it in front

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

)
} else {
enum
}

val type = enum.type
val nameAllocator = nameAllocator(enum)

Expand Down Expand Up @@ -2886,6 +2909,7 @@ class KotlinGenerator private constructor(
nameSuffix: String? = null,
buildersOnly: Boolean = false,
escapeKotlinKeywords: Boolean = false,
generateUnrecognizedEnumConstant: Boolean = false,
): KotlinGenerator {
val typeToKotlinName = mutableMapOf<ProtoType, TypeName>()
val memberToKotlinName = mutableMapOf<ProtoMember, TypeName>()
Expand Down Expand Up @@ -2934,6 +2958,7 @@ class KotlinGenerator private constructor(
nameSuffix = nameSuffix,
buildersOnly = buildersOnly,
escapeKotlinKeywords = escapeKotlinKeywords,
generateUnrecognizedEnumConstant = generateUnrecognizedEnumConstant,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,50 @@ class KotlinGeneratorTest {
assertThat(code).contains("WORK(1),")
}

@Test fun generateUnrecognizedEnumConstantIsIgnoredForProto2() {
val schema = buildSchema {
add(
"message.proto".toPath(),
"""
|syntax = "proto2";
|enum PhoneType {
| HOME = 0;
| WORK = 1;
| MOBILE = 2;
|}
""".trimMargin(),
)
}
val code = KotlinWithProfilesGenerator(schema)
.generateKotlin("PhoneType", generateUnrecognizedEnumConstant = true)
assertThat(code).contains("HOME(0),")
assertThat(code).contains("WORK(1),")
assertThat(code).contains("MOBILE(2),")
assertThat(code).doesNotContain("UNRECOGNIZED(-1),")
}

@Test fun generateUnrecognizedEnumConstantIsAppliedForProto3() {
val schema = buildSchema {
add(
"message.proto".toPath(),
"""
|syntax = "proto3";
|enum PhoneType {
| HOME = 0;
| WORK = 1;
| MOBILE = 2;
|}
""".trimMargin(),
)
}
val code = KotlinWithProfilesGenerator(schema)
.generateKotlin("PhoneType", generateUnrecognizedEnumConstant = true)
assertThat(code).contains("HOME(0),")
assertThat(code).contains("WORK(1),")
assertThat(code).contains("MOBILE(2),")
assertThat(code).contains("UNRECOGNIZED(-1),")
}

@Test fun defaultValues() {
val schema = buildSchema {
add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,15 @@ internal class KotlinWithProfilesGenerator(private val schema: Schema) {
boxOneOfsMinSize: Int = 5_000,
buildersOnly: Boolean = false,
javaInterop: Boolean = false,
generateUnrecognizedEnumConstant: Boolean = false,
): String {
val kotlinGenerator = KotlinGenerator(
schema,
profile = profile(profileName),
boxOneOfsMinSize = boxOneOfsMinSize,
buildersOnly = buildersOnly,
javaInterop = javaInterop,
generateUnrecognizedEnumConstant = generateUnrecognizedEnumConstant,
)
val type = schema.getType(typeName)!!
val typeSpec = kotlinGenerator.generateType(type)
Expand Down