Add script configuration dependencies to script classpath

It was missing during configuration refinement thought new scripting API and during loading script configuration on Gradle project import

Do not pass additional classpath to configuration classpath: this may only affects Gradle with New scripting API (because it isn't used from other places)
In additional classpath kotlin-compiler and kotlin-stdlib was passed and there is no needs for this during loading Script Definitions through new scripting API

^KT-34626 Fixed
This commit is contained in:
Natalia Selezneva
2019-11-14 13:33:32 +03:00
parent 29ef10a919
commit ca71b2fe90
6 changed files with 58 additions and 53 deletions
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * Copyright 2010-2019 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.core.script package org.jetbrains.kotlin.idea.core.script
@@ -235,7 +224,7 @@ fun loadDefinitionsFromTemplates(
// as a compatibility measure, the asm based reading of annotations should be implemented to filter classes before classloading // as a compatibility measure, the asm based reading of annotations should be implemented to filter classes before classloading
val template = loader.loadClass(templateClassName).kotlin val template = loader.loadClass(templateClassName).kotlin
val hostConfiguration = ScriptingHostConfiguration(baseHostConfiguration) { val hostConfiguration = ScriptingHostConfiguration(baseHostConfiguration) {
configurationDependencies(JvmDependency(classpath)) configurationDependencies(JvmDependency(templateClasspath))
} }
when { when {
template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateDefinition>() != null -> { template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateDefinition>() != null -> {
@@ -29,12 +29,16 @@ import org.jetbrains.kotlin.idea.core.script.configuration.getGradleScriptInputs
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
import org.jetbrains.kotlin.scripting.resolve.adjustByDefinition
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings
import org.jetbrains.plugins.gradle.util.GradleConstants import org.jetbrains.plugins.gradle.util.GradleConstants
import java.io.File import java.io.File
import kotlin.script.experimental.dependencies.ScriptDependencies import kotlin.script.experimental.api.*
import kotlin.script.experimental.jvm.JvmDependency
import kotlin.script.experimental.jvm.jdkHome
import kotlin.script.experimental.jvm.jvm
class KotlinGradleBuildScriptsDataService : AbstractProjectDataService<GradleSourceSetData, Void>() { class KotlinGradleBuildScriptsDataService : AbstractProjectDataService<GradleSourceSetData, Void>() {
override fun getTargetDataKey(): Key<GradleSourceSetData> = GradleSourceSetData.KEY override fun getTargetDataKey(): Key<GradleSourceSetData> = GradleSourceSetData.KEY
@@ -67,21 +71,25 @@ class KotlinGradleBuildScriptsDataService : AbstractProjectDataService<GradleSou
// todo(KT-34440): take inputs snapshot before starting import // todo(KT-34440): take inputs snapshot before starting import
val inputs = getGradleScriptInputsStamp(project, virtualFile) val inputs = getGradleScriptInputsStamp(project, virtualFile)
val definition = virtualFile.findScriptDefinition(project) ?: return@forEach
val configuration =
definition.compilationConfiguration.with {
jvm.jdkHome(javaHome)
defaultImports(buildScript.imports)
dependencies(JvmDependency(buildScript.classPath.map { File(it) }))
ide.dependenciesSources(JvmDependency(buildScript.sourcePath.map { File(it) }))
}.adjustByDefinition(definition)
files.add( files.add(
Pair( Pair(
virtualFile, virtualFile,
ScriptConfigurationSnapshot( ScriptConfigurationSnapshot(
inputs ?: CachedConfigurationInputs.OutOfDate, inputs ?: CachedConfigurationInputs.OutOfDate,
listOf(), listOf(),
ScriptCompilationConfigurationWrapper.FromLegacy( ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(
VirtualFileScriptSource(virtualFile), VirtualFileScriptSource(virtualFile),
ScriptDependencies( configuration
javaHome = javaHome,
classpath = buildScript.classPath.map { File(it) },
sources = buildScript.sourcePath.map { File(it) },
imports = buildScript.imports
),
virtualFile.findScriptDefinition(project)
) )
) )
) )
@@ -23,9 +23,6 @@ val ScriptingHostConfigurationKeys.getEnvironment by PropertiesCollection.key<()
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
object TemplateDefinition : ScriptCompilationConfiguration( object TemplateDefinition : ScriptCompilationConfiguration(
{ {
jvm {
dependenciesFromClassContext(TemplateDefinition::class)
}
ide { ide {
acceptedLocations(ScriptAcceptedLocation.Everywhere) acceptedLocations(ScriptAcceptedLocation.Everywhere)
} }
@@ -1,23 +1,24 @@
package custom.scriptDefinition package custom.scriptDefinition
import java.io.File import kotlin.script.experimental.annotations.KotlinScript
import kotlin.script.dependencies.* import kotlin.script.experimental.api.*
import kotlin.script.experimental.dependencies.*
import kotlin.script.templates.ScriptTemplateDefinition
import kotlin.script.experimental.location.*
class TestDependenciesResolver : AsyncDependenciesResolver { @KotlinScript(
override suspend fun resolveAsync( displayName = "Definition for tests",
scriptContents: ScriptContents, fileExtension = "kts",
environment: Environment compilationConfiguration = TemplateDefinition::class
): DependenciesResolver.ResolveResult { )
return ScriptDependencies.Empty.asSuccess() open class Template(val args: Array<String>)
@Suppress("UNCHECKED_CAST")
object TemplateDefinition : ScriptCompilationConfiguration(
{
baseClass(Base::class)
ide {
acceptedLocations(ScriptAcceptedLocation.Everywhere)
}
} }
} )
@ScriptExpectedLocations([ScriptExpectedLocation.Everywhere])
@ScriptTemplateDefinition(TestDependenciesResolver::class, scriptFilePattern = "script.kts")
open class Template: Base()
open class Base { open class Base {
val i = 3 val i = 3
@@ -12,7 +12,6 @@ import java.io.File
import kotlin.script.dependencies.ScriptContents import kotlin.script.dependencies.ScriptContents
import kotlin.script.experimental.dependencies.DependenciesResolver import kotlin.script.experimental.dependencies.DependenciesResolver
import kotlin.script.experimental.dependencies.DependenciesResolver.ResolveResult.Failure import kotlin.script.experimental.dependencies.DependenciesResolver.ResolveResult.Failure
import kotlin.script.experimental.dependencies.ScriptDependencies
import kotlin.script.experimental.dependencies.ScriptReport import kotlin.script.experimental.dependencies.ScriptReport
class ScriptContentLoader(private val project: Project) { class ScriptContentLoader(private val project: Project) {
@@ -54,14 +53,6 @@ class ScriptContentLoader(private val project: Project) {
(scriptDef as? KotlinScriptDefinitionFromAnnotatedTemplate)?.environment.orEmpty() (scriptDef as? KotlinScriptDefinitionFromAnnotatedTemplate)?.environment.orEmpty()
} }
fun ScriptDependencies.adjustByDefinition(
scriptDef: KotlinScriptDefinition
): ScriptDependencies {
val additionalClasspath = (scriptDef as? KotlinScriptDefinitionFromAnnotatedTemplate)?.templateClasspath ?: return this
if (additionalClasspath.isEmpty()) return this
return copy(classpath = additionalClasspath + classpath)
}
fun Throwable.asResolveFailure(scriptDef: KotlinScriptDefinition): Failure { fun Throwable.asResolveFailure(scriptDef: KotlinScriptDefinition): Failure {
val prefix = "${scriptDef.dependencyResolver::class.simpleName} threw exception ${this::class.simpleName}:\n " val prefix = "${scriptDef.dependencyResolver::class.simpleName} threw exception ${this::class.simpleName}:\n "
return Failure(ScriptReport(prefix + (message ?: "<no message>"), ScriptReport.Severity.FATAL)) return Failure(ScriptReport(prefix + (message ?: "<no message>"), ScriptReport.Severity.FATAL))
@@ -229,7 +229,10 @@ fun refineScriptCompilationConfiguration(
.onSuccess { .onSuccess {
it.refineBeforeCompiling(script, collectedData) it.refineBeforeCompiling(script, collectedData)
}.onSuccess { }.onSuccess {
ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(ktFileSource, it).asSuccess() ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(
ktFileSource,
it.adjustByDefinition(definition)
).asSuccess()
} }
} else { } else {
val file = script.getVirtualFile(definition) val file = script.getVirtualFile(definition)
@@ -260,12 +263,28 @@ fun refineScriptCompilationConfiguration(
else else
ScriptCompilationConfigurationWrapper.FromLegacy( ScriptCompilationConfigurationWrapper.FromLegacy(
ktFileSource, ktFileSource,
result.dependencies?.adjustByDefinition(definition.legacyDefinition), result.dependencies?.adjustByDefinition(definition),
definition definition
).asSuccess(result.reports.mapToDiagnostics()) ).asSuccess(result.reports.mapToDiagnostics())
} }
} }
fun ScriptDependencies.adjustByDefinition(definition: ScriptDefinition): ScriptDependencies {
val additionalClasspath = additionalClasspath(definition)
if (additionalClasspath.isEmpty()) return this
return copy(classpath = additionalClasspath + classpath)
}
fun ScriptCompilationConfiguration.adjustByDefinition(definition: ScriptDefinition): ScriptCompilationConfiguration {
return this.withUpdatedClasspath(additionalClasspath(definition))
}
private fun additionalClasspath(definition: ScriptDefinition): List<File> {
return (definition.asLegacyOrNull<KotlinScriptDefinitionFromAnnotatedTemplate>()?.templateClasspath
?: definition.hostConfiguration[ScriptingHostConfiguration.configurationDependencies].toClassPathOrEmpty())
}
internal fun makeScriptContents( internal fun makeScriptContents(
file: VirtualFile, file: VirtualFile,
legacyDefinition: KotlinScriptDefinition, legacyDefinition: KotlinScriptDefinition,