Skip to content

Commit

Permalink
Get rid of kotlinx-coroutines usage in scripting libs and plugins
Browse files Browse the repository at this point in the history
the dependency on the coroutines library caused various problems like
KT-30778, or stdlib/runtime version conflicts.
The only function used was `runBlocking`, so this change replaces it
with the internal implementation based on the similar internal thing
from the stdlib.
#KT-30778 fixed
  • Loading branch information
ligee authored and TeamCityServer committed Jul 19, 2021
1 parent 9b1de90 commit 0cd29ad
Show file tree
Hide file tree
Showing 20 changed files with 89 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ dependencies {
compile(project(":kotlin-scripting-jvm"))
compile(project(":kotlin-scripting-dependencies"))
compile(project(":kotlin-scripting-dependencies-maven"))
compile(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core"))
}

sourceSets {
Expand Down
1 change: 0 additions & 1 deletion libraries/scripting/common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ project.updateJvmTarget("1.6")

dependencies {
compile(kotlinStdlib())
compile(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core"))
compileOnly(project(":kotlin-reflect-api"))
testCompile(commonDep("junit"))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@

package kotlin.script.experimental.host

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.runBlocking
import kotlin.script.experimental.api.*
import kotlin.script.experimental.impl.internalScriptingRunSuspend

/**
* The base class for scripting host implementations
Expand All @@ -32,7 +31,9 @@ abstract class BasicScriptingHost(
/**
* The overridable wrapper for executing evaluation in a desired coroutines context
*/
open fun <T> runInCoroutineContext(block: suspend CoroutineScope.() -> T): T = runBlocking { block() }
open fun <T> runInCoroutineContext(block: suspend () -> T): T =
@Suppress("DEPRECATION_ERROR")
internalScriptingRunSuspend { block() }

/**
* The default implementation of the evaluation function
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/

package kotlin.script.experimental.impl

import kotlin.coroutines.Continuation
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.startCoroutine

// Copied with modifications form kotlin.coroutines.jvm.internal.runSuspend/RunSuspend
// to use as an equivalent of runBlocking without dependency on the kotlinx.coroutines

@Deprecated("For internal use only, use kotlinx.coroutines instead", level = DeprecationLevel.ERROR)
fun <T> internalScriptingRunSuspend(block: suspend () -> T) : T {
val run = InternalScriptingRunSuspend<T>()
block.startCoroutine(run)
return run.await()
}

private class InternalScriptingRunSuspend<T> : Continuation<T> {
override val context: CoroutineContext
get() = EmptyCoroutineContext

@Suppress("RESULT_CLASS_IN_RETURN_TYPE")
var result: Result<T>? = null

override fun resumeWith(result: Result<T>) = synchronized(this) {
this.result = result
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") (this as Object).notifyAll()
}

fun await(): T = synchronized(this) {
while (true) {
when (val result: Result<T>? = this.result) {
null -> @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") (this as Object).wait()
else -> break
}
}
return result!!.getOrThrow()
}
}

1 change: 1 addition & 0 deletions libraries/scripting/dependencies-maven/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ dependencies {
testImplementation(commonDep("junit"))
testRuntimeOnly("org.slf4j:slf4j-nop:1.7.30")
testImplementation(kotlin("reflect"))
testImplementation(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core"))
}

sourceSets {
Expand Down
2 changes: 1 addition & 1 deletion libraries/scripting/dependencies/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ project.updateJvmTarget("1.6")
dependencies {
compile(kotlinStdlib())
compile(project(":kotlin-scripting-common"))
testCompile(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core"))
testCompile(commonDep("junit"))
testImplementation(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core"))
}

sourceSets {
Expand Down
1 change: 1 addition & 0 deletions libraries/scripting/jvm-host-test/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dependencies {
testCompile(projectTests(":compiler:tests-common"))
testCompile(project(":kotlin-scripting-compiler"))
testCompile(project(":daemon-common")) // TODO: fix import (workaround for jps build)
testImplementation(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core"))

testRuntimeOnly(project(":kotlin-compiler"))
testRuntimeOnly(project(":kotlin-reflect"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

package kotlin.script.experimental.jvmhost.repl

import kotlinx.coroutines.runBlocking
import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.KJvmReplCompilerBase
Expand All @@ -15,6 +14,7 @@ import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzerBase
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.write
import kotlin.script.experimental.api.*
import kotlin.script.experimental.impl.internalScriptingRunSuspend
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.experimental.host.withDefaultsFrom
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
Expand Down Expand Up @@ -56,7 +56,8 @@ class JvmReplCompiler(
}()
}

when (val res = runBlocking { replCompiler.compile(listOf(snippet), scriptCompilationConfiguration) }) {
@Suppress("DEPRECATION_ERROR")
when (val res = internalScriptingRunSuspend { replCompiler.compile(listOf(snippet), scriptCompilationConfiguration) }) {
is ResultWithDiagnostics.Success -> {
val lineId = LineId(codeLine.no, 0, snippet.hashCode())
replCompilerState.apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@

package kotlin.script.experimental.jvmhost.repl

import kotlinx.coroutines.runBlocking
import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.cli.common.repl.ReplEvaluator
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.write
import kotlin.reflect.KClass
import kotlin.script.experimental.api.*
import kotlin.script.experimental.impl.internalScriptingRunSuspend
import kotlin.script.experimental.jvm.BasicJvmScriptEvaluator
import kotlin.script.experimental.jvm.baseClassLoader
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
Expand Down Expand Up @@ -60,7 +60,8 @@ class JvmReplEvaluator(
}
}

val res = runBlocking { scriptEvaluator(compiledScript, currentConfiguration) }
@Suppress("DEPRECATION_ERROR")
val res = internalScriptingRunSuspend { scriptEvaluator(compiledScript, currentConfiguration) }

when (res) {
is ResultWithDiagnostics.Success -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

package kotlin.script.experimental.jvm.impl

import kotlinx.coroutines.runBlocking
import java.io.File
import kotlin.script.dependencies.Environment
import kotlin.script.dependencies.ScriptContents
Expand All @@ -16,6 +15,7 @@ import kotlin.script.experimental.dependencies.ScriptDependencies
import kotlin.script.experimental.dependencies.ScriptReport
import kotlin.script.experimental.host.FileScriptSource
import kotlin.script.experimental.host.toScriptSource
import kotlin.script.experimental.impl.internalScriptingRunSuspend
import kotlin.script.experimental.jvm.JvmDependency
import kotlin.script.experimental.jvm.compat.mapToLegacyScriptReportPosition
import kotlin.script.experimental.jvm.compat.mapToLegacyScriptReportSeverity
Expand All @@ -27,7 +27,8 @@ class BridgeDependenciesResolver(
) : AsyncDependenciesResolver {

override fun resolve(scriptContents: ScriptContents, environment: Environment): DependenciesResolver.ResolveResult =
runBlocking {
@Suppress("DEPRECATION_ERROR")
internalScriptingRunSuspend {
resolveAsync(scriptContents, environment)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@

package kotlin.script.experimental.jvm

import kotlin.coroutines.Continuation
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.startCoroutine
import kotlin.script.experimental.api.*
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.baseClass
import kotlin.script.experimental.api.hostConfiguration
import kotlin.script.experimental.api.onFailure
import kotlin.script.experimental.host.createEvaluationConfigurationFromTemplate
import kotlin.script.experimental.host.withDefaultsFrom
import kotlin.script.experimental.impl.internalScriptingRunSuspend
import kotlin.script.experimental.jvm.impl.createScriptFromClassLoader

@Suppress("unused") // script codegen generates a call to it
Expand All @@ -29,42 +29,11 @@ fun runCompiledScript(scriptClass: Class<*>, vararg args: String) {
mainArguments(args)
}
}
runScriptSuspend {
@Suppress("DEPRECATION_ERROR")
internalScriptingRunSuspend {
evaluator(script, evaluationConfiguration).onFailure {
it.reports.forEach(System.err::println)
}
}
}

// Copied form kotlin.coroutines.jvm.internal.runSuspend/RunSuspend to create a runner without dependency on the kotlinx.coroutines
private fun runScriptSuspend(block: suspend () -> Unit) {
val run = RunScriptSuspend()
block.startCoroutine(run)
run.await()
}

private class RunScriptSuspend : Continuation<Unit> {
override val context: CoroutineContext
get() = EmptyCoroutineContext

@Suppress("RESULT_CLASS_IN_RETURN_TYPE")
var result: Result<Unit>? = null

override fun resumeWith(result: Result<Unit>) = synchronized(this) {
this.result = result
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") (this as Object).notifyAll()
}

fun await() = synchronized(this) {
while (true) {
when (val result = this.result) {
null -> @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") (this as Object).wait()
else -> {
result.getOrThrow() // throw up failure
return
}
}
}
}
}

3 changes: 1 addition & 2 deletions libraries/tools/kotlin-main-kts/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ dependencies {
embedded(project(":kotlin-scripting-jvm-host-unshaded")) { isTransitive = false }
embedded(project(":kotlin-scripting-dependencies")) { isTransitive = false }
embedded("org.apache.ivy:ivy:2.5.0")
embedded(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) { isTransitive = false }
embedded(commonDep("org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm")) {
embedded(commonDep("org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm")) {
isTransitive = false
attributes {
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

package org.jetbrains.kotlin.mainKts

import kotlinx.coroutines.runBlocking
import org.jetbrains.kotlin.mainKts.impl.Directories
import org.jetbrains.kotlin.mainKts.impl.IvyResolver
import java.io.File
Expand All @@ -19,6 +18,7 @@ import kotlin.script.experimental.dependencies.*
import kotlin.script.experimental.host.FileBasedScriptSource
import kotlin.script.experimental.host.FileScriptSource
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.experimental.impl.internalScriptingRunSuspend
import kotlin.script.experimental.jvm.*
import kotlin.script.experimental.jvm.compat.mapLegacyDiagnosticSeverity
import kotlin.script.experimental.jvm.compat.mapLegacyScriptPosition
Expand Down Expand Up @@ -135,7 +135,8 @@ class MainKtsConfigurator : RefineScriptCompilationConfigurationHandler {
}

val resolveResult = try {
runBlocking {
@Suppress("DEPRECATION_ERROR")
internalScriptingRunSuspend {
resolver.resolveFromScriptSourceAnnotations(annotations.filter { it.annotation is DependsOn || it.annotation is Repository })
}
} catch (e: Throwable) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package org.jetbrains.kotlin.script.util

import com.intellij.openapi.util.Disposer
import kotlinx.coroutines.runBlocking
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot
import org.jetbrains.kotlin.cli.common.messages.*
Expand Down Expand Up @@ -55,6 +54,7 @@ import kotlin.reflect.KClass
import kotlin.script.experimental.api.onSuccess
import kotlin.script.experimental.api.valueOr
import kotlin.script.experimental.host.toScriptSource
import kotlin.script.experimental.impl.internalScriptingRunSuspend
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContext

Expand Down Expand Up @@ -199,7 +199,8 @@ done
val script = File(scriptPath).toScriptSource()
val newScriptDefinition = ScriptDefinitionProvider.getInstance(environment.project)!!.findDefinition(script)!!
val compiledScript = scriptCompiler.compile(script, newScriptDefinition.compilationConfiguration).onSuccess {
runBlocking {
@Suppress("DEPRECATION_ERROR")
internalScriptingRunSuspend {
it.getClass(newScriptDefinition.evaluationConfiguration)
}
}.valueOr {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ dependencies {
runtimeOnly(project(":kotlin-scripting-common"))
runtimeOnly(project(":kotlin-scripting-jvm"))
runtimeOnly(kotlinStdlib())
runtimeOnly(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core"))
}

publish()
Expand Down
1 change: 0 additions & 1 deletion plugins/scripting/scripting-compiler-impl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ dependencies {
compile(project(":kotlin-scripting-jvm"))
compile(kotlinStdlib())
compileOnly(project(":kotlin-reflect-api"))
compile(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core"))
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
compileOnly(intellijDep()) { includeJars("asm-all", rootProject = rootProject) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

package org.jetbrains.kotlin.scripting.resolve

import kotlinx.coroutines.runBlocking
import kotlin.script.dependencies.Environment
import kotlin.script.dependencies.ScriptContents
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
import kotlin.script.experimental.dependencies.DependenciesResolver
import kotlin.script.experimental.impl.internalScriptingRunSuspend

// wraps AsyncDependenciesResolver to provide implementation for synchronous DependenciesResolver::resolve
class AsyncDependencyResolverWrapper(
Expand All @@ -18,8 +18,9 @@ class AsyncDependencyResolverWrapper(

override fun resolve(
scriptContents: ScriptContents, environment: Environment
): DependenciesResolver.ResolveResult
= runBlocking { delegate.resolveAsync(scriptContents, environment) }
): DependenciesResolver.ResolveResult =
@Suppress("DEPRECATION_ERROR")
internalScriptingRunSuspend { delegate.resolveAsync(scriptContents, environment) }


suspend override fun resolveAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
import com.intellij.testFramework.LightVirtualFile
import kotlinx.coroutines.runBlocking
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtFile
Expand All @@ -34,6 +33,7 @@ import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
import kotlin.script.experimental.dependencies.DependenciesResolver
import kotlin.script.experimental.dependencies.ScriptDependencies
import kotlin.script.experimental.host.*
import kotlin.script.experimental.impl.internalScriptingRunSuspend
import kotlin.script.experimental.jvm.*
import kotlin.script.experimental.jvm.compat.mapToDiagnostics
import kotlin.script.experimental.jvm.impl.toClassPathOrEmpty
Expand Down Expand Up @@ -255,7 +255,8 @@ fun refineScriptCompilationConfiguration(
// runBlocking is using there to avoid loading dependencies asynchronously
// because it leads to starting more than one gradle daemon in case of resolving dependencies in build.gradle.kts
// It is more efficient to use one hot daemon consistently than multiple daemon in parallel
runBlocking {
@Suppress("DEPRECATION_ERROR")
internalScriptingRunSuspend {
resolver.resolveAsync(scriptContents, environment)
}
} else {
Expand Down
1 change: 1 addition & 0 deletions plugins/scripting/scripting-compiler/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dependencies {
testCompile(commonDep("junit:junit"))

testImplementation(intellijCoreDep()) { includeJars("intellij-core") }
testImplementation(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core"))
testRuntimeOnly(intellijDep()) { includeJars("jps-model", "jna") }

testImplementation(project(":kotlin-reflect"))
Expand Down

0 comments on commit 0cd29ad

Please sign in to comment.