Add API to get locations of collected script annotations

#KT-38404 fixed

also:
- Add wrapper class for the location combined with the location id
- Add source code location parameters to external dependency resolvers
- Add tests for locations in annotations
- Add tests for order of annotation resolution for dependencies resolvers
This commit is contained in:
Mathias Quintero
2020-05-20 13:42:08 +02:00
committed by Ilya Chernikov
parent 1539128c3f
commit 83087291df
19 changed files with 550 additions and 85 deletions
@@ -23,6 +23,7 @@ dependencies {
testCompile(projectTests(":kotlin-scripting-dependencies"))
testCompile(commonDep("junit"))
testRuntimeOnly("org.slf4j:slf4j-nop:1.7.30")
testImplementation(kotlin("reflect"))
}
sourceSets {
@@ -13,6 +13,8 @@ import org.eclipse.aether.util.repository.AuthenticationBuilder
import java.io.File
import java.util.*
import kotlin.script.experimental.api.ResultWithDiagnostics
import kotlin.script.experimental.api.SourceCode
import kotlin.script.experimental.api.asSuccess
import kotlin.script.experimental.dependencies.ExternalDependenciesResolver
import kotlin.script.experimental.dependencies.RepositoryCoordinates
import kotlin.script.experimental.dependencies.impl.makeResolveFailureResult
@@ -51,7 +53,10 @@ class MavenDependenciesResolver : ExternalDependenciesResolver {
if (this.isNotBlank() && this.count { it == ':' } >= 2) DefaultArtifact(this)
else null
override suspend fun resolve(artifactCoordinates: String): ResultWithDiagnostics<List<File>> {
override suspend fun resolve(
artifactCoordinates: String,
sourceCodeLocation: SourceCode.LocationWithId?
): ResultWithDiagnostics<List<File>> {
val artifactId = artifactCoordinates.toMavenArtifact()!!
@@ -60,18 +65,21 @@ class MavenDependenciesResolver : ExternalDependenciesResolver {
if (deps != null)
return ResultWithDiagnostics.Success(deps.map { it.file })
} catch (e: DependencyResolutionException) {
return makeResolveFailureResult(e.message ?: "unknown error")
return makeResolveFailureResult(e.message ?: "unknown error", sourceCodeLocation)
}
return makeResolveFailureResult(allRepositories().map { "$it: $artifactId not found" })
return makeResolveFailureResult(allRepositories().map { "$it: $artifactId not found" }, sourceCodeLocation)
}
private fun tryResolveEnvironmentVariable(str: String) =
if (str.startsWith("$")) System.getenv(str.substring(1)) ?: str
else str
override fun addRepository(repositoryCoordinates: RepositoryCoordinates) {
override fun addRepository(
repositoryCoordinates: RepositoryCoordinates,
sourceCodeLocation: SourceCode.LocationWithId?
): ResultWithDiagnostics<Boolean> {
val url = repositoryCoordinates.toRepositoryUrlOrNull()
?: throw IllegalArgumentException("Invalid Maven repository URL: ${repositoryCoordinates}")
?: return false.asSuccess()
val repo = RemoteRepository.Builder(
repositoryCoordinates.string,
"default",
@@ -91,5 +99,6 @@ class MavenDependenciesResolver : ExternalDependenciesResolver {
}
}
repos.add(repo.build())
return true.asSuccess()
}
}
@@ -7,16 +7,21 @@ package kotlin.script.experimental.test
import kotlinx.coroutines.runBlocking
import org.junit.Assert
import org.junit.Ignore
import java.io.File
import kotlin.contracts.ExperimentalContracts
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
@ExperimentalContracts
class MavenResolverTest : ResolversTestBase() {
fun resolveAndCheck(coordinates: String, checkBody: (Iterable<File>) -> Boolean = { true } ) {
fun resolveAndCheck(coordinates: String, checkBody: (Iterable<File>) -> Boolean = { true }) {
val resolver = MavenDependenciesResolver()
val result = runBlocking { resolver.resolve(coordinates) }
if (result is ResultWithDiagnostics.Failure) {
@@ -44,4 +49,51 @@ class MavenResolverTest : ResolversTestBase() {
files.any { it.extension == "pom" }
}
}
// Ignored - tests with custom repos often break the CI due to the caching issues
// TODO: find a way to enable iut back
@Ignore
fun ignore_testResolveFromAnnotationsWillResolveTheSameRegardlessOfAnnotationOrder() {
val dependsOnConstructor = DependsOn::class.primaryConstructor!!
val repositoryConstructor = Repository::class.primaryConstructor!!
// @DepensOn("eu.jrie.jetbrains:kotlin-shell-core:0.2")
val dependsOn = dependsOnConstructor.callBy(
mapOf(
dependsOnConstructor.parameters.first() to arrayOf("eu.jrie.jetbrains:kotlin-shell-core:0.2")
)
)
// @Repository("https://dl.bintray.com/kotlin/kotlin-eap", "https://dl.bintray.com/jakubriegel/kotlin-shell")
val repositories = repositoryConstructor.callBy(
mapOf(
repositoryConstructor.parameters.first() to arrayOf(
"https://dl.bintray.com/kotlin/kotlin-eap",
"https://dl.bintray.com/jakubriegel/kotlin-shell"
)
)
)
val annotationsWithReposFirst = listOf(repositories, dependsOn)
val annotationsWithDependsOnFirst = listOf(dependsOn, repositories)
val filesWithReposFirst = runBlocking {
MavenDependenciesResolver().resolveFromAnnotations(annotationsWithReposFirst)
}.valueOrThrow()
val filesWithDependsOnFirst = runBlocking {
MavenDependenciesResolver().resolveFromAnnotations(annotationsWithDependsOnFirst)
}.valueOrThrow()
// Tests that the jar was resolved
assert(
filesWithReposFirst.any { it.name.startsWith("kotlin-shell-core-") && it.extension == "jar" }
)
assert(
filesWithDependsOnFirst.any { it.name.startsWith("kotlin-shell-core-") && it.extension == "jar" }
)
// Test that the the same files are resolved regardless of annotation order
assertEquals(filesWithReposFirst.map { it.name }.sorted(), filesWithDependsOnFirst.map { it.name }.sorted())
}
}