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

io.realm.kotlin.compiler.IrUtils.kt Maven / Gradle / Ivy

Go to download

Compiler plugin for JVM based platforms for Realm Kotlin. This artifact is not supposed to be consumed directly, but through 'io.realm.kotlin:gradle-plugin:1.0.1' instead.

There is a newer version: 3.0.0
Show newest version
/*
 * Copyright 2020 Realm Inc.
 *
 * 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 io.realm.kotlin.compiler

import io.realm.kotlin.compiler.FqNames.BASE_REALM_OBJECT_INTERFACE
import io.realm.kotlin.compiler.FqNames.EMBEDDED_OBJECT_INTERFACE
import io.realm.kotlin.compiler.FqNames.KOTLIN_COLLECTIONS_LISTOF
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.ir.classIfConstructor
import org.jetbrains.kotlin.backend.common.ir.copyAnnotationsFrom
import org.jetbrains.kotlin.backend.common.ir.remapTypeParameters
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocationWithRange
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
import org.jetbrains.kotlin.com.intellij.psi.PsiElement
import org.jetbrains.kotlin.com.intellij.psi.PsiElementVisitor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.IrBlockBodyBuilder
import org.jetbrains.kotlin.ir.builders.IrBlockBuilder
import org.jetbrains.kotlin.ir.builders.at
import org.jetbrains.kotlin.ir.builders.declarations.IrFieldBuilder
import org.jetbrains.kotlin.ir.builders.declarations.IrFunctionBuilder
import org.jetbrains.kotlin.ir.builders.declarations.IrPropertyBuilder
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.builders.declarations.addGetter
import org.jetbrains.kotlin.ir.builders.declarations.addProperty
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.irBlockBody
import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irGetField
import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrMutableAnnotationContainer
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrElseBranchImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrWhenImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeArgument
import org.jetbrains.kotlin.ir.types.classFqName
import org.jetbrains.kotlin.ir.types.impl.IrTypeBase
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.companionObject
import org.jetbrains.kotlin.ir.util.file
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.getPropertyGetter
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.isVararg
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.properties
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.SUPER_TYPE_LIST
import java.lang.reflect.Field
import java.util.function.Predicate

// Somehow addSetter was removed from the IrProperty in https://github.com/JetBrains/kotlin/commit/d1dc938a5d7331ba43fcbb8ce53c3e17ef76a22a#diff-2726c3747ace0a1c93ad82365cf3ff18L114
// Remove this extension when this will be re-introduced? see https://kotlinlang.slack.com/archives/C7L3JB43G/p1600888883006300
inline fun IrProperty.addSetter(builder: IrFunctionBuilder.() -> Unit = {}): IrSimpleFunction =
    IrFunctionBuilder().run {
        factory.buildFun {
            this.name = Name.special("")
            builder()
        }.also { setter ->
            [email protected] = setter
            setter.correspondingPropertySymbol = [email protected]
            setter.parent = [email protected]
        }
    }

fun IrPluginContext.blockBody(
    symbol: IrSymbol,
    block: IrBlockBodyBuilder.() -> Unit
): IrBlockBody =
    DeclarationIrBuilder(this, symbol).irBlockBody { block() }

val ClassDescriptor.isRealmObjectCompanion
    get() = isCompanionObject && (containingDeclaration as ClassDescriptor).isBaseRealmObject

val realmObjectInterfaceFqNames = setOf(FqNames.REALM_OBJECT_INTERFACE)
val realmEmbeddedObjectInterfaceFqNames = setOf(FqNames.EMBEDDED_OBJECT_INTERFACE)
val anyRealmObjectInterfacesFqNames = realmObjectInterfaceFqNames + realmEmbeddedObjectInterfaceFqNames

inline fun ClassDescriptor.hasInterfacePsi(interfaces: Set): Boolean {
    // Using PSI to find super types to avoid cyclic reference (see https://github.com/realm/realm-kotlin/issues/339)
    var hasRealmObjectAsSuperType = false
    this.findPsi()?.acceptChildren(object : PsiElementVisitor() {
        override fun visitElement(element: PsiElement) {
            if (element.node.elementType == SUPER_TYPE_LIST) {
                // Check supertypes for classes with Embbeded/RealmObject as generics and remove
                // them from the string so as to avoid erroneously processing said classes which
                // implement these types as implementing Embedded/RealmObject. Doing so would
                // add our companion interface causing compilation errors.
                val elementNodeText = element.node.text
                    .replace(" ", "") // Sanitize removing spaces
                    .split(",") // Split by commas
                    .filter {
                        !(
                            it.contains("") ||
                                it.contains("") ||
                                it.contains("") ||
                                it.contains("")
                            )
                    }.joinToString(",") // Re-sanitize again
                hasRealmObjectAsSuperType = elementNodeText.findAnyOf(interfaces) != null
            }
        }
    })

    return hasRealmObjectAsSuperType
}

val realmObjectPsiNames = setOf("RealmObject", "io.realm.kotlin.types.RealmObject")
val embeddedRealmObjectPsiNames = setOf("EmbeddedRealmObject", "io.realm.kotlin.types.EmbeddedRealmObject")
val ClassDescriptor.isRealmObject: Boolean
    get() = this.hasInterfacePsi(realmObjectPsiNames)
val ClassDescriptor.isEmbeddedRealmObject: Boolean
    get() = this.hasInterfacePsi(embeddedRealmObjectPsiNames)
val ClassDescriptor.isBaseRealmObject: Boolean
    get() = this.hasInterfacePsi(realmObjectPsiNames + embeddedRealmObjectPsiNames)

fun IrMutableAnnotationContainer.hasAnnotation(annotation: FqName): Boolean {
    return annotations.hasAnnotation(annotation)
}

val IrClass.isBaseRealmObject
    get() = superTypes.any { it.classFqName in anyRealmObjectInterfacesFqNames }

val IrClass.isRealmObject
    get() = superTypes.any { it.classFqName == BASE_REALM_OBJECT_INTERFACE }

val IrClass.isEmbeddedRealmObject: Boolean
    get() = superTypes.any { it.classFqName == EMBEDDED_OBJECT_INTERFACE }

internal fun IrFunctionBuilder.at(startOffset: Int, endOffset: Int) = also {
    this.startOffset = startOffset
    this.endOffset = endOffset
}

internal fun IrFieldBuilder.at(startOffset: Int, endOffset: Int) = also {
    this.startOffset = startOffset
    this.endOffset = endOffset
}

internal fun IrPropertyBuilder.at(startOffset: Int, endOffset: Int) = also {
    this.startOffset = startOffset
    this.endOffset = endOffset
}

internal fun IrClass.lookupFunction(name: Name, predicate: Predicate? = null): IrSimpleFunction {
    return functions.firstOrNull { it.name == name && predicate?.test(it) ?: true }
        ?: throw AssertionError("Function '$name' not found in class '${this.name}'")
}

internal fun IrClass.lookupProperty(name: Name): IrProperty {
    return properties.firstOrNull { it.name == name }
        ?: throw AssertionError("Property '$name' not found in class '${this.name}'")
}

internal fun IrPluginContext.lookupFunctionInClass(
    fqName: FqName,
    function: String
): IrSimpleFunction {
    return lookupClassOrThrow(fqName).functions.first {
        it.name == Name.identifier(function)
    }
}

internal fun IrPluginContext.lookupClassOrThrow(name: FqName): IrClass {
    return referenceClass(name)?.owner
        ?: fatalError("Cannot find ${name.asString()} on platform $platform.")
}

internal fun IrPluginContext.lookupConstructorInClass(
    fqName: FqName,
    filter: (ctor: IrConstructorSymbol) -> Boolean = { true }
): IrConstructorSymbol {
    return referenceConstructors(fqName).first {
        filter(it)
    }
}

internal fun  IrClass.lookupCompanionDeclaration(
    name: Name
): T {
    return this.companionObject()?.declarations?.first { it.nameForIrSerialization == name } as T
        ?: fatalError("Cannot find companion method ${name.asString()} on ${this.name}")
}

object SchemaCollector {
    val properties = mutableMapOf>()
}

// ------------------------------------------------------------------------------

/**
 * This matches RealmEnums.CollectionType.
 */
enum class CollectionType(val description: String) {
    NONE("None"),
    LIST("RealmList"),
    SET("RealmSet"),
    DICTIONARY("RealmDictionary");
}

/**
 * This matches RealmEnums.PropertyType.
 */
enum class PropertyType {
    RLM_PROPERTY_TYPE_INT,
    RLM_PROPERTY_TYPE_BOOL,
    RLM_PROPERTY_TYPE_STRING,
    RLM_PROPERTY_TYPE_BINARY,
    RLM_PROPERTY_TYPE_OBJECT,
    RLM_PROPERTY_TYPE_FLOAT,
    RLM_PROPERTY_TYPE_DOUBLE,
    RLM_PROPERTY_TYPE_TIMESTAMP,
    RLM_PROPERTY_TYPE_OBJECT_ID,
    RLM_PROPERTY_TYPE_UUID,
}

data class CoreType(
    val propertyType: PropertyType,
    val nullable: Boolean
)

// FIXME use PropertyType instead of "type: String", consider using a common/shared type when implementing public schema
//  see (https://github.com/realm/realm-kotlin/issues/238)
data class SchemaProperty(
    val propertyType: PropertyType,
    val declaration: IrProperty,
    val collectionType: CollectionType = CollectionType.NONE,
    val coreGenericTypes: List? = null
)

// ------------------------------------------------------------------------------

@Suppress("LongParameterList")
internal fun  buildOf(
    context: IrPluginContext,
    startOffset: Int,
    endOffset: Int,
    function: IrSimpleFunctionSymbol,
    containerType: IrClass,
    elementType: IrType,
    args: List
): IrExpression {
    return IrCallImpl(
        startOffset = startOffset, endOffset = endOffset,
        type = containerType.typeWith(elementType),
        symbol = function,
        typeArgumentsCount = 1,
        valueArgumentsCount = 1,
        origin = null,
        superQualifierSymbol = null
    ).apply {
        putTypeArgument(index = 0, type = elementType)
        putValueArgument(
            index = 0,
            valueArgument = IrVarargImpl(
                UNDEFINED_OFFSET,
                UNDEFINED_OFFSET,
                context.irBuiltIns.arrayClass.typeWith(elementType),
                type,
                args.toList()
            )
        )
    }
}

/**
 * Work-around for this method moving package names between Kotlin 1.7.10 and 1.7.20.
 *
 * It moved from `org.jetbrains.kotlin.backend.common.ir.copyTo` to
 * `org.jetbrains.kotlin.ir.util.copyTo`. In order to support users having both versions we
 * move the implementation to the Realm project and rewire all our access to this method.
 *
 * Source: https://github.com/JetBrains/kotlin/blob/d9c5f100dbb626fbfb2d89ee12d170fef49514bb/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt#L744
 */
@Suppress("LongParameterList")
internal fun IrValueParameter.copyTo(
    irFunction: IrFunction,
    origin: IrDeclarationOrigin = this.origin,
    index: Int = this.index,
    startOffset: Int = this.startOffset,
    endOffset: Int = this.endOffset,
    name: Name = this.name,
    remapTypeMap: Map = mapOf(),
    type: IrType = this.type.remapTypeParameters(
        (parent as IrTypeParametersContainer).classIfConstructor,
        irFunction.classIfConstructor,
        remapTypeMap
    ),
    varargElementType: IrType? = this.varargElementType,
    defaultValue: IrExpressionBody? = this.defaultValue,
    isCrossinline: Boolean = this.isCrossinline,
    isNoinline: Boolean = this.isNoinline,
    isAssignable: Boolean = this.isAssignable
): IrValueParameter {
    val symbol = IrValueParameterSymbolImpl()
    val defaultValueCopy = defaultValue?.let { originalDefault ->
        factory.createExpressionBody(originalDefault.startOffset, originalDefault.endOffset) {
            expression = originalDefault.expression.deepCopyWithVariables().also {
                it.patchDeclarationParents(irFunction)
            }
        }
    }
    return factory.createValueParameter(
        startOffset, endOffset, origin, symbol,
        name, index, type, varargElementType, isCrossinline = isCrossinline,
        isNoinline = isNoinline, isHidden = false, isAssignable = isAssignable
    ).also {
        it.parent = irFunction
        it.defaultValue = defaultValueCopy
        it.copyAnnotationsFrom(this)
    }
}

internal fun  buildSetOf(
    context: IrPluginContext,
    startOffset: Int,
    endOffset: Int,
    elementType: IrType,
    args: List
): IrExpression {
    val setOf = context.referenceFunctions(FqName("kotlin.collections.setOf"))
        .first {
            val parameters = it.owner.valueParameters
            parameters.size == 1 && parameters.first().isVararg
        }
    val setIrClass: IrClass = context.lookupClassOrThrow(FqNames.KOTLIN_COLLECTIONS_SET)
    return buildOf(context, startOffset, endOffset, setOf, setIrClass, elementType, args)
}

internal fun  buildListOf(
    context: IrPluginContext,
    startOffset: Int,
    endOffset: Int,
    elementType: IrType,
    args: List
): IrExpression {
    val listOf = context.referenceFunctions(KOTLIN_COLLECTIONS_LISTOF)
        .first {
            val parameters = it.owner.valueParameters
            parameters.size == 1 && parameters.first().isVararg
        }
    val listIrClass: IrClass = context.lookupClassOrThrow(FqNames.KOTLIN_COLLECTIONS_LIST)
    return buildOf(context, startOffset, endOffset, listOf, listIrClass, elementType, args)
}

fun IrClass.addValueProperty(
    pluginContext: IrPluginContext,
    superClass: IrClass,
    propertyName: Name,
    propertyType: IrType,
    initExpression: (startOffset: Int, endOffset: Int) -> IrExpression
): IrProperty {
    // PROPERTY name:realmPointer visibility:public modality:OPEN [var]
    val property = addProperty {
        at([email protected], [email protected])
        name = propertyName
        visibility = DescriptorVisibilities.PUBLIC
        modality = Modality.FINAL
        isVar = true
    }
    // FIELD PROPERTY_BACKING_FIELD name:objectPointer type:kotlin.Long? visibility:private
    property.backingField = pluginContext.irFactory.buildField {
        at([email protected], [email protected])
        origin = IrDeclarationOrigin.PROPERTY_BACKING_FIELD
        name = property.name
        visibility = DescriptorVisibilities.PRIVATE
        modality = property.modality
        type = propertyType
    }.apply {
        initializer = IrExpressionBodyImpl(initExpression(startOffset, endOffset))
    }
    property.backingField?.parent = this
    property.backingField?.correspondingPropertySymbol = property.symbol

    val getter = property.addGetter {
        at([email protected], [email protected])
        visibility = DescriptorVisibilities.PUBLIC
        modality = Modality.FINAL
        returnType = propertyType
        origin = IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
    }
    // $this: VALUE_PARAMETER name: type:dev.nhachicha.Foo.$RealmHandler
    getter.dispatchReceiverParameter = thisReceiver!!.copyTo(getter)
    // overridden:
    //   public abstract fun  (): kotlin.Long? declared in dev.nhachicha.RealmObjectInternal
    val propertyAccessorGetter = superClass.getPropertyGetter(propertyName.asString())
        ?: fatalError("${propertyName.asString()} function getter symbol is not available")
    getter.overriddenSymbols = listOf(propertyAccessorGetter)

    // BLOCK_BODY
    // RETURN type=kotlin.Nothing from='public final fun  (): kotlin.Long? declared in dev.nhachicha.Foo.$RealmHandler'
    // GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:objectPointer type:kotlin.Long? visibility:private' type=kotlin.Long? origin=null
    // receiver: GET_VAR ': dev.nhachicha.Foo.$RealmHandler declared in dev.nhachicha.Foo.$RealmHandler.' type=dev.nhachicha.Foo.$RealmHandler origin=null
    getter.body = pluginContext.blockBody(getter.symbol) {
        at(startOffset, endOffset)
        +irReturn(
            irGetField(irGet(getter.dispatchReceiverParameter!!), property.backingField!!)
        )
    }
    return property
}

internal fun IrClass.addFakeOverrides(
    receiver: IrClassSymbol,
    functions: Set,
) {
    val overrides = receiver.owner.declarations.filterIsInstance()
        .filter { it.name in functions }
    for (override in overrides) {
        addFunction {
            updateFrom(override)
            name = override.name
            returnType = override.returnType
            origin = IrDeclarationOrigin.FAKE_OVERRIDE
            isFakeOverride = true
        }.apply {
            override.valueParameters.forEach { x ->
                addValueParameter(x.name, x.type)
            }
            this.overriddenSymbols = listOf(override.symbol)
            dispatchReceiverParameter =
                receiver.owner.thisReceiver!!.copyTo(this)
        }
    }
}

// Copy of Kotlin's Fir2IrComponents.createSafeCallConstruction
fun IrBlockBuilder.createSafeCallConstruction(
    receiverVariable: IrVariable,
    receiverVariableSymbol: IrValueSymbol,
    expressionOnNotNull: IrExpression,
): IrExpression {
    val startOffset = expressionOnNotNull.startOffset
    val endOffset = expressionOnNotNull.endOffset

    val resultType = expressionOnNotNull.type.makeNullable()
    return IrBlockImpl(startOffset, endOffset, resultType, IrStatementOrigin.SAFE_CALL).apply {
        statements += receiverVariable
        statements += IrWhenImpl(startOffset, endOffset, resultType).apply {
            val condition = IrCallImpl(
                startOffset, endOffset, context.irBuiltIns.booleanType,
                context.irBuiltIns.eqeqSymbol,
                valueArgumentsCount = 2,
                typeArgumentsCount = 0,
                origin = IrStatementOrigin.EQEQ
            ).apply {
                putValueArgument(0, IrGetValueImpl(startOffset, endOffset, receiverVariableSymbol))
                putValueArgument(
                    1,
                    IrConstImpl.constNull(startOffset, endOffset, context.irBuiltIns.nothingNType)
                )
            }
            branches += IrBranchImpl(
                condition,
                IrConstImpl.constNull(startOffset, endOffset, context.irBuiltIns.nothingNType)
            )
            branches += IrElseBranchImpl(
                IrConstImpl.boolean(startOffset, endOffset, context.irBuiltIns.booleanType, true),
                expressionOnNotNull
            )
        }
    }
}

/**
 * Using reflection to invoke the `arguments` attribute of the `IrSimpleType` to determine the enclosing type
 * of the `RealmList`.
 * This work around is needed since `IrSimpleType` became an abstract class in Kotlin 1.7 (see https://github.com/JetBrains/kotlin/commit/53210770a6877c5c08735070f8eff3e33573f0f5)
 * which causes the compiler to throw: "java.lang.IncompatibleClassChangeError: Found class org.jetbrains.kotlin.ir.types.IrSimpleType, but interface was expected"
 * when the compiler plugin is compiled with Kotlin 1.6.10.
 */
// FIXME remove when upgrading to Kotlin 1.7 (revert to usage of `(backingField.type as IrSimpleType).arguments[0] as IrSimpleType` instead)
fun getCollectionElementType(backingFieldType: IrType): IrType? {
    if (backingFieldType is IrSimpleType) {
        val args: Field = backingFieldType::class.java.getDeclaredField("arguments")
        args.isAccessible = true
        @Suppress("UNCHECKED_CAST")
        val values: List = args.get(backingFieldType) as List
        if (values.isNotEmpty()) {
            return (values[0] as IrTypeBase).type
        }
    }
    return null
}

/** Finds the line and column of [IrDeclaration] */
fun IrDeclaration.locationOf(): CompilerMessageSourceLocation {
    val sourceRangeInfo = file.fileEntry.getSourceRangeInfo(
        beginOffset = startOffset,
        endOffset = endOffset
    )
    return CompilerMessageLocationWithRange.create(
        path = sourceRangeInfo.filePath,
        lineStart = sourceRangeInfo.startLineNumber + 1,
        columnStart = sourceRangeInfo.startColumnNumber + 1,
        lineEnd = sourceRangeInfo.endLineNumber + 1,
        columnEnd = sourceRangeInfo.endColumnNumber + 1,
        lineContent = null
    )!!
}

/**
 * Method to indicate fatal issues that should not have happeneded; as opposed to user modeling
 * errors that are reported as compiler errors.
 */
fun fatalError(message: String): Nothing {
    error(message)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy