Skip to content

Commit

Permalink
fix imports for ksp plugin (#2678)
Browse files Browse the repository at this point in the history
  • Loading branch information
i-walker committed Mar 8, 2022
1 parent e9528b4 commit ba979cf
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import arrow.optics.plugin.internals.asFileText
import arrow.optics.plugin.internals.join
import arrow.optics.plugin.internals.noCompanion
import arrow.optics.plugin.internals.otherClassTypeErrorMessage
import arrow.optics.plugin.internals.qualifiedNameOrSimpleName
import arrow.optics.plugin.internals.snippets
import arrow.optics.plugin.internals.typeParametersErrorMessage
import com.google.devtools.ksp.processing.CodeGenerator
Expand Down Expand Up @@ -33,19 +34,19 @@ class OpticsProcessor(private val codegen: CodeGenerator, private val logger: KS
private fun processClass(klass: KSClassDeclaration) {
// check that it is sealed or data
if (!klass.isSealed && !klass.isData) {
logger.error(klass.simpleName.asString().otherClassTypeErrorMessage, klass)
logger.error(klass.qualifiedNameOrSimpleName.otherClassTypeErrorMessage, klass)
return
}

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

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSName
import java.util.Locale

data class ADT(val pckg: KSName, val el: KSClassDeclaration, val targets: List<Target>) {
val sourceClassName = el.qualifiedName?.asString() ?: el.simpleName
val sourceName = el.simpleName.asString().replaceFirstChar { it.lowercase(Locale.getDefault()) }
val simpleName = el.simpleName.asString()
data class ADT(val pckg: KSName, val declaration: KSClassDeclaration, val targets: List<Target>) {
val sourceClassName = declaration.qualifiedNameOrSimpleName
val sourceName = declaration.simpleName.asString().replaceFirstChar { it.lowercase(Locale.getDefault()) }
val simpleName = declaration.simpleName.asString()
val packageName = pckg.asString()

operator fun Snippet.plus(snippet: Snippet): Snippet =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ package arrow.optics.plugin.internals
fun generateLensDsl(ele: ADT, optic: DataClassDsl): Snippet =
Snippet(
`package` = ele.packageName,
name = ele.simpleName,
name = ele.sourceClassName,
content = processLensSyntax(ele, optic.foci)
)

fun generateOptionalDsl(ele: ADT, optic: DataClassDsl): Snippet =
Snippet(
`package` = ele.packageName,
name = ele.simpleName,
name = ele.sourceClassName,
content = processOptionalSyntax(ele, optic)
)

fun generatePrismDsl(ele: ADT, isoOptic: SealedClassDsl): Snippet =
Snippet(
`package` = ele.packageName,
name = ele.simpleName,
name = ele.sourceClassName,
content = processPrismSyntax(ele, isoOptic)
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package arrow.optics.plugin.internals

internal fun generateIsos(ele: ADT, target: IsoTarget) =
Snippet(`package` = ele.packageName, name = ele.simpleName, content = processElement(ele, target))
Snippet(`package` = ele.packageName, name = ele.sourceClassName, content = processElement(ele, target))

inline val Target.targetNames
inline get() = foci.map(Focus::className)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import java.util.Locale
internal fun generateLenses(ele: ADT, target: LensTarget) =
Snippet(
`package` = ele.packageName,
name = ele.simpleName,
name = ele.sourceClassName,
content = processElement(ele, target.foci)
)

Expand All @@ -20,12 +20,22 @@ private fun String.toUpperCamelCase(): String =
}
)

private fun processElement(ele: ADT, foci: List<Focus>): String =
private fun processElement(adt: ADT, foci: List<Focus>): String =
foci.joinToString(separator = "\n") { focus ->
"""
|inline val ${ele.sourceClassName}.Companion.${focus.lensParamName()}: $Lens<${ele.sourceClassName}, ${focus.className}> inline get()= $Lens(
| get = { ${ele.sourceName}: ${ele.sourceClassName} -> ${ele.sourceName}.${focus.paramName.plusIfNotBlank(prefix = "`", postfix = "`")} },
| set = { ${ele.sourceName}: ${ele.sourceClassName}, value: ${focus.className} -> ${ele.sourceName}.copy(${focus.paramName.plusIfNotBlank(prefix = "`", postfix = "`")} = value) }
|inline val ${adt.sourceClassName}.Companion.${focus.lensParamName()}: $Lens<${adt.sourceClassName}, ${focus.className}> inline get()= $Lens(
| get = { ${adt.sourceName}: ${adt.sourceClassName} -> ${adt.sourceName}.${
focus.paramName.plusIfNotBlank(
prefix = "`",
postfix = "`"
)
} },
| set = { ${adt.sourceName}: ${adt.sourceClassName}, value: ${focus.className} -> ${adt.sourceName}.copy(${
focus.paramName.plusIfNotBlank(
prefix = "`",
postfix = "`"
)
} = value) }
|)
|""".trimMargin()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ internal fun generateOptionals(ele: ADT, target: OptionalTarget) =
private fun processElement(ele: ADT, foci: List<Focus>): String =
foci.joinToString(separator = "\n") { focus ->
fun getOrModifyF(toNullable: String = "") =
"{ ${ele.sourceName}: ${ele.sourceClassName} -> ${ele.sourceName}.${focus.paramName.plusIfNotBlank(prefix = "`", postfix = "`")}$toNullable?.right() ?: ${ele.sourceName}.left() }"
"{ ${ele.sourceName}: ${ele.sourceClassName} -> ${ele.sourceName}.${
focus.paramName.plusIfNotBlank(
prefix = "`",
postfix = "`"
)
}$toNullable?.right() ?: ${ele.sourceName}.left() }"
fun setF(fromNullable: String = "") =
"${ele.sourceName}.copy(${focus.paramName.plusIfNotBlank(prefix = "`", postfix = "`")} = value$fromNullable)"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package arrow.optics.plugin.internals
internal fun generatePrisms(ele: ADT, target: PrismTarget) =
Snippet(
`package` = ele.packageName,
name = ele.simpleName,
name = ele.sourceClassName,
imports =
setOf("import arrow.core.left", "import arrow.core.right", "import arrow.core.identity"),
content = processElement(ele, target.foci)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import arrow.optics.plugin.isData
import arrow.optics.plugin.isSealed
import com.google.devtools.ksp.processing.KSPLogger
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSDeclaration
import com.google.devtools.ksp.symbol.KSType
import com.google.devtools.ksp.symbol.KSTypeArgument
import java.util.Locale
Expand All @@ -15,10 +16,10 @@ internal fun adt(c: KSClassDeclaration, logger: KSPLogger): ADT =
c.targets().map { target ->
when (target) {
OpticsTarget.LENS ->
evalAnnotatedDataClass(c, c.simpleName.asString().lensErrorMessage, logger)
evalAnnotatedDataClass(c, c.qualifiedNameOrSimpleName.lensErrorMessage, logger)
.let(::LensTarget)
OpticsTarget.OPTIONAL ->
evalAnnotatedDataClass(c, c.simpleName.asString().optionalErrorMessage, logger)
evalAnnotatedDataClass(c, c.qualifiedNameOrSimpleName.optionalErrorMessage, logger)
.let(::OptionalTarget)
OpticsTarget.ISO -> evalAnnotatedIsoElement(c, logger).let(::IsoTarget)
OpticsTarget.PRISM -> evalAnnotatedPrismElement(c, logger).let(::PrismTarget)
Expand All @@ -44,11 +45,14 @@ internal fun evalAnnotatedPrismElement(
)
}
else -> {
logger.error(element.simpleName.asString().prismErrorMessage, element)
logger.error(element.qualifiedNameOrSimpleName.prismErrorMessage, element)
emptyList()
}
}

internal val KSDeclaration.qualifiedNameOrSimpleName: String
get() = (qualifiedName ?: simpleName).asString()

internal fun KSClassDeclaration.sealedSubclassFqNameList(): List<String> =
getSealedSubclasses().mapNotNull { it.qualifiedName?.asString() }.toList()

Expand Down Expand Up @@ -88,11 +92,11 @@ internal fun evalAnnotatedIsoElement(element: KSClassDeclaration, logger: KSPLog
.zip(element.getConstructorParamNames(), Focus.Companion::invoke)
.takeIf { it.size <= 22 }
?: run {
logger.error(element.simpleName.asString().isoTooBigErrorMessage, element)
logger.error(element.qualifiedNameOrSimpleName.isoTooBigErrorMessage, element)
emptyList()
}
else -> {
logger.error(element.simpleName.asString().isoErrorMessage, element)
logger.error(element.qualifiedNameOrSimpleName.isoErrorMessage, element)
emptyList()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,13 @@ class LensTests {
fun `Lenses which mentions imported elements`() {
"""
|$imports
|import kotlin.time.Duration
|
|@optics
|data class OpticsTest(val time: Duration) {
|data class OpticsTest(val time: kotlin.time.Duration) {
| companion object
|}
|
|val i: Lens<OpticsTest, Duration> = OpticsTest.time
|val i: Lens<OpticsTest, kotlin.time.Duration> = OpticsTest.time
|val r = i != null
""".evals("r" to true)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const val imports =
import arrow.optics.*
import arrow.optics.dsl.*
import arrow.optics.typeclasses.*
import kotlin.time.Duration.Companion.hours
"""

const val dslModel =
Expand All @@ -19,7 +20,7 @@ const val dslModel =
@optics data class Company(val name: String, val address: Address) {
companion object
}
@optics data class Employee(val name: String, val company: Company?) {
@optics data class Employee(val name: String, val company: Company?, val weeklyWorkingHours: kotlin.time.Duration = 5.hours) {
companion object
}
@optics data class Employees(val employees: List<Employee>) {
Expand Down

0 comments on commit ba979cf

Please sign in to comment.