Skip to content

Commit

Permalink
Check for same subtypes before erroring on duplicate labels (#602)
Browse files Browse the repository at this point in the history
Resolves #507
  • Loading branch information
ZacSweers authored May 28, 2024
1 parent 7a8ce53 commit 835513e
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Changelog

- Improve moshi-sealed KSP error messages.
- Fix fallback adapter support in IR code gen not recognizing Moshi parameters to primary constructors.
- Check for same subtypes before erroring on duplicate labels in moshi-sealed IR.

0.27.0
------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,10 @@ private constructor(
}

seenLabels.put(mainLabel, subtype)?.let { prev ->
logger.error(target) {
"Duplicate label '$mainLabel' defined for ${subtype.fqNameWhenAvailable} and ${prev.fqNameWhenAvailable}."
if (prev != subtype) {
logger.error(target) {
"Duplicate label '$mainLabel' defined for ${subtype.fqNameWhenAvailable} and ${prev.fqNameWhenAvailable}."
}
}
return null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,36 @@ class MoshiIrVisitorTest(private val useK2: Boolean) {
assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK)
}

// Covers cases where a nested sealed interface is also implemented by a subtype that implements
// the super type
@Test
fun nestedSealedWithCommonSubtypes() {
val source =
kotlin(
"BaseType.kt",
"""
package test
import com.squareup.moshi.JsonClass
import dev.zacsweers.moshix.sealed.annotations.TypeLabel
import dev.zacsweers.moshix.sealed.annotations.NestedSealed
@JsonClass(generateAdapter = true, generator = "sealed:type")
sealed interface Foo {
@NestedSealed
sealed interface SuperFoo : Foo
@JsonClass(generateAdapter = true)
@TypeLabel("real")
data class RealFoo(val value: String) : SuperFoo, Foo
}
""",
)

val result = compile(source)
assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK)
}

private fun prepareCompilation(
generatedAnnotation: String? = null,
vararg sourceFiles: SourceFile,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,8 +418,10 @@ private class MoshiSealedSymbolProcessor(environment: SymbolProcessorEnvironment
}

seenLabels.put(mainLabel, className)?.let { prev ->
logger.error("Duplicate label '$mainLabel' defined for $className and $prev.", rootType)
return null
if (prev != className) {
logger.error("Duplicate label '$mainLabel' defined for $className and $prev.", rootType)
return null
}
}

labels += mainLabel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,36 @@ class MoshiSealedSymbolProcessorProviderTest(private val useKSP2: Boolean) {
)
}

// Covers cases where a nested sealed interface is also implemented by a subtype that implements
// the super type
@Test
fun nestedSealedWithCommonSubtypes() {
val source =
kotlin(
"BaseType.kt",
"""
package test
import com.squareup.moshi.JsonClass
import dev.zacsweers.moshix.sealed.annotations.TypeLabel
import dev.zacsweers.moshix.sealed.annotations.NestedSealed
@JsonClass(generateAdapter = true, generator = "sealed:type")
sealed interface Foo {
@NestedSealed
sealed interface SuperFoo : Foo
@JsonClass(generateAdapter = true)
@TypeLabel("real")
data class RealFoo(val value: String) : SuperFoo, Foo
}
""",
)

val result = compile(source)
assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK)
}

private fun prepareCompilation(vararg sourceFiles: SourceFile): KotlinCompilation =
KotlinCompilation().apply {
sources = sourceFiles.toList()
Expand Down

0 comments on commit 835513e

Please sign in to comment.