Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions arrow-libs/optics/arrow-optics-compiler-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,44 @@ dependencies {
testRuntimeOnly(projects.arrowOptics)
}

// Compilers the tests also run on, each with its own test task in `check`. The default `test` task runs on the
// compiler kotlin-compile-testing depends on. The tests and plugin are compiled once; each compiler only changes
// the runtime classpath, so these runs check binary compatibility.
val testCompilers = listOf("2.5.0-Beta2")

testCompilers.forEach { version ->
val suffix = "Kotlin" + version.replace(Regex("[^A-Za-z0-9]"), "_")
val testRuntimeClasspath = configurations.testRuntimeClasspath.get()
val runtimeClasspath = configurations.create("test${suffix}RuntimeClasspath") {
isCanBeConsumed = false
extendsFrom(testRuntimeClasspath)
// replicate testRuntimeClasspath's attributes for the same variant resolution
@Suppress("UnstableApiUsage")
attributes.addAllLater(testRuntimeClasspath.attributes)
resolutionStrategy.eachDependency {
if (requested.group == "org.jetbrains.kotlin" && requested.name.startsWith("kotlin-")) useVersion(version)
}
}
val testTask = tasks.register<Test>("test$suffix") {
description = "Runs the tests on Kotlin $version."
group = LifecycleBasePlugin.VERIFICATION_GROUP
testClassesDirs = sourceSets.test.get().output.classesDirs
classpath = sourceSets.test.get().output + sourceSets.main.get().output + runtimeClasspath
// Kotlin 2.5+ needs JDK 17 to run the compiler.
javaLauncher.set(javaToolchains.launcherFor { languageVersion.set(JavaLanguageVersion.of(17)) })
}
tasks.check { dependsOn(testTask) }
}

// Kotlin 2.5 reflects over its own classes' fields and fails on the field coverage instrumentation adds.
kover {
currentProject {
instrumentation {
excludedClasses.add("org.jetbrains.kotlin.*")
}
}
}

tasks.withType<Test>().configureEach {
maxParallelForks = 1
useJUnitPlatform()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.ConeClassifierLookupTag
import org.jetbrains.kotlin.fir.types.ConeDefinitelyNotNullType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType
import org.jetbrains.kotlin.fir.types.ConeStarProjection
import org.jetbrains.kotlin.fir.types.ConeTypeParameterType
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
Expand Down Expand Up @@ -242,7 +244,9 @@ object FirOpticsExtractor {
*/
private fun sealedLensFoci(symbol: FirRegularClassSymbol, session: FirSession, resolveFocusTypes: Boolean): List<FirFocus> {
val abstractProps = mutableListOf<FirPropertySymbol>()
symbol.processAllDeclarations(session) visitor@{
// Members are only needed at RAW_FIR here. The default (STATUS) breaks in the IDE when resolving lazily.
// Only names and syntactic modifiers are read early; return types and visibility are resolved on demand only when computing focus types.
symbol.processAllDeclarations(session, memberRequiredPhase = FirResolvePhase.RAW_FIR) visitor@{
if (it !is FirPropertySymbol) return@visitor
if (!it.isAbstractMemberOf(symbol)) return@visitor
if (it.receiverParameterSymbol != null) return@visitor
Expand Down Expand Up @@ -350,7 +354,15 @@ object FirOpticsExtractor {

private fun ConeKotlinType.mentions(param: FirTypeParameterSymbol, session: FirSession): Boolean = contains { (it as? ConeTypeParameterType)?.toTypeParameterSymbol(session) == param }

fun ConeTypeParameterType.toTypeParameterSymbol(session: FirSession): FirTypeParameterSymbol? = lookupTag.toSymbol(session) as? FirTypeParameterSymbol
fun ConeTypeParameterType.toTypeParameterSymbol(session: FirSession): FirTypeParameterSymbol? = stableLookupTag.toSymbol(session) as? FirTypeParameterSymbol

/**
* The lookup tag, read through the supertype: `ConeTypeParameterType.lookupTag` returns a class that moved
* package in Kotlin 2.5, so calling it directly links on only one of 2.4 and 2.5; the supertype's getter
* (`ConeLookupTagBasedType.lookupTag`) has the same signature in both.
*/
@Suppress("USELESS_CAST")
private val ConeTypeParameterType.stableLookupTag: ConeClassifierLookupTag get() = (this as ConeLookupTagBasedType).lookupTag

/**
* Whether [this] property is abstract. Interface members without a body are implicitly abstract, but
Expand Down Expand Up @@ -381,7 +393,7 @@ object FirOpticsExtractor {
private fun sameType(a: ConeKotlinType, b: ConeKotlinType): Boolean {
if (a.isMarkedNullable != b.isMarkedNullable) return false
if (a is ConeTypeParameterType || b is ConeTypeParameterType) {
return a is ConeTypeParameterType && b is ConeTypeParameterType && a.lookupTag == b.lookupTag
return a is ConeTypeParameterType && b is ConeTypeParameterType && a.stableLookupTag == b.stableLookupTag
}
if (a is ConeDefinitelyNotNullType || b is ConeDefinitelyNotNullType) {
return a is ConeDefinitelyNotNullType && b is ConeDefinitelyNotNullType && sameType(a.original, b.original)
Expand Down
Loading