Coverage Summary for Class: IrTryCatchHelperKt (com.kotlinorm.compiler.helpers)

Class Class, % Method, % Branch, % Line, % Instruction, %
IrTryCatchHelperKt 0% (0/1) 0% (0/2) 0% (0/2) 0% (0/14)


 /**
  * Copyright 2022-2025 kronos-orm
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package com.kotlinorm.compiler.helpers
 
 import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
 import org.jetbrains.kotlin.backend.common.lower.irCatch
 import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
 import org.jetbrains.kotlin.ir.builders.declarations.buildVariable
 import org.jetbrains.kotlin.ir.builders.irBlock
 import org.jetbrains.kotlin.ir.builders.irGet
 import org.jetbrains.kotlin.ir.builders.irTry
 import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
 import org.jetbrains.kotlin.ir.declarations.IrVariable
 import org.jetbrains.kotlin.ir.expressions.IrCatch
 import org.jetbrains.kotlin.ir.expressions.IrExpression
 import org.jetbrains.kotlin.ir.expressions.IrTry
 import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI
 import org.jetbrains.kotlin.ir.types.IrType
 import org.jetbrains.kotlin.ir.types.defaultType
 import org.jetbrains.kotlin.ir.util.getSimpleFunction
 import org.jetbrains.kotlin.name.Name
 import kotlin.contracts.ExperimentalContracts
 import kotlin.contracts.InvocationKind
 import kotlin.contracts.contract
 
 /**
  * Provides utilities to build `try-catch-finally` blocks in Kotlin IR.
  */
 
 /**
  * Gets the symbol for the `java.lang.Exception` class.
  *
  * @return The symbol for the `java.lang.Exception` class.
  */
 context(_: IrPluginContext)
 val JavaLangExceptionSymbol
     get() = referenceClass("java.lang.Exception")!!
 
 /**
  * Gets the symbol for the `printStackTrace` function of the `java.lang.Throwable` class.
  *
  * @return The symbol for the `printStackTrace` function.
  */
 @UnsafeDuringIrConstructionAPI
 context(_: IrPluginContext)
 val printStackTraceSymbol
     get() = referenceClass("java.lang.Throwable")!!.getSimpleFunction("printStackTrace")!!
 
 /**
  * A builder class for constructing `IrTry` expressions with multiple `catch` blocks and an optional `finally` block.
  *
  * @property result The main expression to be executed within the `try` block.
  * @property type The type of the `try` expression, defaulting to the type of the `result`.
  */
 class IrTryBuilder(
     val result: IrExpression,
     val type: IrType = result.type
 ) {
     private val catches = mutableListOf<IrCatch>()
     private val caughtTypes = mutableSetOf<IrType>()
     private var finallyExpression: IrExpression? = null
         set(value) {
             if (field != null) error("Finally block already set")
             field = value
         }
 
 
     /**
      * Adds a `catch` block to the `try` expression for the specified throwable type.
      *
      * @param throwableType The type of exception to catch. Defaults to `java.lang.Exception`.
      * @param body A lambda that defines the body of the `catch` block, receiving the caught exception variable.
      * @throws IllegalArgumentException if the `throwableType` does not inherit from `kotlin.Throwable`
      */
     @ExperimentalContracts
     @UnsafeDuringIrConstructionAPI
     context(builder: IrBuilderWithScope, context: IrPluginContext)
     private fun irCatch(
         throwableType: IrType = JavaLangExceptionSymbol.defaultType,
         body: IrBuilderWithScope.(IrVariable) -> IrExpression = { printStackTraceSymbol(irGet(it)) }
     ) {
         contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) }
         if (throwableType.sub() == builder.context.irBuiltIns.throwableType && throwableType != builder.context.irBuiltIns.throwableType) error(
             "Can only catch types that inherit from kotlin.Throwable"
         )
 
         if (!caughtTypes.add(throwableType)) error("Already caught type $throwableType")
 
         val catchVariable = buildVariable(
             builder.scope.getLocalDeclarationParent(),
             builder.startOffset,
             builder.endOffset,
             IrDeclarationOrigin.CATCH_PARAMETER,
             Name.identifier("e_${catches.size}"),
             throwableType
         )
 
         catches += builder.irCatch(catchVariable, builder.body(catchVariable))
     }
 
     /**
      * Adds a `catch` block to the `try` expression that catches all exceptions.
      * The body of the `catch` block is defined by the provided lambda.
      *
      * @param expression A lambda that defines the body of the `catch` block.
      * @return The current `IrTryBuilder` instance for chaining.
      */
     @ExperimentalContracts
     @UnsafeDuringIrConstructionAPI
     context(builder: IrBuilderWithScope, _: IrPluginContext)
     fun catch(expression: IrTryBuilder.() -> Unit = {}): IrTryBuilder {
         irCatch(builder.context.irBuiltIns.throwableType) {
             builder.irBlock {
                 expression()
             }
         }
         return this
     }
 
     /**
      * Sets the `finally` block for the `try` expression.
      *
      * @param expression The expression to be executed in the `finally` block.
      * @return The current `IrTryBuilder` instance for chaining.
      * @throws IllegalStateException if a `finally` block has already been set.
      */
     @ExperimentalContracts
     @UnsafeDuringIrConstructionAPI
     fun finally(expression: IrExpression): IrTryBuilder {
         finallyExpression = expression
         return this
     }
 
     /**
      * Builds the `IrTry` expression using the configured `try`, `catch`, and `finally` blocks.
      *
      * @return The constructed `IrTry` expression.
      */
     context(builder: IrBuilderWithScope, _: IrPluginContext)
     fun build(): IrTry =
         builder.irTry(type, result, catches, finallyExpression)
 
     companion object {
         /**
          * Creates a new `IrTryBuilder` instance with the specified result expression and type.
          *
          * @param result The main expression to be executed within the `try` block. Defaults to an empty block.
          * @param type The type of the `try` expression, defaulting to the type of the `result`.
          * @return A new `IrTryBuilder` instance.
          */
         context(builder: IrBuilderWithScope, _: IrPluginContext)
         fun irTry(
             result: IrExpression = builder.irBlock {},
             type: IrType = result.type,
         ): IrTryBuilder = IrTryBuilder(result, type)
     }
 }