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

org.jetbrains.kotlinx.jupyter.repl.KotlinCompleter.kt Maven / Gradle / Ivy

Go to download

Implementation of REPL compiler and preprocessor for Jupyter dialect of Kotlin (IDE-compatible)

There is a newer version: 0.12.0-290
Show newest version
package org.jetbrains.kotlinx.jupyter.repl

import kotlinx.coroutines.runBlocking
import org.jetbrains.kotlinx.jupyter.compiler.util.CodeInterval
import org.jetbrains.kotlinx.jupyter.compiler.util.SourceCodeImpl
import org.jetbrains.kotlinx.jupyter.util.toSourceCodePositionWithNewAbsolute
import kotlin.script.experimental.api.ReplCompleter
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.SourceCodeCompletionVariant
import kotlin.script.experimental.api.valueOrNull

class KotlinCompleter {
    fun complete(
        compiler: ReplCompleter,
        configuration: ScriptCompilationConfiguration,
        code: String,
        preprocessedCode: String,
        id: Int,
        cursor: Int,
    ): CompletionResult {
        return try {
            val codeLine = SourceCodeImpl(id, code)
            val preprocessedCodeLine = SourceCodeImpl(id, preprocessedCode)
            val codePos = cursor.toSourceCodePositionWithNewAbsolute(codeLine, preprocessedCodeLine)
            val completionResult =
                codePos?.let { runBlocking { compiler.complete(preprocessedCodeLine, codePos, configuration) } }

            completionResult?.valueOrNull()?.toList()?.let { completionList ->
                getResult(code, cursor, completionList)
            } ?: CompletionResult.Empty(code, cursor)
        } catch (e: Exception) {
            CompletionResult.Error(e.javaClass.simpleName, e.message ?: "", e.stackTrace.map { it.toString() })
        }
    }

    companion object {
        fun getResult(
            code: String,
            cursor: Int,
            completions: List,
        ): CompletionResult.Success {
            val bounds = getTokenBounds(code, cursor)
            return CompletionResult.Success(completions.map { it.text }, bounds, completions, code, cursor)
        }

        private fun getTokenBounds(buf: String, cursor: Int): CodeInterval {
            require(cursor <= buf.length) { "Position $cursor does not exist in code snippet <$buf>" }

            val startSubstring = buf.substring(0, cursor)

            val filter = { c: Char -> !c.isLetterOrDigit() && c != '_' }

            val start = startSubstring.indexOfLast(filter) + 1

            return CodeInterval(start, cursor)
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy