diff --git a/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/MavenDependenciesResolver.kt b/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/MavenDependenciesResolver.kt index 4ab7e57728b..ba02b5477f1 100644 --- a/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/MavenDependenciesResolver.kt +++ b/libraries/scripting/dependencies-maven/src/kotlin/script/experimental/dependencies/maven/MavenDependenciesResolver.kt @@ -21,6 +21,7 @@ import kotlin.script.experimental.dependencies.impl.makeResolveFailureResult import kotlin.script.experimental.dependencies.impl.toRepositoryUrlOrNull import kotlin.script.experimental.dependencies.maven.impl.AetherResolveSession import kotlin.script.experimental.dependencies.maven.impl.mavenCentral +import kotlin.script.experimental.dependencies.impl.dependencyScopes class MavenRepositoryCoordinates( @@ -62,7 +63,12 @@ class MavenDependenciesResolver : ExternalDependenciesResolver { val artifactId = artifactCoordinates.toMavenArtifact()!! try { - val deps = AetherResolveSession(localRepo, remoteRepositories()).resolve(artifactId, JavaScopes.RUNTIME) + val dependencyScopes = options.dependencyScopes ?: listOf(JavaScopes.COMPILE, JavaScopes.RUNTIME) + val deps = AetherResolveSession( + localRepo, remoteRepositories() + ).resolve( + artifactId, dependencyScopes.joinToString(",") + ) if (deps != null) return ResultWithDiagnostics.Success(deps.map { it.file }) } catch (e: DependencyResolutionException) { diff --git a/libraries/scripting/dependencies-maven/test/kotlin/script/experimental/test/MavenResolverTest.kt b/libraries/scripting/dependencies-maven/test/kotlin/script/experimental/test/MavenResolverTest.kt index 81bf3e79a70..58d61fa1b3a 100644 --- a/libraries/scripting/dependencies-maven/test/kotlin/script/experimental/test/MavenResolverTest.kt +++ b/libraries/scripting/dependencies-maven/test/kotlin/script/experimental/test/MavenResolverTest.kt @@ -14,16 +14,21 @@ import kotlin.reflect.full.primaryConstructor import kotlin.script.experimental.dependencies.maven.MavenDependenciesResolver import kotlin.script.experimental.api.ResultWithDiagnostics import kotlin.script.experimental.api.valueOrThrow -import kotlin.script.experimental.dependencies.DependsOn -import kotlin.script.experimental.dependencies.Repository -import kotlin.script.experimental.dependencies.resolveFromAnnotations +import kotlin.script.experimental.dependencies.* +import kotlin.script.experimental.dependencies.impl.DependenciesResolverOptionsName +import kotlin.script.experimental.dependencies.impl.makeExternalDependenciesResolverOptions +import kotlin.script.experimental.dependencies.impl.set @ExperimentalContracts class MavenResolverTest : ResolversTestBase() { - fun resolveAndCheck(coordinates: String, checkBody: (Iterable) -> Boolean = { true }) { + fun resolveAndCheck( + coordinates: String, + options: ExternalDependenciesResolver.Options = ExternalDependenciesResolver.Options.Empty, + checkBody: (Iterable) -> Boolean = { true } + ) { val resolver = MavenDependenciesResolver() - val result = runBlocking { resolver.resolve(coordinates) } + val result = runBlocking { resolver.resolve(coordinates, options) } if (result is ResultWithDiagnostics.Failure) { Assert.fail(result.reports.joinToString("\n") { it.exception?.toString() ?: it.message }) } @@ -40,6 +45,32 @@ class MavenResolverTest : ResolversTestBase() { } } + @ExperimentalStdlibApi + fun testResolveWithRuntime() { + val compileOnly = "compile" + val compileRuntime = "compile,runtime" + val resolvedFilesCount = mutableMapOf() + + listOf(compileOnly, compileRuntime).forEach { scopes -> + resolveAndCheck( + "org.uberfire:uberfire-io:7.39.0.Final", + makeExternalDependenciesResolverOptions(buildMap { + this[DependenciesResolverOptionsName.SCOPE] = scopes + }) + ) { files -> + resolvedFilesCount[scopes] = files.count() + files.any { it.name.startsWith("uberfire-commons") } + } + } + + val compileOnlyCount = resolvedFilesCount[compileOnly]!! + val compileRuntimeCount = resolvedFilesCount[compileRuntime]!! + assertTrue( + "Compile only ($compileOnlyCount) dependencies count should be less than compile/runtime ($compileRuntimeCount) one", + compileOnlyCount < compileRuntimeCount + ) + } + fun testResolveVersionsRange() { resolveAndCheck("org.jetbrains.kotlin:kotlin-annotations-jvm:(1.3.40,1.3.60)") } diff --git a/libraries/scripting/dependencies/src/kotlin/script/experimental/dependencies/impl/SimpleExternalDependenciesResolverOptionsParser.kt b/libraries/scripting/dependencies/src/kotlin/script/experimental/dependencies/impl/SimpleExternalDependenciesResolverOptionsParser.kt index 3e71eaf573c..da88bf9783a 100644 --- a/libraries/scripting/dependencies/src/kotlin/script/experimental/dependencies/impl/SimpleExternalDependenciesResolverOptionsParser.kt +++ b/libraries/scripting/dependencies/src/kotlin/script/experimental/dependencies/impl/SimpleExternalDependenciesResolverOptionsParser.kt @@ -9,7 +9,7 @@ import kotlin.script.experimental.api.* import kotlin.script.experimental.dependencies.ExternalDependenciesResolver private val nameRegex = Regex("^[^\\S\\r\\n]*([a-zA-Z][a-zA-Z0-9-_]*)\\b") -private val valueRegex = Regex("^[^\\S\\r\\n]*([a-zA-Z0-9-_]+)\\b") +private val valueRegex = Regex("^[^\\S\\r\\n]*([a-zA-Z0-9-_,]+)\\b") private val equalsRegex = Regex("^[^\\S\\r\\n]*=") /** diff --git a/libraries/scripting/dependencies/src/kotlin/script/experimental/dependencies/impl/resolverNamedOptions.kt b/libraries/scripting/dependencies/src/kotlin/script/experimental/dependencies/impl/resolverNamedOptions.kt new file mode 100644 index 00000000000..1670406a31f --- /dev/null +++ b/libraries/scripting/dependencies/src/kotlin/script/experimental/dependencies/impl/resolverNamedOptions.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2020 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.dependencies.impl + +import kotlin.script.experimental.dependencies.ExternalDependenciesResolver + +fun ExternalDependenciesResolver.Options.value(name: DependenciesResolverOptionsName) = + value(name.key) + +fun ExternalDependenciesResolver.Options.flag(name: DependenciesResolverOptionsName) = + flag(name.key) + +operator fun MutableMap.set(key: DependenciesResolverOptionsName, value: String) { + put(key.key, value) +} + +/** + * These names are for convenience only. + * They don't have to be implemented in all resolvers. + */ +enum class DependenciesResolverOptionsName(optionName: String? = null) { + TRANSITIVE, + SCOPE; + + val key = optionName ?: name.toLowerCase() +} + +val ExternalDependenciesResolver.Options.transitive + get() = flag(DependenciesResolverOptionsName.TRANSITIVE) + +val ExternalDependenciesResolver.Options.dependencyScopes + get() = value(DependenciesResolverOptionsName.SCOPE)?.split(",") diff --git a/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsTest.kt b/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsTest.kt index 7ea7d4c0934..55e2ecaff83 100644 --- a/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsTest.kt +++ b/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsTest.kt @@ -7,7 +7,9 @@ package org.jetbrains.kotlin.mainKts.test import org.jetbrains.kotlin.mainKts.COMPILED_SCRIPTS_CACHE_DIR_PROPERTY import org.jetbrains.kotlin.mainKts.impl.Directories import org.jetbrains.kotlin.mainKts.MainKtsScript +import org.jetbrains.kotlin.scripting.compiler.plugin.assertTrue import org.junit.Assert +import org.junit.Assert.assertEquals import org.junit.Test import java.io.* import java.util.* @@ -60,6 +62,16 @@ class MainKtsTest { ) } + @Test + fun testResolveRuntimeDeps() { + val resOk = evalFile(File("$TEST_DATA_ROOT/resolve-with-runtime.main.kts")) + assertSucceeded(resOk) + + val resultValue = resOk.valueOrThrow().returnValue + assertTrue(resultValue is ResultValue.Value) { "Result value should be of type Value" } + assertEquals("John Smith", (resultValue as ResultValue.Value).value) + } + // @Test // this test is disabled: the resolving works fine, but ivy resolver is not processing "pom"-type dependencies correctly ( // as far as I can tell) diff --git a/libraries/tools/kotlin-main-kts-test/testData/resolve-with-runtime.csv b/libraries/tools/kotlin-main-kts-test/testData/resolve-with-runtime.csv new file mode 100644 index 00000000000..cdf4422d990 --- /dev/null +++ b/libraries/tools/kotlin-main-kts-test/testData/resolve-with-runtime.csv @@ -0,0 +1,2 @@ +name,surname +John,Smith diff --git a/libraries/tools/kotlin-main-kts-test/testData/resolve-with-runtime.main.kts b/libraries/tools/kotlin-main-kts-test/testData/resolve-with-runtime.main.kts new file mode 100644 index 00000000000..6139a6677fd --- /dev/null +++ b/libraries/tools/kotlin-main-kts-test/testData/resolve-with-runtime.main.kts @@ -0,0 +1,9 @@ +@file:Repository("https://dl.bintray.com/holgerbrandl/mpicbg-scicomp") +//Krangl depends on Klaxon transitively, that's why this repo is needed here +@file:Repository("https://dl.bintray.com/cbeust/maven") +@file:DependsOn("de.mpicbg.scicomp:krangl:0.13", options = arrayOf("scope=compile,runtime")) + +import krangl.* + +val df = DataFrame.readCSV("libraries/tools/kotlin-main-kts-test/testData/resolve-with-runtime.csv") +df.head().rows.first().let { "${it["name"]} ${it["surname"]}" } diff --git a/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/impl/ivy.kt b/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/impl/ivy.kt index 55561588b4f..13d2667e546 100644 --- a/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/impl/ivy.kt +++ b/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/impl/ivy.kt @@ -24,6 +24,8 @@ import kotlin.script.experimental.api.* import kotlin.script.experimental.dependencies.ExternalDependenciesResolver import kotlin.script.experimental.dependencies.RepositoryCoordinates import kotlin.script.experimental.dependencies.impl.toRepositoryUrlOrNull +import kotlin.script.experimental.dependencies.impl.dependencyScopes +import kotlin.script.experimental.dependencies.impl.transitive class IvyResolver : ExternalDependenciesResolver { @@ -111,10 +113,12 @@ class IvyResolver : ExternalDependenciesResolver { val depArtifact = DefaultDependencyArtifactDescriptor(depsDescriptor, artifactName, type, type, null, null) depsDescriptor.addDependencyArtifact(conf, depArtifact) } - depsDescriptor.addDependencyConfiguration("default", "master,compile") + + val dependencyScopes = listOf("master") + (options.dependencyScopes ?: listOf("compile")) + depsDescriptor.addDependencyConfiguration("default", dependencyScopes.joinToString(",")) moduleDescriptor.addDependency(depsDescriptor) - val isTransitive = options.flag("transitive") != false + val isTransitive = options.transitive != false val resolveOptions = ResolveOptions().apply { confs = arrayOf("default")