All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kgp_1.9.0..2.0.0__Main.co.touchlab.skie.compilerinject.interceptor.SimpleNamedPhaseInterceptorConfigurer.kt Maven / Gradle / Ivy

The newest version!
package co.touchlab.skie.compilerinject.interceptor

import co.touchlab.skie.compilerinject.reflection.Reflector
import org.jetbrains.kotlin.backend.common.LoggingContext
import org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase
import org.jetbrains.kotlin.backend.konan.ConfigChecks
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CompilerConfigurationKey
import kotlin.reflect.jvm.jvmName

class SimpleNamedPhaseInterceptorConfigurer :
    PhaseInterceptorConfigurer, Context, Input, Output>
    where Context : LoggingContext, Context : ConfigChecks {

    override fun canConfigurePhase(phase: Any): Boolean = phase is SimpleNamedCompilerPhase<*, *, *>

    override fun configure(
        configuration: CompilerConfiguration,
        phase: SimpleNamedCompilerPhase,
        interceptors: List>,
    ) {
        val namedPhase = phase.reflector
        val chain = ErasedPhaseInterceptorChain(interceptors)
        synchronized(phase) {
            val currentPhaseBody = namedPhase.op
            val (originalPhaseBody, interceptorKey) = if (currentPhaseBody.isIntercepted()) {
                val interceptedPhaseBody = InterceptedPhaseBodyReflector(currentPhaseBody)
                interceptedPhaseBody.originalPhaseBody to interceptedPhaseBody.interceptorKey
            } else {
                currentPhaseBody to CompilerConfigurationKey.create("phaseInterceptor for phase $phase")
            }

            configuration.put(interceptorKey, chain)

            val interceptedPhaseBody = InterceptedPhaseBody(
                originalPhaseBody,
                interceptorKey,
            )
            namedPhase.op = interceptedPhaseBody
        }
    }

    private val SimpleNamedCompilerPhase.reflector: SimpleNamedCompilerPhaseReflector
        get() = SimpleNamedCompilerPhaseReflector(this)
}

private class InterceptedPhaseBody(
    val originalPhaseBody: OriginalPhaseBody,
    val interceptorKey: CompilerConfigurationKey>,
) : (Context, Input) -> Output where Context : LoggingContext, Context : ConfigChecks {

    override fun invoke(context: Context, input: Input): Output {
        val interceptor = context.config.configuration.get(interceptorKey)
        return if (interceptor != null) {
            interceptor.invoke(context, input, originalPhaseBody)
        } else {
            originalPhaseBody.invoke(context, input)
        }
    }
}

private class SimpleNamedCompilerPhaseReflector(
    override val instance: SimpleNamedCompilerPhase,
) : Reflector(instance::class) where Context : LoggingContext, Context : ConfigChecks {

    var op: (Context, Input) -> Output by declaredField("\$op")
}

private class InterceptedPhaseBodyReflector(
    override val instance: (Context, Input) -> Output,
) : Reflector(instance::class) where Context : LoggingContext, Context : ConfigChecks {

    val originalPhaseBody: (Context, Input) -> Output by declaredField()
    val interceptorKey: CompilerConfigurationKey> by declaredField()
}

private fun  ((Context, Input) -> Output).isIntercepted(): Boolean where Context : LoggingContext, Context : ConfigChecks {
    return javaClass.name == InterceptedPhaseBody::class.jvmName
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy