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

[Optics] Show error for generic classes in KSP plug-in #2636

Merged
merged 1 commit into from Jan 12, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
46 changes: 23 additions & 23 deletions arrow-libs/optics/arrow-optics-ksp-plugin/build.gradle.kts
@@ -1,5 +1,5 @@
plugins {
id(libs.plugins.kotlin.jvm.get().pluginId)
id(libs.plugins.kotlin.multiplatform.get().pluginId)
alias(libs.plugins.arrowGradleConfig.kotlin)
alias(libs.plugins.arrowGradleConfig.publish)
}
Expand All @@ -11,27 +11,27 @@ kotlin {
apply(from = property("TEST_COVERAGE"))
apply(from = property("ANIMALSNIFFER_MPP"))

dependencies {
implementation(libs.ksp)

testImplementation(libs.kotlin.stdlibJDK8)
testImplementation(libs.junitJupiter)
testImplementation(libs.junitJupiterEngine)
testImplementation(libs.assertj)
testImplementation(libs.classgraph)
testImplementation(libs.kotlinCompileTesting) {
exclude(
group = libs.classgraph.get().module.group,
module = libs.classgraph.get().module.name
)
exclude(
group = libs.kotlin.stdlibJDK8.get().module.group,
module = libs.kotlin.stdlibJDK8.get().module.name
)
kotlin {
sourceSets {
jvmMain {
dependencies {
implementation(libs.ksp)
}
}
jvmTest {
dependencies {
implementation(libs.kotlin.stdlibJDK8)
implementation(libs.junitJupiter)
implementation(libs.junitJupiterEngine)
implementation(libs.assertj)
implementation(libs.classgraph)
implementation(libs.kotlinCompileTesting)
implementation(libs.kotlinCompileTestingKsp)
runtimeOnly(projects.arrowOpticsKspPlugin)
runtimeOnly(projects.arrowAnnotations)
runtimeOnly(projects.arrowCore)
runtimeOnly(projects.arrowOptics)
}
}
}
testImplementation(libs.kotlinCompileTestingKsp)
testRuntimeOnly(projects.arrowOpticsKspPlugin)
testRuntimeOnly(projects.arrowAnnotations)
testRuntimeOnly(projects.arrowCore)
testRuntimeOnly(projects.arrowOptics)
}
Expand Up @@ -7,6 +7,7 @@ import arrow.optics.plugin.internals.join
import arrow.optics.plugin.internals.noCompanion
import arrow.optics.plugin.internals.otherClassTypeErrorMessage
import arrow.optics.plugin.internals.snippets
import arrow.optics.plugin.internals.typeParametersErrorMessage
import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.KSPLogger
Expand Down Expand Up @@ -36,14 +37,21 @@ class OpticsProcessor(private val codegen: CodeGenerator, private val logger: KS
return
}

// check that it does not have type arguments
if (klass.typeParameters.isNotEmpty()) {
logger.error(klass.simpleName.asString().typeParametersErrorMessage, klass)
return
}

// check that the companion object exists
val companion = klass.companionObject
if (companion == null) {
if (klass.companionObject == null) {
logger.error(klass.simpleName.asString().noCompanion, klass)
return
}

adt(klass, logger).snippets().groupBy(Snippet::fqName).values.map(List<Snippet>::join).forEach {
val adts = adt(klass, logger)
val snippets = adts.snippets()
snippets.groupBy(Snippet::fqName).values.map(List<Snippet>::join).forEach {
val writer =
codegen
.createNewFile(
Expand Down
Expand Up @@ -5,8 +5,14 @@ val String.otherClassTypeErrorMessage
"""
|$this cannot be annotated with @optics
| ^
|
|Only data and sealed classes can be annotated with @optics annotation""".trimMargin()
|Only data and sealed classes can be annotated with @optics""".trimMargin()

val String.typeParametersErrorMessage
get() =
"""
|$this cannot be annotated with @optics
| ^
|Only classes with no type parameters can be annotated with @optics""".trimMargin()

val String.lensErrorMessage
get() =
Expand Down Expand Up @@ -56,10 +62,14 @@ val String.dslErrorMessage
get() =
"""
|Cannot generate DSL (arrow.optics.BoundSetter) for $this
| ^
| ^
|arrow.optics.OpticsTarget.DSL is an invalid @optics argument for $this.
|It is only valid for data classes and sealed classes.
""".trimMargin()

val String.noCompanion
get() = "@optics annotated class $this needs to declare companion object."
get() =
"""
|$this must declare a companion object
| ^
|A companion object is required for the generated optics""".trimMargin()
@@ -1,5 +1,6 @@
package arrow.optics.plugin

import arrow.optics.plugin.internals.typeParametersErrorMessage
import org.junit.jupiter.api.Test

class LensTests {
Expand Down Expand Up @@ -32,4 +33,34 @@ class LensTests {
|val r = i != null
""".evals("r" to true)
}

@Test
fun `Lenses which mentions imported elements`() {
Copy link
Member

Choose a reason for hiding this comment

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

👏

"""
|$imports
|import kotlin.time.Duration
|
|@optics
|data class OpticsTest(val time: Duration) {
| companion object
|}
|
|val i: Lens<OpticsTest, Duration> = OpticsTest.time
|val r = i != null
""".evals("r" to true)
}

@Test
fun `Lenses which mentions type arguments`() {
"""
|$imports
|@optics
|data class OpticsTest<A>(val field: A) {
| companion object
|}
|
|val i: Lens<OpticsTest, Int> = OpticsTest<Int>.time
|val r = i != null
""".failsWith { it.contains("OpticsTest".typeParametersErrorMessage) }
}
}