diff --git a/gradle.properties b/gradle.properties index ab4e418e2..45211062e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,7 +16,7 @@ logbackVersion=1.2.3 http4kVersion=4.4.0.1 artifactsPath=build/artifacts -baseVersion=0.9.1 +baseVersion=0.10.0 projectRepoUrl=https://github.com/Kotlin/kotlin-jupyter docsRepo=git@github.com:ileasile/kotlin-jupyter-docs.git diff --git a/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/CodePreprocessor.kt b/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/CodePreprocessor.kt new file mode 100644 index 000000000..0034de2e4 --- /dev/null +++ b/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/CodePreprocessor.kt @@ -0,0 +1,20 @@ +package org.jetbrains.kotlinx.jupyter.api + +import org.jetbrains.kotlinx.jupyter.api.libraries.LibraryDefinitionProducer + +/** + * Preprocesses the cell code before its execution + */ +interface CodePreprocessor { + /** + * Returns `true` if this preprocessor accepts the given [code] + */ + fun accepts(code: String): Boolean = true + + /** + * Performs code preprocessing + */ + fun process(code: String, host: KotlinKernelHost): Result + + data class Result(val code: Code, val libraries: List = emptyList()) +} diff --git a/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/JupyterIntegration.kt b/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/JupyterIntegration.kt index f8f886394..adee7bbde 100644 --- a/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/JupyterIntegration.kt +++ b/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/JupyterIntegration.kt @@ -3,7 +3,9 @@ package org.jetbrains.kotlinx.jupyter.api.libraries import org.jetbrains.kotlinx.jupyter.api.AfterCellExecutionCallback import org.jetbrains.kotlinx.jupyter.api.ClassAnnotationHandler import org.jetbrains.kotlinx.jupyter.api.ClassDeclarationsCallback +import org.jetbrains.kotlinx.jupyter.api.Code import org.jetbrains.kotlinx.jupyter.api.CodeCell +import org.jetbrains.kotlinx.jupyter.api.CodePreprocessor import org.jetbrains.kotlinx.jupyter.api.ExecutionCallback import org.jetbrains.kotlinx.jupyter.api.FieldHandler import org.jetbrains.kotlinx.jupyter.api.FieldHandlerByClass @@ -54,6 +56,8 @@ abstract class JupyterIntegration : LibraryDefinitionProducer { private val repositories = mutableListOf() + private val codePreprocessors = mutableListOf() + fun addRenderer(handler: RendererTypeHandler) { renderers.add(handler) } @@ -70,6 +74,10 @@ abstract class JupyterIntegration : LibraryDefinitionProducer { fileAnnotations.add(handler) } + fun addCodePreprocessor(preprocessor: CodePreprocessor) { + codePreprocessors.add(preprocessor) + } + inline fun render(noinline renderer: CodeCell.(T) -> Any) { return renderWithHost { _, value: T -> renderer(this, value) } } @@ -152,21 +160,34 @@ abstract class JupyterIntegration : LibraryDefinitionProducer { addFileAnnotationHanlder(FileAnnotationHandler(T::class, callback)) } + fun preprocessCodeWithLibraries(callback: KotlinKernelHost.(Code) -> CodePreprocessor.Result) { + addCodePreprocessor(object : CodePreprocessor { + override fun process(code: String, host: KotlinKernelHost): CodePreprocessor.Result { + return host.callback(code) + } + }) + } + + fun preprocessCode(callback: KotlinKernelHost.(Code) -> Code) { + preprocessCodeWithLibraries { CodePreprocessor.Result(this.callback(it)) } + } + internal fun getDefinition() = - LibraryDefinitionImpl( - init = init, - renderers = renderers, - converters = converters, - imports = imports, - dependencies = dependencies, - repositories = repositories, - initCell = beforeCellExecution, - afterCellExecution = afterCellExecution, - shutdown = shutdownCallbacks, - classAnnotations = classAnnotations, - fileAnnotations = fileAnnotations, - resources = resources, - ) + libraryDefinition { + it.init = init + it.renderers = renderers + it.converters = converters + it.imports = imports + it.dependencies = dependencies + it.repositories = repositories + it.initCell = beforeCellExecution + it.afterCellExecution = afterCellExecution + it.shutdown = shutdownCallbacks + it.classAnnotations = classAnnotations + it.fileAnnotations = fileAnnotations + it.resources = resources + it.codePreprocessors = codePreprocessors + } } override fun getDefinitions(notebook: Notebook): List { diff --git a/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/LibraryDefinition.kt b/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/LibraryDefinition.kt index 6bccb6ff6..11e47f468 100644 --- a/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/LibraryDefinition.kt +++ b/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/LibraryDefinition.kt @@ -2,6 +2,7 @@ package org.jetbrains.kotlinx.jupyter.api.libraries import org.jetbrains.kotlinx.jupyter.api.AfterCellExecutionCallback import org.jetbrains.kotlinx.jupyter.api.ClassAnnotationHandler +import org.jetbrains.kotlinx.jupyter.api.CodePreprocessor import org.jetbrains.kotlinx.jupyter.api.ExecutionCallback import org.jetbrains.kotlinx.jupyter.api.FieldHandler import org.jetbrains.kotlinx.jupyter.api.FileAnnotationHandler @@ -85,6 +86,12 @@ interface LibraryDefinition { val resources: List get() = emptyList() + /** + * List of code preprocessors + */ + val codePreprocessors: List + get() = emptyList() + /** * Minimal kernel version that is supported by this library */ diff --git a/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/LibraryDefinitionImpl.kt b/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/LibraryDefinitionImpl.kt index 97b08b887..5ab847ce4 100644 --- a/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/LibraryDefinitionImpl.kt +++ b/jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/LibraryDefinitionImpl.kt @@ -2,6 +2,7 @@ package org.jetbrains.kotlinx.jupyter.api.libraries import org.jetbrains.kotlinx.jupyter.api.AfterCellExecutionCallback import org.jetbrains.kotlinx.jupyter.api.ClassAnnotationHandler +import org.jetbrains.kotlinx.jupyter.api.CodePreprocessor import org.jetbrains.kotlinx.jupyter.api.ExecutionCallback import org.jetbrains.kotlinx.jupyter.api.FieldHandler import org.jetbrains.kotlinx.jupyter.api.FileAnnotationHandler @@ -9,23 +10,37 @@ import org.jetbrains.kotlinx.jupyter.api.KotlinKernelVersion import org.jetbrains.kotlinx.jupyter.api.RendererTypeHandler /** - * Trivial implementation of [LibraryDefinition]. - * You may use it in simple cases instead of overriding [LibraryDefinition] - * to avoid additional anonymous classes creation + * Trivial implementation of [LibraryDefinition] - simple container. */ -class LibraryDefinitionImpl( - override val dependencies: List = emptyList(), - override val repositories: List = emptyList(), - override val imports: List = emptyList(), - override val init: List> = emptyList(), - override val initCell: List> = emptyList(), - override val afterCellExecution: List = emptyList(), - override val shutdown: List> = emptyList(), - override val renderers: List = emptyList(), - override val converters: List = emptyList(), - override val classAnnotations: List = emptyList(), - override val fileAnnotations: List = emptyList(), - override val resources: List = emptyList(), - override val minKernelVersion: KotlinKernelVersion? = null, - override val originalDescriptorText: String? = null, -) : LibraryDefinition +class LibraryDefinitionImpl private constructor() : LibraryDefinition { + override var dependencies: List = emptyList() + override var repositories: List = emptyList() + override var imports: List = emptyList() + override var init: List> = emptyList() + override var initCell: List> = emptyList() + override var afterCellExecution: List = emptyList() + override var shutdown: List> = emptyList() + override var renderers: List = emptyList() + override var converters: List = emptyList() + override var classAnnotations: List = emptyList() + override var fileAnnotations: List = emptyList() + override var resources: List = emptyList() + override var codePreprocessors: List = emptyList() + override var minKernelVersion: KotlinKernelVersion? = null + override var originalDescriptorText: String? = null + + companion object { + internal fun build(buildAction: (LibraryDefinitionImpl) -> Unit): LibraryDefinition { + return LibraryDefinitionImpl().also(buildAction) + } + } +} + +/** + * Builds an instance of [LibraryDefinition]. + * Build action receives [LibraryDefinitionImpl] as an explicit argument + * because of problems with names clashing that may arise. + */ +fun libraryDefinition(buildAction: (LibraryDefinitionImpl) -> Unit): LibraryDefinition { + return LibraryDefinitionImpl.build(buildAction) +} diff --git a/jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/libraries/LibraryDescriptor.kt b/jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/libraries/LibraryDescriptor.kt index 5a7ea018e..d04ab3950 100644 --- a/jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/libraries/LibraryDescriptor.kt +++ b/jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/libraries/LibraryDescriptor.kt @@ -8,8 +8,8 @@ import org.jetbrains.kotlinx.jupyter.api.ExactRendererTypeHandler import org.jetbrains.kotlinx.jupyter.api.KotlinKernelVersion import org.jetbrains.kotlinx.jupyter.api.libraries.CodeExecution import org.jetbrains.kotlinx.jupyter.api.libraries.LibraryDefinition -import org.jetbrains.kotlinx.jupyter.api.libraries.LibraryDefinitionImpl import org.jetbrains.kotlinx.jupyter.api.libraries.LibraryResource +import org.jetbrains.kotlinx.jupyter.api.libraries.libraryDefinition import org.jetbrains.kotlinx.jupyter.config.currentKernelVersion import org.jetbrains.kotlinx.jupyter.exceptions.ReplPreprocessingException import org.jetbrains.kotlinx.jupyter.util.KotlinKernelVersionSerializer @@ -78,18 +78,18 @@ class LibraryDescriptor( } private fun processDescriptor(mapping: Map): LibraryDefinition { - return LibraryDefinitionImpl( - dependencies = dependencies.replaceVariables(mapping), - repositories = repositories.replaceVariables(mapping), - imports = imports.replaceVariables(mapping), - init = init.replaceVariables(mapping), - shutdown = shutdown.replaceVariables(mapping), - initCell = initCell.replaceVariables(mapping), - renderers = renderers.replaceVariables(mapping), - resources = resources.replaceVariables(mapping), - minKernelVersion = minKernelVersion, - originalDescriptorText = Json.encodeToString(this), - ) + return libraryDefinition { + it.dependencies = dependencies.replaceVariables(mapping) + it.repositories = repositories.replaceVariables(mapping) + it.imports = imports.replaceVariables(mapping) + it.init = init.replaceVariables(mapping) + it.shutdown = shutdown.replaceVariables(mapping) + it.initCell = initCell.replaceVariables(mapping) + it.renderers = renderers.replaceVariables(mapping) + it.resources = resources.replaceVariables(mapping) + it.minKernelVersion = minKernelVersion + it.originalDescriptorText = Json.encodeToString(this) + } } companion object { diff --git a/jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/magics/CompoundCodePreprocessor.kt b/jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/magics/CompoundCodePreprocessor.kt new file mode 100644 index 000000000..15dc6351c --- /dev/null +++ b/jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/magics/CompoundCodePreprocessor.kt @@ -0,0 +1,31 @@ +package org.jetbrains.kotlinx.jupyter.magics + +import org.jetbrains.kotlinx.jupyter.api.CodePreprocessor +import org.jetbrains.kotlinx.jupyter.api.KotlinKernelHost + +/** + * Containing [preprocessors]' [process] are run in reversed order: last added processors + * are run first + */ +class CompoundCodePreprocessor( + private val preprocessors: MutableList +) : CodePreprocessor { + constructor(vararg preprocessors: CodePreprocessor) : this(preprocessors.toMutableList()) + + override fun process(code: String, host: KotlinKernelHost): CodePreprocessor.Result { + return preprocessors.foldRight(CodePreprocessor.Result(code, emptyList())) { preprocessor, result -> + if (preprocessor.accepts(result.code)) { + val newResult = preprocessor.process(result.code, host) + CodePreprocessor.Result(newResult.code, result.libraries + newResult.libraries) + } else result + } + } + + fun add(preprocessor: CodePreprocessor) { + preprocessors.add(preprocessor) + } + + fun addAll(preprocessors: Iterable) { + this.preprocessors.addAll(preprocessors) + } +} diff --git a/jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/magics/MagicsProcessor.kt b/jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/magics/MagicsProcessor.kt index 847ef5d1c..b98ca4502 100644 --- a/jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/magics/MagicsProcessor.kt +++ b/jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/magics/MagicsProcessor.kt @@ -1,7 +1,7 @@ package org.jetbrains.kotlinx.jupyter.magics -import org.jetbrains.kotlinx.jupyter.api.Code -import org.jetbrains.kotlinx.jupyter.api.libraries.LibraryDefinitionProducer +import org.jetbrains.kotlinx.jupyter.api.CodePreprocessor +import org.jetbrains.kotlinx.jupyter.api.KotlinKernelHost import org.jetbrains.kotlinx.jupyter.common.ReplLineMagic import org.jetbrains.kotlinx.jupyter.compiler.util.CodeInterval import org.jetbrains.kotlinx.jupyter.exceptions.ReplPreprocessingException @@ -10,8 +10,8 @@ import kotlin.script.experimental.jvm.util.determineSep class MagicsProcessor( private val handler: MagicsHandler, private val parseOutCellMarker: Boolean = false, -) { - fun processMagics(code: String, parseOnly: Boolean = false, tryIgnoreErrors: Boolean = false): MagicProcessingResult { +) : CodePreprocessor { + fun processMagics(code: String, parseOnly: Boolean = false, tryIgnoreErrors: Boolean = false): CodePreprocessor.Result { val magics = magicsIntervals(code) for (magicRange in magics) { @@ -38,7 +38,7 @@ class MagicsProcessor( val codes = codeIntervals(code, magics, true) val preprocessedCode = codes.joinToString("") { code.substring(it.from, it.to) } - return MagicProcessingResult(preprocessedCode, handler.getLibraries()) + return CodePreprocessor.Result(preprocessedCode, handler.getLibraries()) } fun codeIntervals( @@ -79,7 +79,9 @@ class MagicsProcessor( } } - data class MagicProcessingResult(val code: Code, val libraries: List) + override fun process(code: String, host: KotlinKernelHost): CodePreprocessor.Result { + return processMagics(code) + } companion object { private const val MAGICS_SIGN = '%' diff --git a/src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl.kt b/src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl.kt index 055cf0703..91849ea11 100644 --- a/src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl.kt +++ b/src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl.kt @@ -7,6 +7,7 @@ import jupyter.kotlin.KotlinKernelHostProvider import jupyter.kotlin.Repository import org.jetbrains.kotlin.config.KotlinCompilerVersion import org.jetbrains.kotlinx.jupyter.api.Code +import org.jetbrains.kotlinx.jupyter.api.CodePreprocessor import org.jetbrains.kotlinx.jupyter.api.ExecutionCallback import org.jetbrains.kotlinx.jupyter.api.KotlinKernelHost import org.jetbrains.kotlinx.jupyter.api.KotlinKernelVersion @@ -40,6 +41,7 @@ import org.jetbrains.kotlinx.jupyter.libraries.LibrariesScanner import org.jetbrains.kotlinx.jupyter.libraries.LibraryResourcesProcessorImpl import org.jetbrains.kotlinx.jupyter.libraries.ResolutionInfoProvider import org.jetbrains.kotlinx.jupyter.libraries.ResolutionInfoSwitcher +import org.jetbrains.kotlinx.jupyter.magics.CompoundCodePreprocessor import org.jetbrains.kotlinx.jupyter.magics.FullMagicsHandler import org.jetbrains.kotlinx.jupyter.magics.MagicsProcessor import org.jetbrains.kotlinx.jupyter.repl.CellExecutor @@ -231,6 +233,8 @@ class ReplForJupyterImpl( ) ) + private val codePreprocessor = CompoundCodePreprocessor(magics) + private val importsCollector: ScriptImportsCollector = ScriptImportsCollectorImpl() // Used for various purposes, i.e. completion and listing errors @@ -328,7 +332,7 @@ class ReplForJupyterImpl( fileAnnotationsProcessor, fieldsProcessor, typeRenderersProcessor, - magics, + codePreprocessor, resourcesProcessor, librariesScanner, notebook, diff --git a/src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl/impl/CellExecutorImpl.kt b/src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl/impl/CellExecutorImpl.kt index 170f2228f..e84a0b309 100644 --- a/src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl/impl/CellExecutorImpl.kt +++ b/src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl/impl/CellExecutorImpl.kt @@ -45,7 +45,7 @@ internal class CellExecutorImpl(private val replContext: SharedReplContext) : Ce log.debug("Executing code:\n$code") val preprocessedCode = if (processMagics) { - val processedMagics = magicsProcessor.processMagics(code) + val processedMagics = codePreprocessor.process(code, context) log.debug("Adding ${processedMagics.libraries.size} libraries") processedMagics.libraries.getDefinitions(notebook).forEach { @@ -128,6 +128,7 @@ internal class CellExecutorImpl(private val replContext: SharedReplContext) : Ce library.classAnnotations.forEach(sharedContext.classAnnotationsProcessor::register) library.fileAnnotations.forEach(sharedContext.fileAnnotationsProcessor::register) sharedContext.afterCellExecution.addAll(library.afterCellExecution) + sharedContext.codePreprocessor.addAll(library.codePreprocessors) val classLoader = sharedContext.evaluator.lastClassLoader rethrowAsLibraryException(LibraryProblemPart.RESOURCES) { diff --git a/src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl/impl/SharedReplContext.kt b/src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl/impl/SharedReplContext.kt index e82d8f18f..ad02a21bc 100644 --- a/src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl/impl/SharedReplContext.kt +++ b/src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl/impl/SharedReplContext.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlinx.jupyter.codegen.FileAnnotationsProcessor import org.jetbrains.kotlinx.jupyter.codegen.ResultsTypeRenderersProcessor import org.jetbrains.kotlinx.jupyter.libraries.LibrariesScanner import org.jetbrains.kotlinx.jupyter.libraries.LibraryResourcesProcessor -import org.jetbrains.kotlinx.jupyter.magics.MagicsProcessor +import org.jetbrains.kotlinx.jupyter.magics.CompoundCodePreprocessor import org.jetbrains.kotlinx.jupyter.repl.InternalEvaluator internal data class SharedReplContext( @@ -17,7 +17,7 @@ internal data class SharedReplContext( val fileAnnotationsProcessor: FileAnnotationsProcessor, val fieldsProcessor: FieldsProcessor, val typeRenderersProcessor: ResultsTypeRenderersProcessor, - val magicsProcessor: MagicsProcessor, + val codePreprocessor: CompoundCodePreprocessor, val resourcesProcessor: LibraryResourcesProcessor, val librariesScanner: LibrariesScanner, val notebook: Notebook, diff --git a/src/test/kotlin/org/jetbrains/kotlinx/jupyter/test/embeddingTest.kt b/src/test/kotlin/org/jetbrains/kotlinx/jupyter/test/embeddingTest.kt index 2420b928d..9cae348f2 100644 --- a/src/test/kotlin/org/jetbrains/kotlinx/jupyter/test/embeddingTest.kt +++ b/src/test/kotlin/org/jetbrains/kotlinx/jupyter/test/embeddingTest.kt @@ -3,12 +3,12 @@ package org.jetbrains.kotlinx.jupyter.test import org.jetbrains.kotlinx.jupyter.api.MimeTypedResult import org.jetbrains.kotlinx.jupyter.api.ResultHandlerCodeExecution import org.jetbrains.kotlinx.jupyter.api.SubtypeRendererTypeHandler -import org.jetbrains.kotlinx.jupyter.api.libraries.LibraryDefinitionImpl import org.jetbrains.kotlinx.jupyter.api.libraries.LibraryResource import org.jetbrains.kotlinx.jupyter.api.libraries.ResourceFallbacksBundle import org.jetbrains.kotlinx.jupyter.api.libraries.ResourceLocation import org.jetbrains.kotlinx.jupyter.api.libraries.ResourcePathType import org.jetbrains.kotlinx.jupyter.api.libraries.ResourceType +import org.jetbrains.kotlinx.jupyter.api.libraries.libraryDefinition import org.jetbrains.kotlinx.jupyter.execute import org.jetbrains.kotlinx.jupyter.test.repl.AbstractSingleReplTest import org.junit.jupiter.api.Test @@ -45,8 +45,8 @@ class TestFunList(private val head: T, private val tail: TestFunList?) { * Used for [EmbedReplTest.testSubtypeRenderer] */ @Suppress("unused") -val testLibraryDefinition1 = LibraryDefinitionImpl( - renderers = listOf( +val testLibraryDefinition1 = libraryDefinition { + it.renderers = listOf( SubtypeRendererTypeHandler( TestSum::class, ResultHandlerCodeExecution("\$it.a + \$it.b") @@ -56,14 +56,14 @@ val testLibraryDefinition1 = LibraryDefinitionImpl( ResultHandlerCodeExecution("\$it.render()") ) ) -) +} /** * Used for [EmbedReplTest.testJsResources] */ @Suppress("unused") -val testLibraryDefinition2 = LibraryDefinitionImpl( - resources = listOf( +val testLibraryDefinition2 = libraryDefinition { + it.resources = listOf( LibraryResource( listOf( ResourceFallbacksBundle( @@ -83,7 +83,7 @@ val testLibraryDefinition2 = LibraryDefinitionImpl( "testLib2" ) ) -) +} class EmbedReplTest : AbstractSingleReplTest() { override val repl = makeEmbeddedRepl() diff --git a/src/test/kotlin/org/jetbrains/kotlinx/jupyter/test/repl/IntegrationApiTests.kt b/src/test/kotlin/org/jetbrains/kotlinx/jupyter/test/repl/IntegrationApiTests.kt index 658c4ec3c..bfdd92cd1 100644 --- a/src/test/kotlin/org/jetbrains/kotlinx/jupyter/test/repl/IntegrationApiTests.kt +++ b/src/test/kotlin/org/jetbrains/kotlinx/jupyter/test/repl/IntegrationApiTests.kt @@ -116,7 +116,7 @@ class IntegrationApiTests { val repl = makeRepl() repl.eval( """ - @file:DependsOn("src/test/testData/notebook-api-test-0.0.15.jar") + @file:DependsOn("src/test/testData/kotlin-jupyter-api-test-0.0.16.jar") """.trimIndent() ) @@ -166,4 +166,19 @@ class IntegrationApiTests { val result = repl.eval("B(A())") assertEquals("iB: iA", result.resultValue) } + + @Test + fun `code preprocessing`() { + val repl = makeRepl() + repl.eval( + """ + USE { + preprocessCode { it.replace('b', 'x') } + } + """.trimIndent() + ) + + val result = repl.eval("\"abab\"") + assertEquals("axax", result.resultValue) + } } diff --git a/src/test/testData/kotlin-jupyter-api-test-0.0.16.jar b/src/test/testData/kotlin-jupyter-api-test-0.0.16.jar new file mode 100644 index 000000000..b16902e88 Binary files /dev/null and b/src/test/testData/kotlin-jupyter-api-test-0.0.16.jar differ diff --git a/src/test/testData/notebook-api-test-0.0.15.jar b/src/test/testData/notebook-api-test-0.0.15.jar deleted file mode 100644 index 09032ac9d..000000000 Binary files a/src/test/testData/notebook-api-test-0.0.15.jar and /dev/null differ