Make sure template classpath is always among script dependencies
This commit is contained in:
+3
-1
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.name.NameUtils
|
import org.jetbrains.kotlin.name.NameUtils
|
||||||
import org.jetbrains.kotlin.psi.KtScript
|
import org.jetbrains.kotlin.psi.KtScript
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
|
import java.io.File
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KFunction
|
import kotlin.reflect.KFunction
|
||||||
import kotlin.reflect.KParameter
|
import kotlin.reflect.KParameter
|
||||||
@@ -36,7 +37,8 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
|||||||
template: KClass<out Any>,
|
template: KClass<out Any>,
|
||||||
providedResolver: DependenciesResolver? = null,
|
providedResolver: DependenciesResolver? = null,
|
||||||
providedScriptFilePattern: String? = null,
|
providedScriptFilePattern: String? = null,
|
||||||
val environment: Map<String, Any?>? = null
|
val environment: Map<String, Any?>? = null,
|
||||||
|
val templateClasspath: List<File> = emptyList()
|
||||||
) : KotlinScriptDefinition(template) {
|
) : KotlinScriptDefinition(template) {
|
||||||
|
|
||||||
val scriptFilePattern by lazy {
|
val scriptFilePattern by lazy {
|
||||||
|
|||||||
@@ -67,10 +67,18 @@ class ScriptContentLoader(private val project: Project) {
|
|||||||
getEnvironment(scriptDef)
|
getEnvironment(scriptDef)
|
||||||
)
|
)
|
||||||
ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file, result.reports)
|
ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file, result.reports)
|
||||||
return result.dependencies
|
return result.dependencies?.adjustByDefinition(scriptDef)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEnvironment(scriptDef: KotlinScriptDefinition) =
|
fun getEnvironment(scriptDef: KotlinScriptDefinition) =
|
||||||
(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)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -72,7 +72,10 @@ fun makeScriptDefsFromTemplatesProviders(providers: Iterable<ScriptTemplatesProv
|
|||||||
try {
|
try {
|
||||||
val loader = createClassLoader(provider)
|
val loader = createClassLoader(provider)
|
||||||
provider.templateClassNames.map {
|
provider.templateClassNames.map {
|
||||||
KotlinScriptDefinitionFromAnnotatedTemplate(loader.loadClass(it).kotlin, provider.resolver, provider.filePattern, provider.environment)
|
KotlinScriptDefinitionFromAnnotatedTemplate(
|
||||||
|
loader.loadClass(it).kotlin, provider.resolver,
|
||||||
|
provider.filePattern, provider.environment, provider.templateClasspath
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ex: Throwable) {
|
catch (ex: Throwable) {
|
||||||
|
|||||||
+15
-15
@@ -139,11 +139,23 @@ internal class ScriptDependenciesUpdater(
|
|||||||
scriptDef: KotlinScriptDefinition
|
scriptDef: KotlinScriptDefinition
|
||||||
): TimeStampedJob {
|
): TimeStampedJob {
|
||||||
val currentTimeStamp = TimeStamps.next()
|
val currentTimeStamp = TimeStamps.next()
|
||||||
|
|
||||||
|
fun process(result: DependenciesResolver.ResolveResult) {
|
||||||
|
val lastTimeStamp = requests[file.path]?.job?.timeStamp
|
||||||
|
val isLastSentRequest = lastTimeStamp == null || lastTimeStamp == currentTimeStamp
|
||||||
|
if (isLastSentRequest) {
|
||||||
|
ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file, result.reports)
|
||||||
|
val resultingDependencies = (result.dependencies ?: ScriptDependencies.Empty).adjustByDefinition(scriptDef)
|
||||||
|
if (cache(resultingDependencies, file)) {
|
||||||
|
onChange()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val dependenciesResolver = scriptDef.dependencyResolver
|
val dependenciesResolver = scriptDef.dependencyResolver
|
||||||
val newJob = if (dependenciesResolver is AsyncDependenciesResolver) {
|
val newJob = if (dependenciesResolver is AsyncDependenciesResolver) {
|
||||||
launch(asyncUpdatesDispatcher) {
|
launch(asyncUpdatesDispatcher) {
|
||||||
processResult(
|
process(
|
||||||
file, currentTimeStamp,
|
|
||||||
dependenciesResolver.resolveAsync(
|
dependenciesResolver.resolveAsync(
|
||||||
contentLoader.getScriptContents(scriptDef, file),
|
contentLoader.getScriptContents(scriptDef, file),
|
||||||
contentLoader.getEnvironment(scriptDef)
|
contentLoader.getEnvironment(scriptDef)
|
||||||
@@ -154,8 +166,7 @@ internal class ScriptDependenciesUpdater(
|
|||||||
else {
|
else {
|
||||||
assert(dependenciesResolver is LegacyResolverWrapper)
|
assert(dependenciesResolver is LegacyResolverWrapper)
|
||||||
launch(legacyUpdatesDispatcher) {
|
launch(legacyUpdatesDispatcher) {
|
||||||
processResult(
|
process(
|
||||||
file, currentTimeStamp,
|
|
||||||
dependenciesResolver.resolve(
|
dependenciesResolver.resolve(
|
||||||
contentLoader.getScriptContents(scriptDef, file),
|
contentLoader.getScriptContents(scriptDef, file),
|
||||||
contentLoader.getEnvironment(scriptDef)
|
contentLoader.getEnvironment(scriptDef)
|
||||||
@@ -166,17 +177,6 @@ internal class ScriptDependenciesUpdater(
|
|||||||
return TimeStampedJob(newJob, currentTimeStamp)
|
return TimeStampedJob(newJob, currentTimeStamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processResult(file: VirtualFile, currentTimeStamp: TimeStamp, result: DependenciesResolver.ResolveResult) {
|
|
||||||
val lastTimeStamp = requests[file.path]?.job?.timeStamp
|
|
||||||
val isLastSentRequest = lastTimeStamp == null || lastTimeStamp == currentTimeStamp
|
|
||||||
if (isLastSentRequest) {
|
|
||||||
ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file, result.reports)
|
|
||||||
if (cache(result.dependencies ?: ScriptDependencies.Empty, file)) {
|
|
||||||
onChange()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateSync(file: VirtualFile, scriptDef: KotlinScriptDefinition): Boolean {
|
fun updateSync(file: VirtualFile, scriptDef: KotlinScriptDefinition): Boolean {
|
||||||
val newDeps = contentLoader.loadContentsAndResolveDependencies(scriptDef, file) ?: ScriptDependencies.Empty
|
val newDeps = contentLoader.loadContentsAndResolveDependencies(scriptDef, file) ?: ScriptDependencies.Empty
|
||||||
return cache(newDeps, file)
|
return cache(newDeps, file)
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
val j: Int = i
|
||||||
|
|
||||||
|
val s: String = str
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package custom.scriptDefinition
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.script.dependencies.*
|
||||||
|
import kotlin.script.dependencies.experimental.*
|
||||||
|
import kotlin.script.templates.ScriptTemplateDefinition
|
||||||
|
|
||||||
|
class TestDependenciesResolver : AsyncDependenciesResolver {
|
||||||
|
override suspend fun resolveAsync(
|
||||||
|
scriptContents: ScriptContents,
|
||||||
|
environment: Environment
|
||||||
|
): DependenciesResolver.ResolveResult {
|
||||||
|
return ScriptDependencies.Empty.asSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ScriptTemplateDefinition(TestDependenciesResolver::class, scriptFilePattern = "script.kts")
|
||||||
|
open class Template: Base()
|
||||||
|
|
||||||
|
open class Base {
|
||||||
|
val i = 3
|
||||||
|
val str = ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
val j: Int = i
|
||||||
|
|
||||||
|
val s: String = str
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package custom.scriptDefinition
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.script.dependencies.*
|
||||||
|
import kotlin.script.templates.ScriptTemplateDefinition
|
||||||
|
|
||||||
|
@ScriptTemplateDefinition(scriptFilePattern = "script.kts")
|
||||||
|
class Template: Base()
|
||||||
|
|
||||||
|
open class Base {
|
||||||
|
val i = 3
|
||||||
|
val str = ""
|
||||||
|
}
|
||||||
+12
@@ -78,6 +78,18 @@ public class ScriptConfigurationHighlightingTestGenerated extends AbstractScript
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("emptyAsyncResolver")
|
||||||
|
public void testEmptyAsyncResolver() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/script/definition/highlighting/emptyAsyncResolver/");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("noResolver")
|
||||||
|
public void testNoResolver() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/script/definition/highlighting/noResolver/");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simple")
|
@TestMetadata("simple")
|
||||||
public void testSimple() throws Exception {
|
public void testSimple() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/script/definition/highlighting/simple/");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/script/definition/highlighting/simple/");
|
||||||
|
|||||||
Reference in New Issue
Block a user