Refactor script definitions and resolving/refining infrastructure:
- implement wrappers to wrap old and new API providers and resolvers - make old API deprecated (with error where possible) - drop old internal classes related to the old API - refactor usages accordingly - fix and add missing features to the scripting API where necessary
This commit is contained in:
@@ -13,7 +13,7 @@ import com.intellij.testFramework.TestDataFile;
|
|||||||
import kotlin.collections.ArraysKt;
|
import kotlin.collections.ArraysKt;
|
||||||
import kotlin.collections.CollectionsKt;
|
import kotlin.collections.CollectionsKt;
|
||||||
import kotlin.io.FilesKt;
|
import kotlin.io.FilesKt;
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies;
|
import kotlin.script.experimental.api.ErrorHandlingKt;
|
||||||
import kotlin.text.Charsets;
|
import kotlin.text.Charsets;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
|
|||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider;
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider;
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper;
|
||||||
import org.jetbrains.kotlin.test.ConfigurationKind;
|
import org.jetbrains.kotlin.test.ConfigurationKind;
|
||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils;
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils;
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
@@ -433,9 +434,9 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
|||||||
if (externalImportsProvider != null) {
|
if (externalImportsProvider != null) {
|
||||||
myEnvironment.getSourceFiles().forEach(
|
myEnvironment.getSourceFiles().forEach(
|
||||||
file -> {
|
file -> {
|
||||||
ScriptDependencies dependencies = externalImportsProvider.getScriptDependencies(file);
|
ScriptCompilationConfigurationWrapper refinedConfiguration = ErrorHandlingKt.valueOrNull(externalImportsProvider.getScriptConfigurationResult(file));
|
||||||
if (dependencies != null) {
|
if (refinedConfiguration != null) {
|
||||||
files.addAll(dependencies.getClasspath());
|
files.addAll(refinedConfiguration.getDependenciesClassPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import kotlin.script.experimental.annotations.KotlinScript
|
|||||||
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
||||||
import kotlin.script.experimental.api.implicitReceivers
|
import kotlin.script.experimental.api.implicitReceivers
|
||||||
import kotlin.script.experimental.api.providedProperties
|
import kotlin.script.experimental.api.providedProperties
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrStdlib
|
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrStdlib
|
||||||
|
|
||||||
abstract class AbstractCustomScriptCodegenTest : CodegenTestCase() {
|
abstract class AbstractCustomScriptCodegenTest : CodegenTestCase() {
|
||||||
@@ -37,7 +38,9 @@ abstract class AbstractCustomScriptCodegenTest : CodegenTestCase() {
|
|||||||
|
|
||||||
override fun updateConfiguration(configuration: CompilerConfiguration) {
|
override fun updateConfiguration(configuration: CompilerConfiguration) {
|
||||||
if (scriptDefinitions.isNotEmpty()) {
|
if (scriptDefinitions.isNotEmpty()) {
|
||||||
configureScriptDefinitions(scriptDefinitions, configuration, this::class.java.classLoader, MessageCollector.NONE, emptyMap())
|
configureScriptDefinitions(
|
||||||
|
scriptDefinitions, configuration, this::class.java.classLoader, MessageCollector.NONE, defaultJvmScriptingHostConfiguration
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
configuration.addJvmClasspathRoots(additionalDependencies.orEmpty())
|
configuration.addJvmClasspathRoots(additionalDependencies.orEmpty())
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.io.File
|
|||||||
import java.lang.reflect.Constructor
|
import java.lang.reflect.Constructor
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.script.experimental.annotations.KotlinScript
|
import kotlin.script.experimental.annotations.KotlinScript
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrStdlib
|
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrStdlib
|
||||||
|
|
||||||
class CustomScriptCodegenTest : CodegenTestCase() {
|
class CustomScriptCodegenTest : CodegenTestCase() {
|
||||||
@@ -65,7 +66,8 @@ class CustomScriptCodegenTest : CodegenTestCase() {
|
|||||||
|
|
||||||
if (scriptDefinitions.isNotEmpty()) {
|
if (scriptDefinitions.isNotEmpty()) {
|
||||||
configureScriptDefinitions(
|
configureScriptDefinitions(
|
||||||
scriptDefinitions.asList(), configuration, this::class.java.classLoader, MessageCollector.NONE, emptyMap()
|
scriptDefinitions.asList(), configuration, this::class.java.classLoader,
|
||||||
|
MessageCollector.NONE, defaultJvmScriptingHostConfiguration
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
|
|||||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||||
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
||||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
import org.jetbrains.kotlin.scripts.TestKotlinScriptDependenciesResolver
|
import org.jetbrains.kotlin.scripts.TestKotlinScriptDependenciesResolver
|
||||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||||
@@ -33,14 +34,21 @@ import org.jetbrains.kotlin.test.KotlinTestUtils
|
|||||||
import org.jetbrains.kotlin.test.TestJdkKind
|
import org.jetbrains.kotlin.test.TestJdkKind
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
import kotlin.script.templates.ScriptTemplateDefinition
|
import kotlin.script.templates.ScriptTemplateDefinition
|
||||||
|
|
||||||
class ScriptGenTest : CodegenTestCase() {
|
class ScriptGenTest : CodegenTestCase() {
|
||||||
companion object {
|
companion object {
|
||||||
private val FIB_SCRIPT_DEFINITION =
|
private val FIB_SCRIPT_DEFINITION =
|
||||||
KotlinScriptDefinitionFromAnnotatedTemplate(ScriptWithIntParam::class)
|
ScriptDefinition.FromLegacy(
|
||||||
|
defaultJvmScriptingHostConfiguration,
|
||||||
|
KotlinScriptDefinitionFromAnnotatedTemplate(ScriptWithIntParam::class)
|
||||||
|
)
|
||||||
private val NO_PARAM_SCRIPT_DEFINITION =
|
private val NO_PARAM_SCRIPT_DEFINITION =
|
||||||
KotlinScriptDefinitionFromAnnotatedTemplate(Any::class)
|
ScriptDefinition.FromLegacy(
|
||||||
|
defaultJvmScriptingHostConfiguration,
|
||||||
|
KotlinScriptDefinitionFromAnnotatedTemplate(Any::class)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
|
|||||||
+8
-12
@@ -12,16 +12,13 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
|||||||
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
|
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
|
||||||
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
||||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinitionAdapterFromNewAPI
|
|
||||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import org.jetbrains.kotlin.test.TestJdkKind
|
import org.jetbrains.kotlin.test.TestJdkKind
|
||||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.script.experimental.api.KotlinType
|
|
||||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
import kotlin.script.experimental.host.createCompilationConfigurationFromTemplate
|
|
||||||
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
private const val testDataPath = "compiler/testData/script/collectDependencies"
|
private const val testDataPath = "compiler/testData/script/collectDependencies"
|
||||||
@@ -58,15 +55,14 @@ class CollectScriptCompilationDependenciesTest : KtUsefulTestCase() {
|
|||||||
|
|
||||||
private fun runTest(scriptFile: String, expectedDependencies: List<String>, classPath: List<File> = emptyList()) {
|
private fun runTest(scriptFile: String, expectedDependencies: List<String>, classPath: List<File> = emptyList()) {
|
||||||
val configuration = KotlinTestUtils.newConfiguration(ConfigurationKind.NO_KOTLIN_REFLECT, TestJdkKind.MOCK_JDK).apply {
|
val configuration = KotlinTestUtils.newConfiguration(ConfigurationKind.NO_KOTLIN_REFLECT, TestJdkKind.MOCK_JDK).apply {
|
||||||
val hostConfiguration = ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration)
|
add(
|
||||||
val scriptDefinition = KotlinScriptDefinitionAdapterFromNewAPI(
|
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS,
|
||||||
createCompilationConfigurationFromTemplate(
|
ScriptDefinition.FromTemplate(
|
||||||
KotlinType(TestScriptWithRequire::class),
|
ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration),
|
||||||
hostConfiguration, KotlinScriptDefinition::class
|
TestScriptWithRequire::class,
|
||||||
),
|
ScriptDefinition::class
|
||||||
hostConfiguration
|
)
|
||||||
)
|
)
|
||||||
add(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, scriptDefinition)
|
|
||||||
|
|
||||||
addKotlinSourceRoot(File(testDataPath, scriptFile).path)
|
addKotlinSourceRoot(File(testDataPath, scriptFile).path)
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler
|
|||||||
import org.jetbrains.kotlin.daemon.TestMessageCollector
|
import org.jetbrains.kotlin.daemon.TestMessageCollector
|
||||||
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
||||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinitionAdapterFromNewAPI
|
|
||||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import org.jetbrains.kotlin.test.TestJdkKind
|
import org.jetbrains.kotlin.test.TestJdkKind
|
||||||
@@ -27,10 +26,10 @@ import java.io.File
|
|||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.script.experimental.annotations.KotlinScript
|
import kotlin.script.experimental.annotations.KotlinScript
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
|
import kotlin.script.experimental.host.FileBasedScriptSource
|
||||||
import kotlin.script.experimental.host.FileScriptSource
|
import kotlin.script.experimental.host.FileScriptSource
|
||||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
import kotlin.script.experimental.host.configurationDependencies
|
import kotlin.script.experimental.host.configurationDependencies
|
||||||
import kotlin.script.experimental.host.createCompilationConfigurationFromTemplate
|
|
||||||
import kotlin.script.experimental.jvm.*
|
import kotlin.script.experimental.jvm.*
|
||||||
|
|
||||||
private const val testDataPath = "compiler/testData/script/cliCompilation"
|
private const val testDataPath = "compiler/testData/script/cliCompilation"
|
||||||
@@ -75,14 +74,10 @@ class ScriptCliCompilationTest : KtUsefulTestCase() {
|
|||||||
val hostConfiguration = ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration) {
|
val hostConfiguration = ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration) {
|
||||||
configurationDependencies(JvmDependency(classpath))
|
configurationDependencies(JvmDependency(classpath))
|
||||||
}
|
}
|
||||||
val scriptDefinition = KotlinScriptDefinitionAdapterFromNewAPI(
|
add(
|
||||||
createCompilationConfigurationFromTemplate(
|
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS,
|
||||||
KotlinType(scriptDef),
|
ScriptDefinition.FromTemplate(hostConfiguration, scriptDef, ScriptDefinition::class)
|
||||||
hostConfiguration, KotlinScriptDefinition::class
|
|
||||||
),
|
|
||||||
hostConfiguration
|
|
||||||
)
|
)
|
||||||
add(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, scriptDefinition)
|
|
||||||
}
|
}
|
||||||
loadScriptingPlugin(this)
|
loadScriptingPlugin(this)
|
||||||
}
|
}
|
||||||
@@ -122,7 +117,7 @@ object TestScriptWithRequireConfiguration : ScriptCompilationConfiguration(
|
|||||||
}
|
}
|
||||||
refineConfiguration {
|
refineConfiguration {
|
||||||
onAnnotations(Import::class, DependsOn::class) { context: ScriptConfigurationRefinementContext ->
|
onAnnotations(Import::class, DependsOn::class) { context: ScriptConfigurationRefinementContext ->
|
||||||
val scriptBaseDir = (context.script as? FileScriptSource)?.file?.parentFile
|
val scriptBaseDir = (context.script as? FileBasedScriptSource)?.file?.parentFile
|
||||||
val sources = context.collectedData?.get(ScriptCollectedData.foundAnnotations)
|
val sources = context.collectedData?.get(ScriptCollectedData.foundAnnotations)
|
||||||
?.flatMap {
|
?.flatMap {
|
||||||
(it as? Import)?.sources?.map { sourceName ->
|
(it as? Import)?.sources?.map { sourceName ->
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.daemon.toFile
|
|||||||
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
||||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.InvalidScriptResolverAnnotation
|
import org.jetbrains.kotlin.scripting.resolve.InvalidScriptResolverAnnotation
|
||||||
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||||
@@ -50,6 +51,7 @@ import kotlin.reflect.KClass
|
|||||||
import kotlin.script.dependencies.*
|
import kotlin.script.dependencies.*
|
||||||
import kotlin.script.experimental.dependencies.*
|
import kotlin.script.experimental.dependencies.*
|
||||||
import kotlin.script.experimental.dependencies.DependenciesResolver.ResolveResult
|
import kotlin.script.experimental.dependencies.DependenciesResolver.ResolveResult
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
import kotlin.script.templates.AcceptedAnnotations
|
import kotlin.script.templates.AcceptedAnnotations
|
||||||
import kotlin.script.templates.ScriptTemplateDefinition
|
import kotlin.script.templates.ScriptTemplateDefinition
|
||||||
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
||||||
@@ -348,7 +350,13 @@ class ScriptTemplateTest : KtUsefulTestCase() {
|
|||||||
*additionalClasspath)
|
*additionalClasspath)
|
||||||
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
||||||
configuration.addKotlinSourceRoot(scriptPath)
|
configuration.addKotlinSourceRoot(scriptPath)
|
||||||
configuration.add(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, scriptDefinition)
|
configuration.add(
|
||||||
|
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS,
|
||||||
|
ScriptDefinition.FromLegacy(
|
||||||
|
defaultJvmScriptingHostConfiguration,
|
||||||
|
scriptDefinition
|
||||||
|
)
|
||||||
|
)
|
||||||
configuration.put(JVMConfigurationKeys.DISABLE_STANDARD_SCRIPT_DEFINITION, true)
|
configuration.put(JVMConfigurationKeys.DISABLE_STANDARD_SCRIPT_DEFINITION, true)
|
||||||
configuration.put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
|
configuration.put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
|||||||
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
||||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.StandardScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.StandardScriptDefinition
|
||||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
@@ -37,6 +38,7 @@ import org.jetbrains.kotlin.utils.tryConstructClassFromStringArgs
|
|||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
class ScriptTest : KtUsefulTestCase() {
|
class ScriptTest : KtUsefulTestCase() {
|
||||||
fun testStandardScriptWithParams() {
|
fun testStandardScriptWithParams() {
|
||||||
@@ -102,7 +104,13 @@ class ScriptTest : KtUsefulTestCase() {
|
|||||||
val configuration = KotlinTestUtils.newConfiguration(ConfigurationKind.ALL, TestJdkKind.FULL_JDK)
|
val configuration = KotlinTestUtils.newConfiguration(ConfigurationKind.ALL, TestJdkKind.FULL_JDK)
|
||||||
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
||||||
configuration.addKotlinSourceRoot("compiler/testData/script/$scriptPath")
|
configuration.addKotlinSourceRoot("compiler/testData/script/$scriptPath")
|
||||||
configuration.add(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, scriptDefinition)
|
configuration.add(
|
||||||
|
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS,
|
||||||
|
ScriptDefinition.FromLegacy(
|
||||||
|
defaultJvmScriptingHostConfiguration,
|
||||||
|
scriptDefinition
|
||||||
|
)
|
||||||
|
)
|
||||||
configuration.put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
|
configuration.put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
|
||||||
if (saveClassesDir != null) {
|
if (saveClassesDir != null) {
|
||||||
configuration.put(JVMConfigurationKeys.OUTPUT_DIRECTORY, saveClassesDir)
|
configuration.put(JVMConfigurationKeys.OUTPUT_DIRECTORY, saveClassesDir)
|
||||||
|
|||||||
+3
-3
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
|
|||||||
import org.jetbrains.kotlin.idea.core.script.dependencies.ScriptAdditionalIdeaDependenciesProvider
|
import org.jetbrains.kotlin.idea.core.script.dependencies.ScriptAdditionalIdeaDependenciesProvider
|
||||||
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
|
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
|
|||||||
data class ScriptModuleInfo(
|
data class ScriptModuleInfo(
|
||||||
val project: Project,
|
val project: Project,
|
||||||
val scriptFile: VirtualFile,
|
val scriptFile: VirtualFile,
|
||||||
val scriptDefinition: KotlinScriptDefinition
|
val scriptDefinition: ScriptDefinition
|
||||||
) : IdeaModuleInfo {
|
) : IdeaModuleInfo {
|
||||||
override val moduleOrigin: ModuleOrigin
|
override val moduleOrigin: ModuleOrigin
|
||||||
get() = ModuleOrigin.OTHER
|
get() = ModuleOrigin.OTHER
|
||||||
@@ -85,7 +85,7 @@ sealed class ScriptDependenciesInfo(val project: Project) : IdeaModuleInfo, Bina
|
|||||||
class ForFile(
|
class ForFile(
|
||||||
project: Project,
|
project: Project,
|
||||||
val scriptFile: VirtualFile,
|
val scriptFile: VirtualFile,
|
||||||
val scriptDefinition: KotlinScriptDefinition
|
val scriptDefinition: ScriptDefinition
|
||||||
) : ScriptDependenciesInfo(project) {
|
) : ScriptDependenciesInfo(project) {
|
||||||
override val sdk: Sdk?
|
override val sdk: Sdk?
|
||||||
get() {
|
get() {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.idea.util.isInSourceContentWithoutInjected
|
|||||||
import org.jetbrains.kotlin.idea.util.isKotlinBinary
|
import org.jetbrains.kotlin.idea.util.isKotlinBinary
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||||
import org.jetbrains.kotlin.scripting.definitions.scriptDefinitionByFileName
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinitionByFileName
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
import org.jetbrains.kotlin.utils.yieldIfNotNull
|
import org.jetbrains.kotlin.utils.yieldIfNotNull
|
||||||
@@ -174,7 +174,7 @@ private fun <T> PsiElement.collectInfos(c: ModuleInfoCollector<T>): T {
|
|||||||
return c.onResult(it)
|
return c.onResult(it)
|
||||||
}
|
}
|
||||||
containingKtFile.script?.let {
|
containingKtFile.script?.let {
|
||||||
val definition = scriptDefinitionByFileName(project, containingKtFile.name)
|
val definition = findScriptDefinitionByFileName(project, containingKtFile.name)
|
||||||
return c.onResult(ScriptModuleInfo(project, virtualFile, definition))
|
return c.onResult(ScriptModuleInfo(project, virtualFile, definition))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -37,7 +37,7 @@ import org.jetbrains.kotlin.idea.caches.project.*
|
|||||||
import org.jetbrains.kotlin.idea.project.getLanguageVersionSettings
|
import org.jetbrains.kotlin.idea.project.getLanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.idea.project.platform
|
import org.jetbrains.kotlin.idea.project.platform
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.platform.jvm.JdkPlatform
|
import org.jetbrains.kotlin.platform.jvm.JdkPlatform
|
||||||
import org.jetbrains.kotlin.platform.subplatformOfType
|
import org.jetbrains.kotlin.platform.subplatformOfType
|
||||||
import org.jetbrains.kotlin.utils.Jsr305State
|
import org.jetbrains.kotlin.utils.Jsr305State
|
||||||
@@ -92,8 +92,8 @@ private data class ScriptLanguageSettings(
|
|||||||
|
|
||||||
private val SCRIPT_LANGUAGE_SETTINGS = Key.create<CachedValue<ScriptLanguageSettings>>("SCRIPT_LANGUAGE_SETTINGS")
|
private val SCRIPT_LANGUAGE_SETTINGS = Key.create<CachedValue<ScriptLanguageSettings>>("SCRIPT_LANGUAGE_SETTINGS")
|
||||||
|
|
||||||
private fun getLanguageSettingsForScripts(project: Project, scriptDefinition: KotlinScriptDefinition): ScriptLanguageSettings {
|
private fun getLanguageSettingsForScripts(project: Project, scriptDefinition: ScriptDefinition): ScriptLanguageSettings {
|
||||||
val args = scriptDefinition.additionalCompilerArguments
|
val args = scriptDefinition.compilerOptions
|
||||||
return if (args == null || args.none()) {
|
return if (args == null || args.none()) {
|
||||||
ScriptLanguageSettings(project.getLanguageVersionSettings(), TargetPlatformVersion.NoVersion)
|
ScriptLanguageSettings(project.getLanguageVersionSettings(), TargetPlatformVersion.NoVersion)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+2
-2
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.idea.caches.project.NotUnderContentRootModuleInfo
|
|||||||
import org.jetbrains.kotlin.idea.caches.project.getModuleInfo
|
import org.jetbrains.kotlin.idea.caches.project.getModuleInfo
|
||||||
import org.jetbrains.kotlin.idea.core.script.IdeScriptReportSink
|
import org.jetbrains.kotlin.idea.core.script.IdeScriptReportSink
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesUpdater
|
import org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationUpdater
|
||||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||||
import org.jetbrains.kotlin.idea.util.isRunningInCidrIde
|
import org.jetbrains.kotlin.idea.util.isRunningInCidrIde
|
||||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||||
@@ -70,7 +70,7 @@ object KotlinHighlightingUtil {
|
|||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
private fun shouldHighlightScript(ktFile: KtFile): Boolean {
|
private fun shouldHighlightScript(ktFile: KtFile): Boolean {
|
||||||
if (isRunningInCidrIde) return false // There is no Java support in CIDR. So do not highlight errors in KTS if running in CIDR.
|
if (isRunningInCidrIde) return false // There is no Java support in CIDR. So do not highlight errors in KTS if running in CIDR.
|
||||||
if (!ScriptDependenciesUpdater.areDependenciesCached(ktFile)) return false
|
if (!ScriptsCompilationConfigurationUpdater.areDependenciesCached(ktFile)) return false
|
||||||
if (ktFile.virtualFile.getUserData(IdeScriptReportSink.Reports)?.any { it.severity == ScriptReport.Severity.FATAL } == true) {
|
if (ktFile.virtualFile.getUserData(IdeScriptReportSink.Reports)?.any { it.severity == ScriptReport.Severity.FATAL } == true) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -39,9 +39,8 @@ import com.intellij.util.ui.UIUtil
|
|||||||
import org.jetbrains.kotlin.idea.core.script.IdeScriptReportSink
|
import org.jetbrains.kotlin.idea.core.script.IdeScriptReportSink
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
|
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesUpdater
|
import org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationUpdater
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
|
||||||
import kotlin.script.experimental.dependencies.ScriptReport
|
import kotlin.script.experimental.dependencies.ScriptReport
|
||||||
|
|
||||||
class ScriptExternalHighlightingPass(
|
class ScriptExternalHighlightingPass(
|
||||||
@@ -62,9 +61,10 @@ class ScriptExternalHighlightingPass(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ScriptDependenciesUpdater.areDependenciesCached(file)) {
|
if (!ScriptsCompilationConfigurationUpdater.areDependenciesCached(file)) {
|
||||||
val scriptDependencies = ScriptDependenciesManager.getInstance(file.project).getScriptDependencies(file.virtualFile)
|
// initiate configuration refinement, if needed
|
||||||
if (scriptDependencies == ScriptDependencies.Empty) {
|
ScriptDependenciesManager.getInstance(file.project).getRefinedCompilationConfiguration(file.virtualFile)
|
||||||
|
if (!ScriptsCompilationConfigurationUpdater.areDependenciesCached(file)) {
|
||||||
showNotification(
|
showNotification(
|
||||||
file,
|
file,
|
||||||
"Highlighting in scripts is not available until all Script Dependencies are loaded"
|
"Highlighting in scripts is not available until all Script Dependencies are loaded"
|
||||||
|
|||||||
+2
-2
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.psi.KtPsiFactoryKt;
|
|||||||
import org.jetbrains.kotlin.platform.TargetPlatform;
|
import org.jetbrains.kotlin.platform.TargetPlatform;
|
||||||
import org.jetbrains.kotlin.platform.SimplePlatform;
|
import org.jetbrains.kotlin.platform.SimplePlatform;
|
||||||
import org.jetbrains.kotlin.scripting.definitions.DefinitionsKt;
|
import org.jetbrains.kotlin.scripting.definitions.DefinitionsKt;
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition;
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition;
|
||||||
|
|
||||||
public class TargetPlatformDetector {
|
public class TargetPlatformDetector {
|
||||||
public static final TargetPlatformDetector INSTANCE = new TargetPlatformDetector();
|
public static final TargetPlatformDetector INSTANCE = new TargetPlatformDetector();
|
||||||
@@ -62,7 +62,7 @@ public class TargetPlatformDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (file.isScript()) {
|
if (file.isScript()) {
|
||||||
KotlinScriptDefinition scriptDefinition = DefinitionsKt.scriptDefinition(file);
|
ScriptDefinition scriptDefinition = DefinitionsKt.findScriptDefinition(file);
|
||||||
if (scriptDefinition != null) {
|
if (scriptDefinition != null) {
|
||||||
String platformNameFromScriptDefinition = scriptDefinition.getPlatform();
|
String platformNameFromScriptDefinition = scriptDefinition.getPlatform();
|
||||||
for (TargetPlatform compilerPlatform : IdePlatformKind.Companion.getAll_PLATFORMS()) {
|
for (TargetPlatform compilerPlatform : IdePlatformKind.Companion.getAll_PLATFORMS()) {
|
||||||
|
|||||||
@@ -71,7 +71,8 @@ object ProjectRootsUtil {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
val scriptDefinition = file.findScriptDefinition(project)
|
val scriptDefinition = file.findScriptDefinition(project)
|
||||||
if (scriptDefinition != null) {
|
if (scriptDefinition != null) {
|
||||||
val scriptScope = scriptDefinition.scriptExpectedLocations
|
// TODO: rewrite to ScriptAcceptedLocation and without legacyDefinition
|
||||||
|
val scriptScope = scriptDefinition.legacyDefinition.scriptExpectedLocations
|
||||||
val includeAll = scriptScope.contains(ScriptExpectedLocation.Everywhere)
|
val includeAll = scriptScope.contains(ScriptExpectedLocation.Everywhere)
|
||||||
|| scriptScope.contains(ScriptExpectedLocation.Project)
|
|| scriptScope.contains(ScriptExpectedLocation.Project)
|
||||||
|| ScratchUtil.isScratch(file)
|
|| ScratchUtil.isScratch(file)
|
||||||
@@ -115,7 +116,8 @@ object ProjectRootsUtil {
|
|||||||
if (ProjectRootManager.getInstance(project).fileIndex.isInContent(file) || ScratchUtil.isScratch(file)) {
|
if (ProjectRootManager.getInstance(project).fileIndex.isInContent(file) || ScratchUtil.isScratch(file)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return file.findScriptDefinition(project)?.scriptExpectedLocations?.contains(ScriptExpectedLocation.Everywhere) == true
|
// TODO: rewrite to ScriptAcceptedLocation and without legacyDefinition
|
||||||
|
return file.findScriptDefinition(project)?.legacyDefinition?.scriptExpectedLocations?.contains(ScriptExpectedLocation.Everywhere) == true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!includeLibraryClasses && !includeLibrarySource) return false
|
if (!includeLibraryClasses && !includeLibrarySource) return false
|
||||||
|
|||||||
+71
-56
@@ -39,11 +39,7 @@ import org.jetbrains.kotlin.idea.caches.project.SdkInfo
|
|||||||
import org.jetbrains.kotlin.idea.caches.project.getScriptRelatedModuleInfo
|
import org.jetbrains.kotlin.idea.caches.project.getScriptRelatedModuleInfo
|
||||||
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
||||||
import org.jetbrains.kotlin.script.ScriptTemplatesProvider
|
import org.jetbrains.kotlin.script.ScriptTemplatesProvider
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.*
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinitionAdapterFromNewAPI
|
|
||||||
import org.jetbrains.kotlin.scripting.definitions.LazyScriptDefinitionProvider
|
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider
|
|
||||||
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.flattenTo
|
import org.jetbrains.kotlin.utils.addToStdlib.flattenTo
|
||||||
@@ -53,35 +49,33 @@ import java.util.concurrent.locks.ReentrantReadWriteLock
|
|||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
import kotlin.script.dependencies.Environment
|
import kotlin.script.dependencies.Environment
|
||||||
import kotlin.script.dependencies.ScriptContents
|
import kotlin.script.dependencies.ScriptContents
|
||||||
import kotlin.script.experimental.api.KotlinType
|
|
||||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||||
import kotlin.script.experimental.dependencies.asSuccess
|
import kotlin.script.experimental.dependencies.asSuccess
|
||||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
import kotlin.script.experimental.host.configurationDependencies
|
import kotlin.script.experimental.host.configurationDependencies
|
||||||
import kotlin.script.experimental.host.createCompilationConfigurationFromTemplate
|
|
||||||
import kotlin.script.experimental.jvm.JvmDependency
|
import kotlin.script.experimental.jvm.JvmDependency
|
||||||
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrStdlib
|
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrStdlib
|
||||||
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
||||||
|
|
||||||
class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinitionProvider() {
|
class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinitionProvider() {
|
||||||
private var definitionsByContributor = mutableMapOf<ScriptDefinitionContributor, List<KotlinScriptDefinition>>()
|
private var definitionsBySource = mutableMapOf<ScriptDefinitionsSource, List<ScriptDefinition>>()
|
||||||
private var definitions: List<KotlinScriptDefinition>? = null
|
private var definitions: List<ScriptDefinition>? = null
|
||||||
|
|
||||||
private val failedContributorsHashes = HashSet<Int>()
|
private val failedContributorsHashes = HashSet<Int>()
|
||||||
|
|
||||||
private val scriptDefinitionsCacheLock = ReentrantReadWriteLock()
|
private val scriptDefinitionsCacheLock = ReentrantReadWriteLock()
|
||||||
private val scriptDefinitionsCache = SLRUMap<String, KotlinScriptDefinition>(10, 10)
|
private val scriptDefinitionsCache = SLRUMap<String, ScriptDefinition>(10, 10)
|
||||||
|
|
||||||
override fun findScriptDefinition(fileName: String): KotlinScriptDefinition? {
|
override fun findDefinition(fileName: String): ScriptDefinition? {
|
||||||
if (nonScriptFileName(fileName)) return null
|
if (nonScriptFileName(fileName)) return null
|
||||||
if (!isReady()) return null
|
if (!isReady()) return null
|
||||||
|
|
||||||
val cached = scriptDefinitionsCacheLock.write { scriptDefinitionsCache.get(fileName) }
|
val cached = scriptDefinitionsCacheLock.write { scriptDefinitionsCache.get(fileName) }
|
||||||
if (cached != null) return cached
|
if (cached != null) return cached
|
||||||
|
|
||||||
val definition = super.findScriptDefinition(fileName) ?: return null
|
val definition = super.findDefinition(fileName) ?: return null
|
||||||
|
|
||||||
scriptDefinitionsCacheLock.write {
|
scriptDefinitionsCacheLock.write {
|
||||||
scriptDefinitionsCache.put(fileName, definition)
|
scriptDefinitionsCache.put(fileName, definition)
|
||||||
@@ -90,48 +84,43 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit
|
|||||||
return definition
|
return definition
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reloadDefinitionsBy(contributor: ScriptDefinitionContributor) = lock.write {
|
override fun findScriptDefinition(fileName: String): KotlinScriptDefinition? = findDefinition(fileName)?.legacyDefinition
|
||||||
|
|
||||||
|
fun reloadDefinitionsBy(source: ScriptDefinitionsSource) = lock.write {
|
||||||
if (definitions == null) return // not loaded yet
|
if (definitions == null) return // not loaded yet
|
||||||
|
|
||||||
if (contributor !in definitionsByContributor) error("Unknown contributor: ${contributor.id}")
|
if (source !in definitionsBySource) error("Unknown script definition source: $source")
|
||||||
|
|
||||||
definitionsByContributor[contributor] = contributor.safeGetDefinitions()
|
definitionsBySource[source] = source.safeGetDefinitions()
|
||||||
|
|
||||||
definitions = definitionsByContributor.values.flattenTo(mutableListOf())
|
definitions = definitionsBySource.values.flattenTo(mutableListOf())
|
||||||
|
|
||||||
updateDefinitions()
|
updateDefinitions()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDefinitionsBy(contributor: ScriptDefinitionContributor): List<KotlinScriptDefinition> = lock.write {
|
override val currentDefinitions
|
||||||
if (definitions == null) return emptyList() // not loaded yet
|
|
||||||
|
|
||||||
if (contributor !in definitionsByContributor) error("Unknown contributor: ${contributor.id}")
|
|
||||||
|
|
||||||
return definitionsByContributor[contributor] ?: emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
override val currentDefinitions: Sequence<KotlinScriptDefinition>
|
|
||||||
get() =
|
get() =
|
||||||
(definitions ?: kotlin.run {
|
(definitions ?: kotlin.run {
|
||||||
reloadScriptDefinitions()
|
reloadScriptDefinitions()
|
||||||
definitions!!
|
definitions!!
|
||||||
}).asSequence().filter { KotlinScriptingSettings.getInstance(project).isScriptDefinitionEnabled(it) }
|
}).asSequence().filter { KotlinScriptingSettings.getInstance(project).isScriptDefinitionEnabled(it) }
|
||||||
|
|
||||||
private fun getContributors(): List<ScriptDefinitionContributor> {
|
private fun getSources(): List<ScriptDefinitionsSource> {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
val fromDeprecatedEP = Extensions.getArea(project).getExtensionPoint(ScriptTemplatesProvider.EP_NAME).extensions.toList()
|
val fromDeprecatedEP = Extensions.getArea(project).getExtensionPoint(ScriptTemplatesProvider.EP_NAME).extensions.toList()
|
||||||
.map(::ScriptTemplatesProviderAdapter)
|
.map { ScriptTemplatesProviderAdapter(it).asSource() }
|
||||||
val fromNewEp = Extensions.getArea(project).getExtensionPoint(ScriptDefinitionContributor.EP_NAME).extensions.toList()
|
val fromNewEp = Extensions.getArea(project).getExtensionPoint(ScriptDefinitionContributor.EP_NAME).extensions.toList()
|
||||||
|
.map { it.asSource() }
|
||||||
return fromNewEp.dropLast(1) + fromDeprecatedEP + fromNewEp.last()
|
return fromNewEp.dropLast(1) + fromDeprecatedEP + fromNewEp.last()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reloadScriptDefinitions() = lock.write {
|
fun reloadScriptDefinitions() = lock.write {
|
||||||
for (contributor in getContributors()) {
|
for (source in getSources()) {
|
||||||
val definitions = contributor.safeGetDefinitions()
|
val definitions = source.safeGetDefinitions()
|
||||||
definitionsByContributor[contributor] = definitions
|
definitionsBySource[source] = definitions
|
||||||
}
|
}
|
||||||
|
|
||||||
definitions = definitionsByContributor.values.flattenTo(mutableListOf())
|
definitions = definitionsBySource.values.flattenTo(mutableListOf())
|
||||||
|
|
||||||
updateDefinitions()
|
updateDefinitions()
|
||||||
}
|
}
|
||||||
@@ -140,7 +129,7 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit
|
|||||||
updateDefinitions()
|
updateDefinitions()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllDefinitions(): List<KotlinScriptDefinition> {
|
fun getAllDefinitions(): List<ScriptDefinition> {
|
||||||
return definitions ?: kotlin.run {
|
return definitions ?: kotlin.run {
|
||||||
reloadScriptDefinitions()
|
reloadScriptDefinitions()
|
||||||
definitions!!
|
definitions!!
|
||||||
@@ -148,15 +137,16 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun isReady(): Boolean {
|
fun isReady(): Boolean {
|
||||||
return definitionsByContributor.keys.all { contributor ->
|
return definitionsBySource.keys.all { source ->
|
||||||
contributor.isReady()
|
// TODO: implement another API for readiness checking
|
||||||
|
(source as? ScriptDefinitionContributor)?.isReady() != false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDefaultScriptDefinition(): KotlinScriptDefinition {
|
override fun getDefaultDefinition(): ScriptDefinition {
|
||||||
val standardScriptDefinitionContributor = ScriptDefinitionContributor.find<StandardScriptDefinitionContributor>(project)
|
val standardScriptDefinitionContributor = ScriptDefinitionContributor.find<StandardScriptDefinitionContributor>(project)
|
||||||
?: error("StandardScriptDefinitionContributor should be registered is plugin.xml")
|
?: error("StandardScriptDefinitionContributor should be registered is plugin.xml")
|
||||||
return standardScriptDefinitionContributor.getDefinitions().last()
|
return ScriptDefinition.FromLegacy(getScriptingHostConfiguration(), standardScriptDefinitionContributor.getDefinitions().last())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateDefinitions() {
|
private fun updateDefinitions() {
|
||||||
@@ -187,7 +177,7 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit
|
|||||||
scriptDefinitionsCacheLock.write { scriptDefinitionsCache.clear() }
|
scriptDefinitionsCacheLock.write { scriptDefinitionsCache.clear() }
|
||||||
|
|
||||||
// TODO: clear by script type/definition
|
// TODO: clear by script type/definition
|
||||||
ServiceManager.getService(project, ScriptDependenciesCache::class.java).clear()
|
ServiceManager.getService(project, ScriptsCompilationConfigurationCache::class.java).clear()
|
||||||
|
|
||||||
ApplicationManager.getApplication().invokeLater {
|
ApplicationManager.getApplication().invokeLater {
|
||||||
if (!project.isDisposed) {
|
if (!project.isDisposed) {
|
||||||
@@ -196,9 +186,9 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ScriptDefinitionContributor.safeGetDefinitions(): List<KotlinScriptDefinition> {
|
private fun ScriptDefinitionsSource.safeGetDefinitions(): List<ScriptDefinition> {
|
||||||
if (!failedContributorsHashes.contains(this@safeGetDefinitions.hashCode())) try {
|
if (!failedContributorsHashes.contains(this@safeGetDefinitions.hashCode())) try {
|
||||||
return getDefinitions()
|
return definitions.toList()
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
// reporting failed loading only once
|
// reporting failed loading only once
|
||||||
LOG.error("[kts] cannot load script definitions using $this", t)
|
LOG.error("[kts] cannot load script definitions using $this", t)
|
||||||
@@ -207,6 +197,15 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit
|
|||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("unused") // used in the 182/as33 bunches
|
||||||
|
fun getDefinitionsBy(source: ScriptDefinitionsSource): List<ScriptDefinition> = lock.write {
|
||||||
|
if (definitions == null) return emptyList() // not loaded yet
|
||||||
|
|
||||||
|
if (source !in definitionsBySource) error("Unknown source: ${source::class.java.name}")
|
||||||
|
|
||||||
|
return definitionsBySource[source] ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getInstance(project: Project): ScriptDefinitionsManager =
|
fun getInstance(project: Project): ScriptDefinitionsManager =
|
||||||
ServiceManager.getService(project, ScriptDefinitionProvider::class.java) as ScriptDefinitionsManager
|
ServiceManager.getService(project, ScriptDefinitionProvider::class.java) as ScriptDefinitionsManager
|
||||||
@@ -216,10 +215,11 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit
|
|||||||
|
|
||||||
private val LOG = Logger.getInstance("ScriptTemplatesProviders")
|
private val LOG = Logger.getInstance("ScriptTemplatesProviders")
|
||||||
|
|
||||||
|
// TODO: consider rewriting to return sequence
|
||||||
fun loadDefinitionsFromTemplates(
|
fun loadDefinitionsFromTemplates(
|
||||||
templateClassNames: List<String>,
|
templateClassNames: List<String>,
|
||||||
templateClasspath: List<File>,
|
templateClasspath: List<File>,
|
||||||
environment: Environment = emptyMap(),
|
baseHostConfiguration: ScriptingHostConfiguration,
|
||||||
// TODO: need to provide a way to specify this in compiler/repl .. etc
|
// TODO: need to provide a way to specify this in compiler/repl .. etc
|
||||||
/*
|
/*
|
||||||
* Allows to specify additional jars needed for DependenciesResolver (and not script template).
|
* Allows to specify additional jars needed for DependenciesResolver (and not script template).
|
||||||
@@ -227,7 +227,7 @@ fun loadDefinitionsFromTemplates(
|
|||||||
* i.e. gradle resolver may depend on some jars that 'built.gradle.kts' files should not depend on.
|
* i.e. gradle resolver may depend on some jars that 'built.gradle.kts' files should not depend on.
|
||||||
*/
|
*/
|
||||||
additionalResolverClasspath: List<File> = emptyList()
|
additionalResolverClasspath: List<File> = emptyList()
|
||||||
): List<KotlinScriptDefinition> {
|
): List<ScriptDefinition> {
|
||||||
val classpath = templateClasspath + additionalResolverClasspath
|
val classpath = templateClasspath + additionalResolverClasspath
|
||||||
LOG.info("[kts] loading script definitions $templateClassNames using cp: ${classpath.joinToString(File.pathSeparator)}")
|
LOG.info("[kts] loading script definitions $templateClassNames using cp: ${classpath.joinToString(File.pathSeparator)}")
|
||||||
val baseLoader = ScriptDefinitionContributor::class.java.classLoader
|
val baseLoader = ScriptDefinitionContributor::class.java.classLoader
|
||||||
@@ -240,24 +240,13 @@ fun loadDefinitionsFromTemplates(
|
|||||||
val template = loader.loadClass(templateClassName).kotlin
|
val template = loader.loadClass(templateClassName).kotlin
|
||||||
when {
|
when {
|
||||||
template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateDefinition>() != null -> {
|
template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateDefinition>() != null -> {
|
||||||
KotlinScriptDefinitionFromAnnotatedTemplate(
|
ScriptDefinition.FromLegacyTemplate(baseHostConfiguration, template, templateClasspath)
|
||||||
template,
|
|
||||||
environment,
|
|
||||||
templateClasspath
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
template.annotations.firstIsInstanceOrNull<kotlin.script.experimental.annotations.KotlinScript>() != null -> {
|
template.annotations.firstIsInstanceOrNull<kotlin.script.experimental.annotations.KotlinScript>() != null -> {
|
||||||
val hostConfiguration = ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration) {
|
val hostConfiguration = ScriptingHostConfiguration(baseHostConfiguration) {
|
||||||
configurationDependencies(JvmDependency(classpath))
|
configurationDependencies(JvmDependency(classpath))
|
||||||
}
|
}
|
||||||
KotlinScriptDefinitionAdapterFromNewAPI(
|
ScriptDefinition.FromTemplate(hostConfiguration, template, ScriptDefinition::class)
|
||||||
createCompilationConfigurationFromTemplate(
|
|
||||||
KotlinType(
|
|
||||||
template
|
|
||||||
), hostConfiguration, KotlinScriptDefinition::class
|
|
||||||
),
|
|
||||||
hostConfiguration
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
LOG.warn("[kts] cannot find a valid script definition annotation on the class $template")
|
LOG.warn("[kts] cannot find a valid script definition annotation on the class $template")
|
||||||
@@ -276,10 +265,16 @@ fun loadDefinitionsFromTemplates(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("migrating to new configuration refinement: use ScriptDefinitionsSource internally and kotlin.script.experimental.intellij.ScriptDefinitionsProvider as a providing extension point")
|
||||||
interface ScriptDefinitionContributor {
|
interface ScriptDefinitionContributor {
|
||||||
|
|
||||||
|
@Deprecated("migrating to new configuration refinement: drop usages")
|
||||||
val id: String
|
val id: String
|
||||||
|
|
||||||
|
@Deprecated("migrating to new configuration refinement: use ScriptDefinitionsSource instead")
|
||||||
fun getDefinitions(): List<KotlinScriptDefinition>
|
fun getDefinitions(): List<KotlinScriptDefinition>
|
||||||
|
|
||||||
|
@Deprecated("migrating to new configuration refinement: drop usages")
|
||||||
fun isReady() = true
|
fun isReady() = true
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -289,9 +284,29 @@ interface ScriptDefinitionContributor {
|
|||||||
inline fun <reified T> find(project: Project) =
|
inline fun <reified T> find(project: Project) =
|
||||||
Extensions.getArea(project).getExtensionPoint(ScriptDefinitionContributor.EP_NAME).extensions.filterIsInstance<T>().firstOrNull()
|
Extensions.getArea(project).getExtensionPoint(ScriptDefinitionContributor.EP_NAME).extensions.filterIsInstance<T>().firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("migrating to new configuration refinement: use ScriptDefinitionsSource directly instead")
|
||||||
|
interface ScriptDefinitionSourceAsContributor : ScriptDefinitionContributor, ScriptDefinitionsSource {
|
||||||
|
|
||||||
|
override fun getDefinitions(): List<KotlinScriptDefinition> = definitions.map { it.legacyDefinition }.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("migrating to new configuration refinement: convert all contributors to ScriptDefinitionsSource/ScriptDefinitionsProvider")
|
||||||
|
class ScriptDefinitionSourceFromContributor(
|
||||||
|
val contributor: ScriptDefinitionContributor,
|
||||||
|
val hostConfiguration: ScriptingHostConfiguration = defaultJvmScriptingHostConfiguration
|
||||||
|
) : ScriptDefinitionsSource {
|
||||||
|
override val definitions: Sequence<ScriptDefinition>
|
||||||
|
get() =
|
||||||
|
if (contributor is ScriptDefinitionsSource) contributor.definitions
|
||||||
|
else contributor.getDefinitions().asSequence().map { ScriptDefinition.FromLegacy(hostConfiguration, it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ScriptDefinitionContributor.asSource(): ScriptDefinitionsSource =
|
||||||
|
if (this is ScriptDefinitionsSource) this
|
||||||
|
else ScriptDefinitionSourceFromContributor(this)
|
||||||
|
|
||||||
class StandardScriptDefinitionContributor(project: Project) : ScriptDefinitionContributor {
|
class StandardScriptDefinitionContributor(project: Project) : ScriptDefinitionContributor {
|
||||||
private val standardIdeScriptDefinition = StandardIdeScriptDefinition(project)
|
private val standardIdeScriptDefinition = StandardIdeScriptDefinition(project)
|
||||||
|
|
||||||
|
|||||||
+27
-3
@@ -18,8 +18,9 @@ package org.jetbrains.kotlin.idea.core.script
|
|||||||
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.idea.core.util.*
|
import org.jetbrains.kotlin.idea.core.util.*
|
||||||
import java.io.DataInput
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
import java.io.DataOutput
|
import java.io.*
|
||||||
|
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||||
|
|
||||||
var VirtualFile.scriptDependencies: ScriptDependencies? by cachedFileAttribute(
|
var VirtualFile.scriptDependencies: ScriptDependencies? by cachedFileAttribute(
|
||||||
@@ -43,4 +44,27 @@ var VirtualFile.scriptDependencies: ScriptDependencies? by cachedFileAttribute(
|
|||||||
writeFileList(sources)
|
writeFileList(sources)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var VirtualFile.scriptCompilationConfiguration: ScriptCompilationConfiguration? by cachedFileAttribute(
|
||||||
|
name = "kotlin-script-compilation-configuration",
|
||||||
|
version = 1,
|
||||||
|
read = {
|
||||||
|
val size = readInt()
|
||||||
|
val bytes = ByteArray(size)
|
||||||
|
read(bytes, 0, size)
|
||||||
|
val bis = ByteArrayInputStream(bytes)
|
||||||
|
ObjectInputStream(bis).use { ois ->
|
||||||
|
ois.readObject() as ScriptCompilationConfiguration
|
||||||
|
}
|
||||||
|
},
|
||||||
|
write = {
|
||||||
|
val os = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(os).use { oos ->
|
||||||
|
oos.writeObject((it as? ScriptCompilationConfigurationWrapper.FromCompilationConfiguration)?.configuration)
|
||||||
|
}
|
||||||
|
val bytes = os.toByteArray()
|
||||||
|
writeInt(bytes.size)
|
||||||
|
write(bytes)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|||||||
+32
-33
@@ -30,8 +30,10 @@ import org.jetbrains.annotations.TestOnly
|
|||||||
import org.jetbrains.kotlin.idea.caches.project.getAllProjectSdks
|
import org.jetbrains.kotlin.idea.caches.project.getAllProjectSdks
|
||||||
import org.jetbrains.kotlin.idea.core.script.dependencies.SyncScriptDependenciesLoader
|
import org.jetbrains.kotlin.idea.core.script.dependencies.SyncScriptDependenciesLoader
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
import kotlin.script.experimental.api.valueOrNull
|
||||||
|
|
||||||
|
|
||||||
// NOTE: this service exists exclusively because ScriptDependencyManager
|
// NOTE: this service exists exclusively because ScriptDependencyManager
|
||||||
@@ -39,18 +41,21 @@ import kotlin.script.experimental.dependencies.ScriptDependencies
|
|||||||
class IdeScriptDependenciesProvider(
|
class IdeScriptDependenciesProvider(
|
||||||
private val scriptDependenciesManager: ScriptDependenciesManager
|
private val scriptDependenciesManager: ScriptDependenciesManager
|
||||||
) : ScriptDependenciesProvider {
|
) : ScriptDependenciesProvider {
|
||||||
override fun getScriptDependencies(file: VirtualFile): ScriptDependencies? {
|
override fun getScriptConfigurationResult(file: VirtualFile): ScriptCompilationConfigurationResult? = scriptDependenciesManager.getRefinedCompilationConfiguration(file)
|
||||||
return scriptDependenciesManager.getScriptDependencies(file)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: rename and provide alias for compatibility - this is not only about dependencies anymore
|
||||||
class ScriptDependenciesManager internal constructor(
|
class ScriptDependenciesManager internal constructor(
|
||||||
private val cacheUpdater: ScriptDependenciesUpdater,
|
private val cacheUpdater: ScriptsCompilationConfigurationUpdater,
|
||||||
private val cache: ScriptDependenciesCache
|
private val cache: ScriptsCompilationConfigurationCache
|
||||||
) {
|
) {
|
||||||
fun getScriptClasspath(file: VirtualFile): List<VirtualFile> = toVfsRoots(cacheUpdater.getCurrentDependencies(file).classpath)
|
fun getScriptClasspath(file: VirtualFile): List<VirtualFile> =
|
||||||
fun getScriptDependencies(file: VirtualFile): ScriptDependencies = cacheUpdater.getCurrentDependencies(file)
|
toVfsRoots(cacheUpdater.getCurrentCompilationConfiguration(file)?.valueOrNull()?.dependenciesClassPath.orEmpty())
|
||||||
fun getScriptSdk(file: VirtualFile): Sdk? = getScriptSdk(getScriptDependencies(file))
|
|
||||||
|
fun getRefinedCompilationConfiguration(file: VirtualFile): ScriptCompilationConfigurationResult? =
|
||||||
|
cacheUpdater.getCurrentCompilationConfiguration(file)
|
||||||
|
|
||||||
|
fun getScriptSdk(file: VirtualFile): Sdk? = Companion.getScriptSdk(getRefinedCompilationConfiguration(file)?.valueOrNull())
|
||||||
|
|
||||||
fun getScriptDependenciesClassFilesScope(file: VirtualFile) = cache.scriptDependenciesClassFilesScope(file)
|
fun getScriptDependenciesClassFilesScope(file: VirtualFile) = cache.scriptDependenciesClassFilesScope(file)
|
||||||
|
|
||||||
@@ -67,35 +72,29 @@ class ScriptDependenciesManager internal constructor(
|
|||||||
fun getInstance(project: Project): ScriptDependenciesManager =
|
fun getInstance(project: Project): ScriptDependenciesManager =
|
||||||
ServiceManager.getService(project, ScriptDependenciesManager::class.java)
|
ServiceManager.getService(project, ScriptDependenciesManager::class.java)
|
||||||
|
|
||||||
fun getScriptSdk(dependencies: ScriptDependencies): Sdk? {
|
fun getScriptSdk(compilationConfiguration: ScriptCompilationConfigurationWrapper?): Sdk? {
|
||||||
// workaround for mismatched gradle wrapper and plugin version
|
// workaround for mismatched gradle wrapper and plugin version
|
||||||
try {
|
val javaHome = try {
|
||||||
val javaHome = dependencies.javaHome
|
compilationConfiguration?.javaHome?.let { VfsUtil.findFileByIoFile(it, true) }
|
||||||
?.let { VfsUtil.findFileByIoFile(it, true) }
|
|
||||||
?: return null
|
|
||||||
|
|
||||||
return getAllProjectSdks().find { it.homeDirectory == javaHome }
|
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
return null
|
null
|
||||||
}
|
} ?: return null
|
||||||
|
|
||||||
|
return getAllProjectSdks().find { it.homeDirectory == javaHome }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getScriptDefaultSdk(project: Project): Sdk? {
|
|
||||||
val projectSdk = getProjectSdk(project)
|
|
||||||
if (projectSdk != null) return projectSdk
|
|
||||||
|
|
||||||
val anyJavaSdk = getAllProjectSdks().find { it.canBeUsedForScript() }
|
fun getScriptDefaultSdk(project: Project): Sdk? =
|
||||||
if (anyJavaSdk != null) {
|
getProjectSdk(project)
|
||||||
return anyJavaSdk
|
?: getAllProjectSdks().find { it.canBeUsedForScript() }
|
||||||
}
|
?: run {
|
||||||
|
log.warn(
|
||||||
log.warn(
|
"Default Script SDK is null: " +
|
||||||
"Default Script SDK is null: " +
|
"projectSdk = ${ProjectRootManager.getInstance(project).projectSdk}, " +
|
||||||
"projectSdk = ${ProjectRootManager.getInstance(project).projectSdk}, " +
|
"all sdks = ${getAllProjectSdks().joinToString("; ")}"
|
||||||
"all sdks = ${getAllProjectSdks().joinToString("\n")}"
|
)
|
||||||
)
|
null
|
||||||
return null
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun getProjectSdk(project: Project) = ProjectRootManager.getInstance(project).projectSdk?.takeIf { it.canBeUsedForScript() }
|
fun getProjectSdk(project: Project) = ProjectRootManager.getInstance(project).projectSdk?.takeIf { it.canBeUsedForScript() }
|
||||||
|
|
||||||
|
|||||||
+11
-11
@@ -16,7 +16,7 @@ import com.intellij.ui.EditorNotificationPanel
|
|||||||
import com.intellij.ui.HyperlinkLabel
|
import com.intellij.ui.HyperlinkLabel
|
||||||
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
||||||
import org.jetbrains.kotlin.psi.UserDataProperty
|
import org.jetbrains.kotlin.psi.UserDataProperty
|
||||||
import kotlin.script.experimental.dependencies.DependenciesResolver.ResolveResult
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||||
|
|
||||||
fun VirtualFile.removeScriptDependenciesNotificationPanel(project: Project) {
|
fun VirtualFile.removeScriptDependenciesNotificationPanel(project: Project) {
|
||||||
withSelectedEditor(project) { manager ->
|
withSelectedEditor(project) { manager ->
|
||||||
@@ -28,14 +28,14 @@ fun VirtualFile.removeScriptDependenciesNotificationPanel(project: Project) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun VirtualFile.addScriptDependenciesNotificationPanel(
|
fun VirtualFile.addScriptDependenciesNotificationPanel(
|
||||||
resolveResult: ResolveResult,
|
compilationConfigurationResult: ScriptCompilationConfigurationResult?,
|
||||||
project: Project,
|
project: Project,
|
||||||
onClick: (ResolveResult) -> Unit
|
onClick: (ScriptCompilationConfigurationResult?) -> Unit
|
||||||
) {
|
) {
|
||||||
withSelectedEditor(project) { manager ->
|
withSelectedEditor(project) { manager ->
|
||||||
val existingPanel = notificationPanel
|
val existingPanel = notificationPanel
|
||||||
if (existingPanel != null) {
|
if (existingPanel != null) {
|
||||||
if (existingPanel.resolveResult.dependencies == resolveResult.dependencies) {
|
if (existingPanel.compilationConfigurationResult == compilationConfigurationResult) {
|
||||||
return@withSelectedEditor
|
return@withSelectedEditor
|
||||||
}
|
}
|
||||||
notificationPanel?.let {
|
notificationPanel?.let {
|
||||||
@@ -43,7 +43,7 @@ fun VirtualFile.addScriptDependenciesNotificationPanel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val panel = NewScriptDependenciesNotificationPanel(onClick, resolveResult, project)
|
val panel = NewScriptDependenciesNotificationPanel(onClick, compilationConfigurationResult, project)
|
||||||
notificationPanel = panel
|
notificationPanel = panel
|
||||||
manager.addTopComponent(this, panel)
|
manager.addTopComponent(this, panel)
|
||||||
}
|
}
|
||||||
@@ -61,19 +61,19 @@ private fun VirtualFile.withSelectedEditor(project: Project, f: FileEditor.(File
|
|||||||
private var FileEditor.notificationPanel: NewScriptDependenciesNotificationPanel? by UserDataProperty<FileEditor, NewScriptDependenciesNotificationPanel>(Key.create("script.dependencies.panel"))
|
private var FileEditor.notificationPanel: NewScriptDependenciesNotificationPanel? by UserDataProperty<FileEditor, NewScriptDependenciesNotificationPanel>(Key.create("script.dependencies.panel"))
|
||||||
|
|
||||||
private class NewScriptDependenciesNotificationPanel(
|
private class NewScriptDependenciesNotificationPanel(
|
||||||
onClick: (ResolveResult) -> Unit,
|
onClick: (ScriptCompilationConfigurationResult?) -> Unit,
|
||||||
val resolveResult: ResolveResult,
|
val compilationConfigurationResult: ScriptCompilationConfigurationResult?,
|
||||||
project: Project
|
project: Project
|
||||||
) : EditorNotificationPanel() {
|
) : EditorNotificationPanel() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setText("There are new script dependencies available.")
|
setText("There is a new script context available.")
|
||||||
createComponentActionLabel("Apply dependencies") {
|
createComponentActionLabel("Apply context") {
|
||||||
onClick(resolveResult)
|
onClick(compilationConfigurationResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
createComponentActionLabel("Enable auto-reload") {
|
createComponentActionLabel("Enable auto-reload") {
|
||||||
onClick(resolveResult)
|
onClick(compilationConfigurationResult)
|
||||||
KotlinScriptingSettings.getInstance(project).isAutoReloadEnabled = true
|
KotlinScriptingSettings.getInstance(project).isAutoReloadEnabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-9
@@ -6,17 +6,25 @@
|
|||||||
package org.jetbrains.kotlin.idea.core.script
|
package org.jetbrains.kotlin.idea.core.script
|
||||||
|
|
||||||
import org.jetbrains.kotlin.script.ScriptTemplatesProvider
|
import org.jetbrains.kotlin.script.ScriptTemplatesProvider
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.getEnvironment
|
||||||
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
|
class ScriptTemplatesProviderAdapter(private val templatesProvider: ScriptTemplatesProvider) : ScriptDefinitionSourceAsContributor {
|
||||||
|
|
||||||
class ScriptTemplatesProviderAdapter(private val templatesProvider: ScriptTemplatesProvider) :
|
|
||||||
ScriptDefinitionContributor {
|
|
||||||
override val id: String
|
override val id: String
|
||||||
get() = templatesProvider.id
|
get() = templatesProvider.id
|
||||||
|
|
||||||
override fun getDefinitions(): List<KotlinScriptDefinition> {
|
override val definitions: Sequence<ScriptDefinition>
|
||||||
return loadDefinitionsFromTemplates(
|
get() =
|
||||||
templatesProvider.templateClassNames.toList(), templatesProvider.templateClasspath,
|
loadDefinitionsFromTemplates(
|
||||||
templatesProvider.environment.orEmpty(), templatesProvider.additionalResolverClasspath
|
templatesProvider.templateClassNames.toList(), templatesProvider.templateClasspath,
|
||||||
)
|
ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration) {
|
||||||
}
|
getEnvironment {
|
||||||
|
templatesProvider.environment
|
||||||
|
}
|
||||||
|
},
|
||||||
|
templatesProvider.additionalResolverClasspath
|
||||||
|
).asSequence()
|
||||||
}
|
}
|
||||||
+20
-17
@@ -29,15 +29,17 @@ import com.intellij.util.containers.SLRUMap
|
|||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
import kotlin.properties.ReadOnlyProperty
|
import kotlin.properties.ReadOnlyProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
import kotlin.reflect.KProperty0
|
import kotlin.reflect.KProperty0
|
||||||
import kotlin.reflect.jvm.isAccessible
|
import kotlin.reflect.jvm.isAccessible
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
import kotlin.script.experimental.api.valueOrNull
|
||||||
|
|
||||||
class ScriptDependenciesCache(private val project: Project) {
|
class ScriptsCompilationConfigurationCache(private val project: Project) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val MAX_SCRIPTS_CACHED = 50
|
const val MAX_SCRIPTS_CACHED = 50
|
||||||
@@ -45,10 +47,10 @@ class ScriptDependenciesCache(private val project: Project) {
|
|||||||
|
|
||||||
private val cacheLock = ReentrantReadWriteLock()
|
private val cacheLock = ReentrantReadWriteLock()
|
||||||
|
|
||||||
private val scriptDependenciesCache = SLRUCacheWithLock<ScriptDependencies>()
|
private val scriptDependenciesCache = SLRUCacheWithLock<ScriptCompilationConfigurationResult>()
|
||||||
private val scriptsModificationStampsCache = SLRUCacheWithLock<Long>()
|
private val scriptsModificationStampsCache = SLRUCacheWithLock<Long>()
|
||||||
|
|
||||||
operator fun get(virtualFile: VirtualFile): ScriptDependencies? = scriptDependenciesCache.get(virtualFile)
|
operator fun get(virtualFile: VirtualFile): ScriptCompilationConfigurationResult? = scriptDependenciesCache.get(virtualFile)
|
||||||
|
|
||||||
fun shouldRunDependenciesUpdate(file: VirtualFile): Boolean {
|
fun shouldRunDependenciesUpdate(file: VirtualFile): Boolean {
|
||||||
return scriptsModificationStampsCache.replace(file, file.modificationStamp) != file.modificationStamp
|
return scriptsModificationStampsCache.replace(file, file.modificationStamp) != file.modificationStamp
|
||||||
@@ -58,10 +60,10 @@ class ScriptDependenciesCache(private val project: Project) {
|
|||||||
|
|
||||||
fun scriptDependenciesClassFilesScope(file: VirtualFile): GlobalSearchScope {
|
fun scriptDependenciesClassFilesScope(file: VirtualFile): GlobalSearchScope {
|
||||||
return scriptsDependenciesClasspathScopeCache.getOrPut(file) {
|
return scriptsDependenciesClasspathScopeCache.getOrPut(file) {
|
||||||
val dependencies = scriptDependenciesCache.get(file) ?: return@getOrPut GlobalSearchScope.EMPTY_SCOPE
|
val compilationConfiguration = scriptDependenciesCache.get(file)?.valueOrNull() ?: return@getOrPut GlobalSearchScope.EMPTY_SCOPE
|
||||||
val roots = dependencies.classpath
|
val roots = compilationConfiguration.dependenciesClassPath
|
||||||
|
|
||||||
val sdk = ScriptDependenciesManager.getScriptSdk(dependencies)
|
val sdk = ScriptDependenciesManager.getScriptSdk(compilationConfiguration)
|
||||||
|
|
||||||
@Suppress("FoldInitializerAndIfToElvis")
|
@Suppress("FoldInitializerAndIfToElvis")
|
||||||
if (sdk == null) {
|
if (sdk == null) {
|
||||||
@@ -86,7 +88,8 @@ class ScriptDependenciesCache(private val project: Project) {
|
|||||||
.filter { it != ScriptDependenciesManager.getProjectSdk(project) }
|
.filter { it != ScriptDependenciesManager.getProjectSdk(project) }
|
||||||
.flatMap { it.rootProvider.getFiles(OrderRootType.CLASSES).toList() }
|
.flatMap { it.rootProvider.getFiles(OrderRootType.CLASSES).toList() }
|
||||||
|
|
||||||
val scriptDependenciesClasspath = scriptDependenciesCache.getAll().flatMap { it.value.classpath }.distinct()
|
val scriptDependenciesClasspath = scriptDependenciesCache.getAll()
|
||||||
|
.flatMap { it.value.valueOrNull()?.dependenciesClassPath ?: emptyList() }.distinct()
|
||||||
|
|
||||||
sdkFiles + ScriptDependenciesManager.toVfsRoots(scriptDependenciesClasspath)
|
sdkFiles + ScriptDependenciesManager.toVfsRoots(scriptDependenciesClasspath)
|
||||||
}
|
}
|
||||||
@@ -96,7 +99,8 @@ class ScriptDependenciesCache(private val project: Project) {
|
|||||||
.filter { it != ScriptDependenciesManager.getProjectSdk(project) }
|
.filter { it != ScriptDependenciesManager.getProjectSdk(project) }
|
||||||
.flatMap { it.rootProvider.getFiles(OrderRootType.SOURCES).toList() }
|
.flatMap { it.rootProvider.getFiles(OrderRootType.SOURCES).toList() }
|
||||||
|
|
||||||
val scriptDependenciesSources = scriptDependenciesCache.getAll().flatMap { it.value.sources }.distinct()
|
val scriptDependenciesSources = scriptDependenciesCache.getAll()
|
||||||
|
.flatMap { it.value.valueOrNull()?.dependenciesSources ?: emptyList() }.distinct()
|
||||||
sdkSources + ScriptDependenciesManager.toVfsRoots(scriptDependenciesSources)
|
sdkSources + ScriptDependenciesManager.toVfsRoots(scriptDependenciesSources)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,11 +144,10 @@ class ScriptDependenciesCache(private val project: Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasNotCachedRoots(scriptDependencies: ScriptDependencies): Boolean {
|
fun hasNotCachedRoots(compilationConfiguration: ScriptCompilationConfigurationWrapper): Boolean {
|
||||||
return !allSdks.contains(ScriptDependenciesManager.getScriptSdk(scriptDependencies)) ||
|
return !allSdks.contains(ScriptDependenciesManager.getScriptSdk(compilationConfiguration)) ||
|
||||||
!allDependenciesClassFiles.containsAll(ScriptDependenciesManager.toVfsRoots(scriptDependencies.classpath)) ||
|
!allDependenciesClassFiles.containsAll(ScriptDependenciesManager.toVfsRoots(compilationConfiguration.dependenciesClassPath)) ||
|
||||||
!allDependenciesSources.containsAll(ScriptDependenciesManager.toVfsRoots(scriptDependencies.sources))
|
!allDependenciesSources.containsAll(ScriptDependenciesManager.toVfsRoots(compilationConfiguration.dependenciesSources))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
@@ -155,7 +158,7 @@ class ScriptDependenciesCache(private val project: Project) {
|
|||||||
onChange(keys)
|
onChange(keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun save(virtualFile: VirtualFile, new: ScriptDependencies): Boolean {
|
fun save(virtualFile: VirtualFile, new: ScriptCompilationConfigurationResult): Boolean {
|
||||||
val old = scriptDependenciesCache.replace(virtualFile, new)
|
val old = scriptDependenciesCache.replace(virtualFile, new)
|
||||||
val changed = new != old
|
val changed = new != old
|
||||||
if (changed) {
|
if (changed) {
|
||||||
@@ -207,8 +210,8 @@ private class SLRUCacheWithLock<T> {
|
|||||||
private val lock = ReentrantReadWriteLock()
|
private val lock = ReentrantReadWriteLock()
|
||||||
|
|
||||||
val cache = SLRUMap<VirtualFile, T>(
|
val cache = SLRUMap<VirtualFile, T>(
|
||||||
ScriptDependenciesCache.MAX_SCRIPTS_CACHED,
|
ScriptsCompilationConfigurationCache.MAX_SCRIPTS_CACHED,
|
||||||
ScriptDependenciesCache.MAX_SCRIPTS_CACHED
|
ScriptsCompilationConfigurationCache.MAX_SCRIPTS_CACHED
|
||||||
)
|
)
|
||||||
|
|
||||||
fun get(value: VirtualFile): T? = lock.write {
|
fun get(value: VirtualFile): T? = lock.write {
|
||||||
+12
-11
@@ -41,14 +41,15 @@ import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
|||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
|
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.LegacyResolverWrapper
|
import org.jetbrains.kotlin.scripting.resolve.LegacyResolverWrapper
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||||
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
|
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
|
||||||
|
|
||||||
class ScriptDependenciesUpdater(
|
class ScriptsCompilationConfigurationUpdater(
|
||||||
private val project: Project,
|
private val project: Project,
|
||||||
private val cache: ScriptDependenciesCache
|
private val cache: ScriptsCompilationConfigurationCache
|
||||||
) {
|
) {
|
||||||
private val scriptsQueue = Alarm(Alarm.ThreadToUse.SWING_THREAD, project)
|
private val scriptsQueue = Alarm(Alarm.ThreadToUse.SWING_THREAD, project)
|
||||||
private val scriptChangesListenerDelay = 1400
|
private val scriptChangesListenerDelay = 1400
|
||||||
@@ -64,13 +65,13 @@ class ScriptDependenciesUpdater(
|
|||||||
listenForChangesInScripts()
|
listenForChangesInScripts()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCurrentDependencies(file: VirtualFile): ScriptDependencies {
|
fun getCurrentCompilationConfiguration(file: VirtualFile): ScriptCompilationConfigurationResult? {
|
||||||
cache[file]?.let { return it }
|
cache[file]?.let { return it }
|
||||||
|
|
||||||
updateDependencies(file)
|
updateDependencies(file)
|
||||||
makeRootsChangeIfNeeded()
|
makeRootsChangeIfNeeded()
|
||||||
|
|
||||||
return cache[file] ?: ScriptDependencies.Empty
|
return cache[file]
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateDependenciesIfNeeded(files: List<VirtualFile>): Boolean {
|
fun updateDependenciesIfNeeded(files: List<VirtualFile>): Boolean {
|
||||||
@@ -174,15 +175,15 @@ class ScriptDependenciesUpdater(
|
|||||||
return cache[file] != null || file.scriptDependencies != null
|
return cache[file] != null || file.scriptDependencies != null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isAsyncDependencyResolver(scriptDef: KotlinScriptDefinition): Boolean {
|
fun isAsyncDependencyResolver(scriptDef: ScriptDefinition): Boolean =
|
||||||
val dependencyResolver = scriptDef.dependencyResolver
|
scriptDef.asLegacyOrNull<KotlinScriptDefinition>()?.dependencyResolver?.let {
|
||||||
return dependencyResolver is AsyncDependenciesResolver || dependencyResolver is LegacyResolverWrapper
|
it is AsyncDependenciesResolver || it is LegacyResolverWrapper
|
||||||
}
|
} ?: false
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getInstance(project: Project): ScriptDependenciesUpdater =
|
fun getInstance(project: Project): ScriptsCompilationConfigurationUpdater =
|
||||||
ServiceManager.getService(project, ScriptDependenciesUpdater::class.java)
|
ServiceManager.getService(project, ScriptsCompilationConfigurationUpdater::class.java)
|
||||||
|
|
||||||
fun areDependenciesCached(file: KtFile): Boolean {
|
fun areDependenciesCached(file: KtFile): Boolean {
|
||||||
return getInstance(file.project).areDependenciesCached(file.virtualFile)
|
return getInstance(file.project).areDependenciesCached(file.virtualFile)
|
||||||
+9
-32
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.core.script.dependencies
|
package org.jetbrains.kotlin.idea.core.script.dependencies
|
||||||
|
|
||||||
import com.intellij.openapi.application.runReadAction
|
|
||||||
import com.intellij.openapi.progress.EmptyProgressIndicator
|
import com.intellij.openapi.progress.EmptyProgressIndicator
|
||||||
import com.intellij.openapi.progress.ProgressIndicator
|
import com.intellij.openapi.progress.ProgressIndicator
|
||||||
import com.intellij.openapi.progress.Task
|
import com.intellij.openapi.progress.Task
|
||||||
@@ -13,18 +12,16 @@ import com.intellij.openapi.progress.util.BackgroundTaskUtil
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import kotlinx.coroutines.Runnable
|
import kotlinx.coroutines.Runnable
|
||||||
import kotlinx.coroutines.runBlocking
|
import org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationUpdater
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesUpdater
|
|
||||||
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
|
||||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.asResolveFailure
|
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.refineScriptCompilationConfiguration
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
|
|
||||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
|
||||||
|
|
||||||
|
// TODO: rename and provide alias for compatibility - this is not only about dependencies anymore
|
||||||
class AsyncScriptDependenciesLoader internal constructor(project: Project) : ScriptDependenciesLoader(project) {
|
class AsyncScriptDependenciesLoader internal constructor(project: Project) : ScriptDependenciesLoader(project) {
|
||||||
private val lock = ReentrantReadWriteLock()
|
private val lock = ReentrantReadWriteLock()
|
||||||
|
|
||||||
@@ -33,7 +30,7 @@ class AsyncScriptDependenciesLoader internal constructor(project: Project) : Scr
|
|||||||
|
|
||||||
override fun isApplicable(file: VirtualFile): Boolean {
|
override fun isApplicable(file: VirtualFile): Boolean {
|
||||||
val scriptDefinition = file.findScriptDefinition(project) ?: return false
|
val scriptDefinition = file.findScriptDefinition(project) ?: return false
|
||||||
return ScriptDependenciesUpdater.getInstance(project).isAsyncDependencyResolver(scriptDefinition)
|
return ScriptsCompilationConfigurationUpdater.getInstance(project).isAsyncDependencyResolver(scriptDefinition)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadDependencies(file: VirtualFile) {
|
override fun loadDependencies(file: VirtualFile) {
|
||||||
@@ -73,35 +70,15 @@ class AsyncScriptDependenciesLoader internal constructor(project: Project) : Scr
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun runDependenciesUpdate(file: VirtualFile) {
|
private fun runDependenciesUpdate(file: VirtualFile) {
|
||||||
val scriptDef = runReadAction { file.findScriptDefinition(project) } ?: return
|
val scriptDef = file.findScriptDefinition(project) ?: return
|
||||||
|
|
||||||
debug(file) { "start async dependencies loading" }
|
debug(file) { "start async dependencies loading" }
|
||||||
// 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
|
val result = refineScriptCompilationConfiguration(VirtualFileScriptSource(file), scriptDef, project)
|
||||||
// It is more efficient to use one hot daemon consistently than multiple daemon in parallel
|
|
||||||
val result = runBlocking {
|
|
||||||
try {
|
|
||||||
resolveDependencies(file, scriptDef)
|
|
||||||
} catch (t: Throwable) {
|
|
||||||
t.asResolveFailure(scriptDef)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug(file) { "finish async dependencies loading" }
|
debug(file) { "finish async dependencies loading" }
|
||||||
|
|
||||||
processResult(result, file, scriptDef)
|
processRefinedConfiguration(result, file)
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun resolveDependencies(file: VirtualFile, scriptDef: KotlinScriptDefinition): DependenciesResolver.ResolveResult {
|
|
||||||
val dependenciesResolver = scriptDef.dependencyResolver
|
|
||||||
val scriptContents = contentLoader.getScriptContents(scriptDef, file)
|
|
||||||
val environment = contentLoader.getEnvironment(scriptDef)
|
|
||||||
return if (dependenciesResolver is AsyncDependenciesResolver) {
|
|
||||||
dependenciesResolver.resolveAsync(scriptContents, environment)
|
|
||||||
} else {
|
|
||||||
// TODO: shouldn't come here after dropping legacy resolvers, refactor accordingly
|
|
||||||
dependenciesResolver.resolve(scriptContents, environment)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class LoaderBackgroundTask {
|
private inner class LoaderBackgroundTask {
|
||||||
|
|||||||
+16
-3
@@ -7,8 +7,13 @@ package org.jetbrains.kotlin.idea.core.script.dependencies
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.scriptCompilationConfiguration
|
||||||
import org.jetbrains.kotlin.idea.core.script.scriptDependencies
|
import org.jetbrains.kotlin.idea.core.script.scriptDependencies
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
|
||||||
|
import kotlin.script.experimental.api.asSuccess
|
||||||
|
|
||||||
|
// TODO: rename and provide alias for compatibility - this is not only about dependencies anymore
|
||||||
class FromFileAttributeScriptDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) {
|
class FromFileAttributeScriptDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) {
|
||||||
|
|
||||||
override fun isApplicable(file: VirtualFile): Boolean {
|
override fun isApplicable(file: VirtualFile): Boolean {
|
||||||
@@ -16,9 +21,17 @@ class FromFileAttributeScriptDependenciesLoader(project: Project) : ScriptDepend
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun loadDependencies(file: VirtualFile) {
|
override fun loadDependencies(file: VirtualFile) {
|
||||||
val deserializedDependencies = file.scriptDependencies ?: return
|
file.scriptCompilationConfiguration?.let {
|
||||||
debug(file) { "dependencies from fileAttributes = $deserializedDependencies" }
|
ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(VirtualFileScriptSource(file), it).apply {
|
||||||
saveToCache(file, deserializedDependencies)
|
debug(file) { "refined configuration from fileAttributes = $it" }
|
||||||
|
}
|
||||||
|
} ?: file.scriptDependencies?.let {
|
||||||
|
ScriptCompilationConfigurationWrapper.FromLegacy(VirtualFileScriptSource(file), it).apply {
|
||||||
|
debug(file) { "dependencies from fileAttributes = $it" }
|
||||||
|
}
|
||||||
|
}?.let {
|
||||||
|
saveToCache(file, it.asSuccess(), skipSaveToAttributes = true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldShowNotification(): Boolean = false
|
override fun shouldShowNotification(): Boolean = false
|
||||||
|
|||||||
+7
-4
@@ -22,6 +22,7 @@ import com.intellij.psi.ResolveScopeProvider
|
|||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
|
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
|
||||||
import org.jetbrains.kotlin.idea.core.script.StandardIdeScriptDefinition
|
import org.jetbrains.kotlin.idea.core.script.StandardIdeScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
|
|
||||||
@@ -36,11 +37,13 @@ class KotlinScriptResolveScopeProvider : ResolveScopeProvider() {
|
|||||||
// TODO: this should get this particular scripts dependencies
|
// TODO: this should get this particular scripts dependencies
|
||||||
return when {
|
return when {
|
||||||
scriptDefinition == null -> null
|
scriptDefinition == null -> null
|
||||||
// This is a workaround for completion in scripts and REPL to provide module dependencies
|
// This is a workaround for completion in scripts and REPL to provide module dependencies
|
||||||
scriptDefinition.template == Any::class -> null
|
scriptDefinition.baseClassType.fromClass == Any::class -> null
|
||||||
scriptDefinition is StandardIdeScriptDefinition -> null
|
scriptDefinition.asLegacyOrNull<StandardIdeScriptDefinition>() != null -> null
|
||||||
scriptDefinition is KotlinScriptDefinitionFromAnnotatedTemplate -> // TODO: should include the file itself
|
scriptDefinition is ScriptDefinition.FromConfigurations || scriptDefinition.asLegacyOrNull<KotlinScriptDefinitionFromAnnotatedTemplate>() != null -> {
|
||||||
|
// TODO: should include the file itself
|
||||||
ScriptDependenciesManager.getInstance(project).getAllScriptsDependenciesClassFilesScope()
|
ScriptDependenciesManager.getInstance(project).getAllScriptsDependenciesClassFilesScope()
|
||||||
|
}
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -18,9 +18,8 @@ class OutsiderFileDependenciesLoader(project: Project) : ScriptDependenciesLoade
|
|||||||
|
|
||||||
override fun loadDependencies(file: VirtualFile) {
|
override fun loadDependencies(file: VirtualFile) {
|
||||||
val fileOrigin = OutsidersPsiFileSupportUtils.getOutsiderFileOrigin(project, file) ?: return
|
val fileOrigin = OutsidersPsiFileSupportUtils.getOutsiderFileOrigin(project, file) ?: return
|
||||||
val originDependencies = ScriptDependenciesManager.getInstance(project).getScriptDependencies(fileOrigin)
|
val compilationConfiguration = ScriptDependenciesManager.getInstance(project).getRefinedCompilationConfiguration(fileOrigin) ?: return
|
||||||
debug(file) { "dependencies for outsider file = $originDependencies" }
|
saveToCache(file, compilationConfiguration)
|
||||||
saveToCache(file, originDependencies)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldShowNotification(): Boolean = false
|
override fun shouldShowNotification(): Boolean = false
|
||||||
|
|||||||
+42
-32
@@ -15,13 +15,14 @@ import com.intellij.openapi.util.EmptyRunnable
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.idea.core.script.*
|
import org.jetbrains.kotlin.idea.core.script.*
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptContentLoader
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
|
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
|
||||||
import org.jetbrains.kotlin.scripting.resolve.adjustByDefinition
|
import kotlin.script.experimental.api.ResultWithDiagnostics
|
||||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
import kotlin.script.experimental.api.valueOrNull
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
import kotlin.script.experimental.jvm.compat.mapToLegacyReports
|
||||||
|
|
||||||
|
// TODO: rename and provide alias for compatibility - this is not only about dependencies anymore
|
||||||
abstract class ScriptDependenciesLoader(protected val project: Project) {
|
abstract class ScriptDependenciesLoader(protected val project: Project) {
|
||||||
|
|
||||||
abstract fun isApplicable(file: VirtualFile): Boolean
|
abstract fun isApplicable(file: VirtualFile): Boolean
|
||||||
@@ -31,40 +32,40 @@ abstract class ScriptDependenciesLoader(protected val project: Project) {
|
|||||||
|
|
||||||
protected var shouldNotifyRootsChanged = false
|
protected var shouldNotifyRootsChanged = false
|
||||||
|
|
||||||
protected val contentLoader = ScriptContentLoader(project)
|
protected val cache: ScriptsCompilationConfigurationCache = ServiceManager.getService(project, ScriptsCompilationConfigurationCache::class.java)
|
||||||
protected val cache: ScriptDependenciesCache = ServiceManager.getService(project, ScriptDependenciesCache::class.java)
|
|
||||||
|
|
||||||
private val reporter: ScriptReportSink = ServiceManager.getService(project, ScriptReportSink::class.java)
|
private val reporter: ScriptReportSink = ServiceManager.getService(project, ScriptReportSink::class.java)
|
||||||
|
|
||||||
protected fun processResult(result: DependenciesResolver.ResolveResult, file: VirtualFile, scriptDef: KotlinScriptDefinition) {
|
protected fun processRefinedConfiguration(result: ScriptCompilationConfigurationResult, file: VirtualFile) {
|
||||||
debug(file) { "dependencies from ${this.javaClass} received = $result" }
|
debug(file) { "refined script compilation configuration from ${this.javaClass} received = $result" }
|
||||||
|
|
||||||
if (cache[file] == null) {
|
val oldResult = cache[file]
|
||||||
saveDependencies(result, file, scriptDef)
|
|
||||||
attachReportsIfChanged(result, file, scriptDef)
|
if (oldResult == null) {
|
||||||
|
save(result, file)
|
||||||
|
attachReportsIfChanged(result, file)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val newDependencies = result.dependencies?.adjustByDefinition(scriptDef)
|
if (oldResult != result) {
|
||||||
if (cache[file] != newDependencies) {
|
|
||||||
if (shouldShowNotification() && !ApplicationManager.getApplication().isUnitTestMode) {
|
if (shouldShowNotification() && !ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
debug(file) {
|
debug(file) {
|
||||||
"dependencies changed, notification was shown: old = ${cache[file]}, new = $newDependencies"
|
"dependencies changed, notification is shown: old = $oldResult, new = $result"
|
||||||
}
|
}
|
||||||
file.addScriptDependenciesNotificationPanel(result, project) {
|
file.addScriptDependenciesNotificationPanel(result, project) {
|
||||||
saveDependencies(it, file, scriptDef)
|
save(it, file)
|
||||||
attachReportsIfChanged(it, file, scriptDef)
|
attachReportsIfChanged(result, file)
|
||||||
submitMakeRootsChange()
|
submitMakeRootsChange()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debug(file) {
|
debug(file) {
|
||||||
"dependencies changed, new dependencies were applied automatically: old = ${cache[file]}, new = $newDependencies"
|
"dependencies changed, new dependencies are applied automatically: old = $oldResult, new = $result"
|
||||||
}
|
}
|
||||||
saveDependencies(result, file, scriptDef)
|
save(result, file)
|
||||||
attachReportsIfChanged(result, file, scriptDef)
|
attachReportsIfChanged(result, file)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
attachReportsIfChanged(result, file, scriptDef)
|
attachReportsIfChanged(result, file)
|
||||||
|
|
||||||
if (shouldShowNotification()) {
|
if (shouldShowNotification()) {
|
||||||
file.removeScriptDependenciesNotificationPanel(project)
|
file.removeScriptDependenciesNotificationPanel(project)
|
||||||
@@ -72,28 +73,36 @@ abstract class ScriptDependenciesLoader(protected val project: Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun attachReportsIfChanged(result: DependenciesResolver.ResolveResult, file: VirtualFile, scriptDef: KotlinScriptDefinition) {
|
private fun attachReportsIfChanged(result: ResultWithDiagnostics<*>, file: VirtualFile) {
|
||||||
if (file.getUserData(IdeScriptReportSink.Reports) != result.reports.takeIf { it.isNotEmpty() }) {
|
if (file.getUserData(IdeScriptReportSink.Reports) != result.reports.takeIf { it.isNotEmpty() }) {
|
||||||
reporter.attachReports(file, result.reports)
|
reporter.attachReports(file, result.reports.mapToLegacyReports())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveDependencies(result: DependenciesResolver.ResolveResult, file: VirtualFile, scriptDef: KotlinScriptDefinition) {
|
private fun save(compilationConfigurationResult: ScriptCompilationConfigurationResult?, file: VirtualFile) {
|
||||||
if (shouldShowNotification()) {
|
if (shouldShowNotification()) {
|
||||||
file.removeScriptDependenciesNotificationPanel(project)
|
file.removeScriptDependenciesNotificationPanel(project)
|
||||||
}
|
}
|
||||||
|
if (compilationConfigurationResult != null) {
|
||||||
val dependencies = result.dependencies?.adjustByDefinition(scriptDef) ?: return
|
saveToCache(file, compilationConfigurationResult)
|
||||||
saveToCache(file, dependencies)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveToCache(file: VirtualFile, dependencies: ScriptDependencies) {
|
protected fun saveToCache(
|
||||||
val rootsChanged = cache.hasNotCachedRoots(dependencies)
|
file: VirtualFile, compilationConfigurationResult: ScriptCompilationConfigurationResult, skipSaveToAttributes: Boolean = false
|
||||||
if (cache.save(file, dependencies)) {
|
) {
|
||||||
|
val rootsChanged = compilationConfigurationResult.valueOrNull()?.let { cache.hasNotCachedRoots(it) } ?: false
|
||||||
|
if (cache.save(file, compilationConfigurationResult)
|
||||||
|
&& !skipSaveToAttributes
|
||||||
|
&& compilationConfigurationResult is ResultWithDiagnostics.Success
|
||||||
|
) {
|
||||||
debug(file) {
|
debug(file) {
|
||||||
"dependencies were saved to file attributes: dependencies = $dependencies"
|
"refined configuration is saved to file attributes: $compilationConfigurationResult"
|
||||||
}
|
}
|
||||||
file.scriptDependencies = dependencies
|
if (compilationConfigurationResult.value is ScriptCompilationConfigurationWrapper.FromLegacy)
|
||||||
|
file.scriptDependencies = compilationConfigurationResult.value.legacyDependencies
|
||||||
|
else
|
||||||
|
file.scriptCompilationConfiguration = compilationConfigurationResult.value.configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rootsChanged) {
|
if (rootsChanged) {
|
||||||
@@ -101,6 +110,7 @@ abstract class ScriptDependenciesLoader(protected val project: Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
open fun notifyRootsChanged(): Boolean = submitMakeRootsChange()
|
open fun notifyRootsChanged(): Boolean = submitMakeRootsChange()
|
||||||
|
|
||||||
protected fun submitMakeRootsChange(): Boolean {
|
protected fun submitMakeRootsChange(): Boolean {
|
||||||
|
|||||||
+7
-5
@@ -7,21 +7,23 @@ package org.jetbrains.kotlin.idea.core.script.dependencies
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesUpdater
|
import org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationUpdater
|
||||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.refineScriptCompilationConfiguration
|
||||||
|
|
||||||
class SyncScriptDependenciesLoader internal constructor(project: Project) : ScriptDependenciesLoader(project) {
|
class SyncScriptDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) {
|
||||||
override fun isApplicable(file: VirtualFile): Boolean {
|
override fun isApplicable(file: VirtualFile): Boolean {
|
||||||
val scriptDefinition = file.findScriptDefinition(project) ?: return false
|
val scriptDefinition = file.findScriptDefinition(project) ?: return false
|
||||||
return !ScriptDependenciesUpdater.getInstance(project).isAsyncDependencyResolver(scriptDefinition)
|
return !ScriptsCompilationConfigurationUpdater.getInstance(project).isAsyncDependencyResolver(scriptDefinition)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadDependencies(file: VirtualFile) {
|
override fun loadDependencies(file: VirtualFile) {
|
||||||
val scriptDef = file.findScriptDefinition(project) ?: return
|
val scriptDef = file.findScriptDefinition(project) ?: return
|
||||||
debug(file) { "start sync dependencies loading" }
|
debug(file) { "start sync dependencies loading" }
|
||||||
val result = contentLoader.loadContentsAndResolveDependencies(scriptDef, file)
|
val result = refineScriptCompilationConfiguration(VirtualFileScriptSource(file), scriptDef, project)
|
||||||
debug(file) { "finish sync dependencies loading" }
|
debug(file) { "finish sync dependencies loading" }
|
||||||
processResult(result, file, scriptDef)
|
processRefinedConfiguration(result, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldShowNotification(): Boolean = false
|
override fun shouldShowNotification(): Boolean = false
|
||||||
|
|||||||
+7
-7
@@ -14,7 +14,7 @@ import com.intellij.util.addOptionTag
|
|||||||
import com.intellij.util.attribute
|
import com.intellij.util.attribute
|
||||||
import com.intellij.util.getAttributeBooleanValue
|
import com.intellij.util.getAttributeBooleanValue
|
||||||
import org.jdom.Element
|
import org.jdom.Element
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
|
|
||||||
@State(
|
@State(
|
||||||
name = "KotlinScriptingSettings",
|
name = "KotlinScriptingSettings",
|
||||||
@@ -72,22 +72,22 @@ class KotlinScriptingSettings : PersistentStateComponent<Element> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setOrder(scriptDefinition: KotlinScriptDefinition, order: Int) {
|
fun setOrder(scriptDefinition: ScriptDefinition, order: Int) {
|
||||||
scriptDefinitions[scriptDefinition.toKey()] = scriptDefinitions[scriptDefinition.toKey()]?.copy(order = order) ?:
|
scriptDefinitions[scriptDefinition.toKey()] = scriptDefinitions[scriptDefinition.toKey()]?.copy(order = order) ?:
|
||||||
KotlinScriptDefinitionValue(order)
|
KotlinScriptDefinitionValue(order)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun setEnabled(scriptDefinition: KotlinScriptDefinition, isEnabled: Boolean) {
|
fun setEnabled(scriptDefinition: ScriptDefinition, isEnabled: Boolean) {
|
||||||
scriptDefinitions[scriptDefinition.toKey()] = scriptDefinitions[scriptDefinition.toKey()]?.copy(isEnabled = isEnabled) ?:
|
scriptDefinitions[scriptDefinition.toKey()] = scriptDefinitions[scriptDefinition.toKey()]?.copy(isEnabled = isEnabled) ?:
|
||||||
KotlinScriptDefinitionValue(scriptDefinitions.size, isEnabled)
|
KotlinScriptDefinitionValue(scriptDefinitions.size, isEnabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getScriptDefinitionOrder(scriptDefinition: KotlinScriptDefinition): Int {
|
fun getScriptDefinitionOrder(scriptDefinition: ScriptDefinition): Int {
|
||||||
return scriptDefinitions[scriptDefinition.toKey()]?.order ?: Integer.MAX_VALUE
|
return scriptDefinitions[scriptDefinition.toKey()]?.order ?: Integer.MAX_VALUE
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isScriptDefinitionEnabled(scriptDefinition: KotlinScriptDefinition): Boolean {
|
fun isScriptDefinitionEnabled(scriptDefinition: ScriptDefinition): Boolean {
|
||||||
return scriptDefinitions[scriptDefinition.toKey()]?.isEnabled ?: true
|
return scriptDefinitions[scriptDefinition.toKey()]?.isEnabled ?: true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,8 +99,8 @@ class KotlinScriptingSettings : PersistentStateComponent<Element> {
|
|||||||
getAttributeValue(KotlinScriptDefinitionKey::className.name)
|
getAttributeValue(KotlinScriptDefinitionKey::className.name)
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun KotlinScriptDefinition.toKey() =
|
private fun ScriptDefinition.toKey() =
|
||||||
KotlinScriptDefinitionKey(this.name, this::class.qualifiedName ?: "unknown")
|
KotlinScriptDefinitionKey(this.name, this.definitionId)
|
||||||
|
|
||||||
private fun Element.addScriptDefinitionContentElement(definition: KotlinScriptDefinitionKey, settings: KotlinScriptDefinitionValue) {
|
private fun Element.addScriptDefinitionContentElement(definition: KotlinScriptDefinitionKey, settings: KotlinScriptDefinitionValue) {
|
||||||
addElement(SCRIPT_DEFINITION_TAG).apply {
|
addElement(SCRIPT_DEFINITION_TAG).apply {
|
||||||
|
|||||||
+76
-67
@@ -27,8 +27,9 @@ import com.intellij.util.EnvironmentUtil
|
|||||||
import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID
|
import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID
|
||||||
import org.jetbrains.kotlin.lexer.KotlinLexer
|
import org.jetbrains.kotlin.lexer.KotlinLexer
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinitionAdapterFromNewAPIBase
|
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinitionAdapterFromNewAPIBase
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.getEnvironment
|
||||||
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
import org.jetbrains.plugins.gradle.config.GradleSettingsListenerAdapter
|
import org.jetbrains.plugins.gradle.config.GradleSettingsListenerAdapter
|
||||||
import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper
|
import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper
|
||||||
@@ -38,10 +39,8 @@ import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
|||||||
import org.jetbrains.plugins.gradle.settings.GradleSettingsListener
|
import org.jetbrains.plugins.gradle.settings.GradleSettingsListener
|
||||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.IllegalStateException
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import kotlin.collections.LinkedHashSet
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.script.dependencies.Environment
|
import kotlin.script.dependencies.Environment
|
||||||
import kotlin.script.dependencies.ScriptContents
|
import kotlin.script.dependencies.ScriptContents
|
||||||
@@ -54,7 +53,7 @@ import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
|||||||
import kotlin.script.experimental.location.ScriptExpectedLocation
|
import kotlin.script.experimental.location.ScriptExpectedLocation
|
||||||
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
||||||
|
|
||||||
class GradleScriptDefinitionsContributor(private val project: Project) : ScriptDefinitionContributor {
|
class GradleScriptDefinitionsContributor(private val project: Project) : ScriptDefinitionSourceAsContributor {
|
||||||
|
|
||||||
override val id: String = "Gradle Kotlin DSL"
|
override val id: String = "Gradle Kotlin DSL"
|
||||||
private val failedToLoad = AtomicBoolean(false)
|
private val failedToLoad = AtomicBoolean(false)
|
||||||
@@ -86,55 +85,52 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
|
|||||||
initializeScriptModificationListener(project)
|
initializeScriptModificationListener(project)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDefinitions(): List<KotlinScriptDefinition> {
|
|
||||||
return loadDefinitions()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: control flow here depends on suppressing exceptions from loadGradleTemplates calls
|
// NOTE: control flow here depends on suppressing exceptions from loadGradleTemplates calls
|
||||||
// TODO: possibly combine exceptions from every loadGradleTemplates call, be mindful of KT-19276
|
// TODO: possibly combine exceptions from every loadGradleTemplates call, be mindful of KT-19276
|
||||||
private fun loadDefinitions(): List<KotlinScriptDefinition> {
|
override val definitions: Sequence<ScriptDefinition>
|
||||||
val kotlinDslDependencySelector = Regex("^gradle-(?:kotlin-dsl|core).*\\.jar\$")
|
get() {
|
||||||
val kotlinDslAdditionalResolverCp = ::kotlinStdlibAndCompiler
|
val kotlinDslDependencySelector = Regex("^gradle-(?:kotlin-dsl|core).*\\.jar\$")
|
||||||
|
val kotlinDslAdditionalResolverCp = ::kotlinStdlibAndCompiler
|
||||||
|
|
||||||
failedToLoad.set(false)
|
failedToLoad.set(false)
|
||||||
|
|
||||||
val kotlinDslTemplates = LinkedHashSet<KotlinScriptDefinition>()
|
val kotlinDslTemplates = LinkedHashSet<ScriptDefinition>()
|
||||||
|
|
||||||
loadGradleTemplates(
|
loadGradleTemplates(
|
||||||
templateClass = "org.gradle.kotlin.dsl.KotlinInitScript",
|
templateClass = "org.gradle.kotlin.dsl.KotlinInitScript",
|
||||||
dependencySelector = kotlinDslDependencySelector,
|
dependencySelector = kotlinDslDependencySelector,
|
||||||
additionalResolverClasspath = kotlinDslAdditionalResolverCp
|
additionalResolverClasspath = kotlinDslAdditionalResolverCp
|
||||||
|
|
||||||
).let { kotlinDslTemplates.addAll(it) }
|
).let { kotlinDslTemplates.addAll(it) }
|
||||||
|
|
||||||
loadGradleTemplates(
|
loadGradleTemplates(
|
||||||
templateClass = "org.gradle.kotlin.dsl.KotlinSettingsScript",
|
templateClass = "org.gradle.kotlin.dsl.KotlinSettingsScript",
|
||||||
dependencySelector = kotlinDslDependencySelector,
|
dependencySelector = kotlinDslDependencySelector,
|
||||||
additionalResolverClasspath = kotlinDslAdditionalResolverCp
|
additionalResolverClasspath = kotlinDslAdditionalResolverCp
|
||||||
|
|
||||||
).let { kotlinDslTemplates.addAll(it) }
|
).let { kotlinDslTemplates.addAll(it) }
|
||||||
|
|
||||||
// KotlinBuildScript should be last because it has wide scriptFilePattern
|
// KotlinBuildScript should be last because it has wide scriptFilePattern
|
||||||
loadGradleTemplates(
|
loadGradleTemplates(
|
||||||
templateClass = "org.gradle.kotlin.dsl.KotlinBuildScript",
|
templateClass = "org.gradle.kotlin.dsl.KotlinBuildScript",
|
||||||
dependencySelector = kotlinDslDependencySelector,
|
dependencySelector = kotlinDslDependencySelector,
|
||||||
additionalResolverClasspath = kotlinDslAdditionalResolverCp
|
additionalResolverClasspath = kotlinDslAdditionalResolverCp
|
||||||
).let { kotlinDslTemplates.addAll(it) }
|
).let { kotlinDslTemplates.addAll(it) }
|
||||||
|
|
||||||
|
|
||||||
if (kotlinDslTemplates.isNotEmpty()) {
|
if (kotlinDslTemplates.isNotEmpty()) {
|
||||||
return kotlinDslTemplates.toList()
|
return kotlinDslTemplates.asSequence()
|
||||||
|
}
|
||||||
|
|
||||||
|
val default = tryToLoadOldBuildScriptDefinition()
|
||||||
|
if (default.isNotEmpty()) {
|
||||||
|
return default.asSequence()
|
||||||
|
}
|
||||||
|
|
||||||
|
return sequenceOf(ErrorGradleScriptDefinition())
|
||||||
}
|
}
|
||||||
|
|
||||||
val default = tryToLoadOldBuildScriptDefinition()
|
private fun tryToLoadOldBuildScriptDefinition(): List<ScriptDefinition> {
|
||||||
if (default.isNotEmpty()) {
|
|
||||||
return default
|
|
||||||
}
|
|
||||||
|
|
||||||
return listOf(ErrorGradleScriptDefinition())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun tryToLoadOldBuildScriptDefinition(): List<KotlinScriptDefinition> {
|
|
||||||
failedToLoad.set(false)
|
failedToLoad.set(false)
|
||||||
|
|
||||||
return loadGradleTemplates(
|
return loadGradleTemplates(
|
||||||
@@ -154,7 +150,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
|
|||||||
private fun loadGradleTemplates(
|
private fun loadGradleTemplates(
|
||||||
templateClass: String, dependencySelector: Regex,
|
templateClass: String, dependencySelector: Regex,
|
||||||
additionalResolverClasspath: (gradleLibDir: File) -> List<File>
|
additionalResolverClasspath: (gradleLibDir: File) -> List<File>
|
||||||
): List<KotlinScriptDefinition> = try {
|
): List<ScriptDefinition> = try {
|
||||||
doLoadGradleTemplates(templateClass, dependencySelector, additionalResolverClasspath)
|
doLoadGradleTemplates(templateClass, dependencySelector, additionalResolverClasspath)
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
// TODO: review exception handling
|
// TODO: review exception handling
|
||||||
@@ -170,11 +166,11 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
|
|||||||
private fun doLoadGradleTemplates(
|
private fun doLoadGradleTemplates(
|
||||||
templateClass: String, dependencySelector: Regex,
|
templateClass: String, dependencySelector: Regex,
|
||||||
additionalResolverClasspath: (gradleLibDir: File) -> List<File>
|
additionalResolverClasspath: (gradleLibDir: File) -> List<File>
|
||||||
): List<KotlinScriptDefinition> {
|
): List<ScriptDefinition> {
|
||||||
fun createEnvironment(
|
fun createHostConfiguration(
|
||||||
gradleExeSettings: GradleExecutionSettings,
|
gradleExeSettings: GradleExecutionSettings,
|
||||||
projectSettings: GradleProjectSettings
|
projectSettings: GradleProjectSettings
|
||||||
): Environment {
|
): ScriptingHostConfiguration {
|
||||||
val gradleJvmOptions = gradleExeSettings.daemonVmOptions?.let { vmOptions ->
|
val gradleJvmOptions = gradleExeSettings.daemonVmOptions?.let { vmOptions ->
|
||||||
CommandLineTokenizer(vmOptions).toList()
|
CommandLineTokenizer(vmOptions).toList()
|
||||||
.mapNotNull { it?.let { it as? String } }
|
.mapNotNull { it?.let { it as? String } }
|
||||||
@@ -182,7 +178,8 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
|
|||||||
.distinct()
|
.distinct()
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
|
|
||||||
return mapOf(
|
|
||||||
|
val environment = mapOf(
|
||||||
"gradleHome" to gradleExeSettings.gradleHome?.let(::File),
|
"gradleHome" to gradleExeSettings.gradleHome?.let(::File),
|
||||||
"gradleJavaHome" to gradleExeSettings.javaHome,
|
"gradleJavaHome" to gradleExeSettings.javaHome,
|
||||||
|
|
||||||
@@ -194,6 +191,9 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
|
|||||||
|
|
||||||
"getScriptSectionTokens" to ::topLevelSectionCodeTextTokens
|
"getScriptSectionTokens" to ::topLevelSectionCodeTextTokens
|
||||||
)
|
)
|
||||||
|
return ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration) {
|
||||||
|
getEnvironment { environment }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
||||||
@@ -221,14 +221,17 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
|
|||||||
return loadDefinitionsFromTemplates(
|
return loadDefinitionsFromTemplates(
|
||||||
listOf(templateClass),
|
listOf(templateClass),
|
||||||
templateClasspath,
|
templateClasspath,
|
||||||
createEnvironment(gradleExeSettings, projectSettings),
|
createHostConfiguration(gradleExeSettings, projectSettings),
|
||||||
additionalResolverClasspath(gradleLibDir)
|
additionalResolverClasspath(gradleLibDir)
|
||||||
).map {
|
).map {
|
||||||
// Expand scope for old gradle script definition
|
it.asLegacyOrNull<KotlinScriptDefinitionFromAnnotatedTemplate>()?.let { legacyDef ->
|
||||||
if (it is KotlinScriptDefinitionFromAnnotatedTemplate && !it.scriptExpectedLocations.contains(ScriptExpectedLocation.Project))
|
@Suppress("DEPRECATION")
|
||||||
GradleKotlinScriptDefinitionFromAnnotatedTemplate(it)
|
if (legacyDef.scriptExpectedLocations.contains(ScriptExpectedLocation.Project)) null
|
||||||
else
|
else {
|
||||||
it
|
// Expand scope for old gradle script definition
|
||||||
|
ScriptDefinition.FromLegacy(it.hostConfiguration, GradleKotlinScriptDefinitionFromAnnotatedTemplate(legacyDef))
|
||||||
|
}
|
||||||
|
} ?: it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,23 +245,28 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
|
|||||||
ScriptDefinitionsManager.getInstance(project).reloadDefinitionsBy(this)
|
ScriptDefinitionsManager.getInstance(project).reloadDefinitionsBy(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ErrorGradleScriptDefinition(message: String? = null) : KotlinScriptDefinitionAdapterFromNewAPIBase() {
|
// TODO: refactor - minimize
|
||||||
companion object {
|
private class ErrorGradleScriptDefinition(message: String? = null) :
|
||||||
private const val KOTLIN_DSL_SCRIPT_EXTENSION = "gradle.kts"
|
ScriptDefinition.FromLegacy(ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration), LegacyDefinition(message)) {
|
||||||
|
|
||||||
|
private class LegacyDefinition(message: String?) : KotlinScriptDefinitionAdapterFromNewAPIBase() {
|
||||||
|
companion object {
|
||||||
|
private const val KOTLIN_DSL_SCRIPT_EXTENSION = "gradle.kts"
|
||||||
|
}
|
||||||
|
|
||||||
|
override val name: String = "Default Kotlin Gradle Script"
|
||||||
|
override val fileExtension: String = KOTLIN_DSL_SCRIPT_EXTENSION
|
||||||
|
|
||||||
|
override val scriptCompilationConfiguration: ScriptCompilationConfiguration = ScriptCompilationConfiguration.Default
|
||||||
|
override val hostConfiguration: ScriptingHostConfiguration = ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration)
|
||||||
|
override val baseClass: KClass<*> = ScriptTemplateWithArgs::class
|
||||||
|
|
||||||
|
override val dependencyResolver: DependenciesResolver = ErrorScriptDependenciesResolver(message)
|
||||||
|
|
||||||
|
override fun toString(): String = "ErrorGradleScriptDefinition"
|
||||||
|
override fun equals(other: Any?): Boolean = other is ErrorGradleScriptDefinition
|
||||||
|
override fun hashCode(): Int = name.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val name: String = "Default Kotlin Gradle Script"
|
|
||||||
override val fileExtension: String = KOTLIN_DSL_SCRIPT_EXTENSION
|
|
||||||
|
|
||||||
override val scriptCompilationConfiguration: ScriptCompilationConfiguration = ScriptCompilationConfiguration.Default
|
|
||||||
override val hostConfiguration: ScriptingHostConfiguration = ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration)
|
|
||||||
override val baseClass: KClass<*> = ScriptTemplateWithArgs::class
|
|
||||||
|
|
||||||
override val dependencyResolver: DependenciesResolver = ErrorScriptDependenciesResolver(message)
|
|
||||||
|
|
||||||
override fun toString(): String = "ErrorGradleScriptDefinition"
|
|
||||||
override fun equals(other: Any?): Boolean = other is ErrorGradleScriptDefinition
|
|
||||||
override fun hashCode(): Int = name.hashCode()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ErrorScriptDependenciesResolver(private val message: String? = null) : DependenciesResolver {
|
private class ErrorScriptDependenciesResolver(private val message: String? = null) : DependenciesResolver {
|
||||||
@@ -280,6 +288,7 @@ internal class GradleSyncState {
|
|||||||
class GradleKotlinScriptDefinitionFromAnnotatedTemplate(
|
class GradleKotlinScriptDefinitionFromAnnotatedTemplate(
|
||||||
base: KotlinScriptDefinitionFromAnnotatedTemplate
|
base: KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
) : KotlinScriptDefinitionFromAnnotatedTemplate(base.template, base.environment, base.templateClasspath) {
|
) : KotlinScriptDefinitionFromAnnotatedTemplate(base.template, base.environment, base.templateClasspath) {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
override val scriptExpectedLocations: List<ScriptExpectedLocation>
|
override val scriptExpectedLocations: List<ScriptExpectedLocation>
|
||||||
get() = listOf(ScriptExpectedLocation.Project)
|
get() = listOf(ScriptExpectedLocation.Project)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||||
import org.jetbrains.kotlin.resolve.AnalyzingUtils
|
import org.jetbrains.kotlin.resolve.AnalyzingUtils
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.script.experimental.api.valueOrNull
|
||||||
|
|
||||||
class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) {
|
class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -186,8 +187,10 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) {
|
|||||||
javaParameters.classPath.addAll(JavaParametersBuilder.getModuleDependencies(module))
|
javaParameters.classPath.addAll(JavaParametersBuilder.getModuleDependencies(module))
|
||||||
}
|
}
|
||||||
|
|
||||||
val scriptDependencies = ScriptDependenciesManager.getInstance(originalFile.project).getScriptDependencies(originalFile.virtualFile)
|
ScriptDependenciesManager.getInstance(originalFile.project)
|
||||||
javaParameters.classPath.addAll(scriptDependencies.classpath.map { it.absolutePath })
|
.getRefinedCompilationConfiguration(originalFile.virtualFile)?.valueOrNull()?.let {
|
||||||
|
javaParameters.classPath.addAll(it.dependenciesClassPath.map { f -> f.absolutePath })
|
||||||
|
}
|
||||||
|
|
||||||
return javaParameters.toCommandLine()
|
return javaParameters.toCommandLine()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ import org.jetbrains.kotlin.idea.caches.project.productionSourceInfo
|
|||||||
import org.jetbrains.kotlin.idea.caches.project.testSourceInfo
|
import org.jetbrains.kotlin.idea.caches.project.testSourceInfo
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionSourceAsContributor
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager
|
||||||
import org.jetbrains.kotlin.idea.project.KOTLIN_CONSOLE_KEY
|
import org.jetbrains.kotlin.idea.project.KOTLIN_CONSOLE_KEY
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
@@ -72,11 +73,13 @@ import org.jetbrains.kotlin.psi.KtScript
|
|||||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
|
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
|
||||||
import org.jetbrains.kotlin.resolve.repl.ReplState
|
import org.jetbrains.kotlin.resolve.repl.ReplState
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import java.awt.Color
|
import java.awt.Color
|
||||||
import java.awt.Font
|
import java.awt.Font
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
private val KOTLIN_SHELL_EXECUTE_ACTION_ID = "KotlinShellExecute"
|
private val KOTLIN_SHELL_EXECUTE_ACTION_ID = "KotlinShellExecute"
|
||||||
|
|
||||||
@@ -305,20 +308,21 @@ class KotlinConsoleRunner(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConsoleScriptDefinitionContributor: ScriptDefinitionContributor {
|
class ConsoleScriptDefinitionContributor: ScriptDefinitionSourceAsContributor {
|
||||||
private val definitions = ContainerUtil.newConcurrentSet<KotlinScriptDefinition>()
|
|
||||||
|
val definitionsSet = ContainerUtil.newConcurrentSet<ScriptDefinition>()
|
||||||
|
|
||||||
|
override val definitions: Sequence<ScriptDefinition>
|
||||||
|
get() = definitionsSet.asSequence()
|
||||||
|
|
||||||
override val id: String = "IDEA Console"
|
override val id: String = "IDEA Console"
|
||||||
|
|
||||||
override fun getDefinitions(): List<KotlinScriptDefinition> {
|
// TODO: rewrite to ScriptDefinition
|
||||||
return definitions.toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun registerDefinition(definition: KotlinScriptDefinition) {
|
fun registerDefinition(definition: KotlinScriptDefinition) {
|
||||||
definitions.add(definition)
|
definitionsSet.add(ScriptDefinition.FromLegacy(defaultJvmScriptingHostConfiguration, definition))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unregisterDefinition(definition: KotlinScriptDefinition) {
|
fun unregisterDefinition(definition: KotlinScriptDefinition) {
|
||||||
definitions.remove(definition)
|
definitionsSet.removeIf { it.asLegacyOrNull<KotlinScriptDefinition>() == definition }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,11 +284,11 @@
|
|||||||
<projectService serviceInterface="org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager"
|
<projectService serviceInterface="org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager"
|
||||||
serviceImplementation="org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager"/>
|
serviceImplementation="org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager"/>
|
||||||
|
|
||||||
<projectService serviceInterface="org.jetbrains.kotlin.idea.core.script.ScriptDependenciesCache"
|
<projectService serviceInterface="org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationCache"
|
||||||
serviceImplementation="org.jetbrains.kotlin.idea.core.script.ScriptDependenciesCache"/>
|
serviceImplementation="org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationCache"/>
|
||||||
|
|
||||||
<projectService serviceInterface="org.jetbrains.kotlin.idea.core.script.ScriptDependenciesUpdater"
|
<projectService serviceInterface="org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationUpdater"
|
||||||
serviceImplementation="org.jetbrains.kotlin.idea.core.script.ScriptDependenciesUpdater"/>
|
serviceImplementation="org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationUpdater"/>
|
||||||
|
|
||||||
<projectService serviceInterface="org.jetbrains.kotlin.scripting.resolve.ScriptReportSink"
|
<projectService serviceInterface="org.jetbrains.kotlin.scripting.resolve.ScriptReportSink"
|
||||||
serviceImplementation="org.jetbrains.kotlin.idea.core.script.IdeScriptReportSink"/>
|
serviceImplementation="org.jetbrains.kotlin.idea.core.script.IdeScriptReportSink"/>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
|||||||
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||||
import org.jetbrains.kotlin.idea.core.isInheritable
|
import org.jetbrains.kotlin.idea.core.isInheritable
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesUpdater
|
import org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationUpdater
|
||||||
import org.jetbrains.kotlin.idea.core.toDescriptor
|
import org.jetbrains.kotlin.idea.core.toDescriptor
|
||||||
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
|
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
|
||||||
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindClassUsagesHandler
|
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindClassUsagesHandler
|
||||||
@@ -127,7 +127,7 @@ class UnusedSymbolInspection : AbstractKotlinInspection() {
|
|||||||
|
|
||||||
val usedScripts = findScriptsWithUsages(declaration)
|
val usedScripts = findScriptsWithUsages(declaration)
|
||||||
if (usedScripts.isNotEmpty()) {
|
if (usedScripts.isNotEmpty()) {
|
||||||
if (ScriptDependenciesUpdater.getInstance(declaration.project).updateDependenciesIfNeeded(usedScripts)) {
|
if (ScriptsCompilationConfigurationUpdater.getInstance(declaration.project).updateDependenciesIfNeeded(usedScripts)) {
|
||||||
return TOO_MANY_OCCURRENCES
|
return TOO_MANY_OCCURRENCES
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,29 +9,30 @@ import com.intellij.openapi.application.ApplicationManager
|
|||||||
import com.intellij.openapi.progress.ProgressIndicator
|
import com.intellij.openapi.progress.ProgressIndicator
|
||||||
import com.intellij.openapi.progress.Task
|
import com.intellij.openapi.progress.Task
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionSourceAsContributor
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
import kotlin.concurrent.read
|
import kotlin.concurrent.read
|
||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
|
|
||||||
abstract class AsyncScriptDefinitionsContributor(protected val project: Project) : ScriptDefinitionContributor {
|
abstract class AsyncScriptDefinitionsContributor(protected val project: Project) : ScriptDefinitionSourceAsContributor {
|
||||||
abstract val progressMessage: String
|
abstract val progressMessage: String
|
||||||
|
|
||||||
override fun isReady(): Boolean = definitions != null
|
override fun isReady(): Boolean = _definitions != null
|
||||||
|
|
||||||
override fun getDefinitions(): List<KotlinScriptDefinition> {
|
override val definitions: Sequence<ScriptDefinition>
|
||||||
definitionsLock.read {
|
get() {
|
||||||
if (definitions != null) {
|
definitionsLock.read {
|
||||||
return definitions!!
|
if (_definitions != null) {
|
||||||
|
return _definitions!!.asSequence()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
forceStartUpdate = false
|
forceStartUpdate = false
|
||||||
asyncRunUpdateScriptTemplates()
|
asyncRunUpdateScriptTemplates()
|
||||||
return emptyList()
|
return emptySequence()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun asyncRunUpdateScriptTemplates() {
|
protected fun asyncRunUpdateScriptTemplates() {
|
||||||
val backgroundTask = inProgressLock.write {
|
val backgroundTask = inProgressLock.write {
|
||||||
@@ -50,9 +51,9 @@ abstract class AsyncScriptDefinitionsContributor(protected val project: Project)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun loadScriptDefinitions(previous: List<KotlinScriptDefinition>?): List<KotlinScriptDefinition>
|
protected abstract fun loadScriptDefinitions(previous: List<ScriptDefinition>?): List<ScriptDefinition>
|
||||||
|
|
||||||
private var definitions: List<KotlinScriptDefinition>? = null
|
private var _definitions: List<ScriptDefinition>? = null
|
||||||
private val definitionsLock = ReentrantReadWriteLock()
|
private val definitionsLock = ReentrantReadWriteLock()
|
||||||
|
|
||||||
protected var forceStartUpdate = false
|
protected var forceStartUpdate = false
|
||||||
@@ -77,10 +78,10 @@ abstract class AsyncScriptDefinitionsContributor(protected val project: Project)
|
|||||||
|
|
||||||
val wasRunning = definitionsLock.isWriteLocked
|
val wasRunning = definitionsLock.isWriteLocked
|
||||||
val needReload = definitionsLock.write {
|
val needReload = definitionsLock.write {
|
||||||
if (wasRunning && !forceStartUpdate && definitions != null) return@write false
|
if (wasRunning && !forceStartUpdate && _definitions != null) return@write false
|
||||||
val newDefinitions = loadScriptDefinitions(definitions)
|
val newDefinitions = loadScriptDefinitions(_definitions)
|
||||||
if (newDefinitions != definitions) {
|
if (newDefinitions != _definitions) {
|
||||||
definitions = newDefinitions
|
_definitions = newDefinitions
|
||||||
return@write true
|
return@write true
|
||||||
}
|
}
|
||||||
return@write false
|
return@write false
|
||||||
|
|||||||
@@ -11,35 +11,38 @@ import com.intellij.openapi.project.Project
|
|||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionSourceAsContributor
|
||||||
import org.jetbrains.kotlin.idea.core.script.loadDefinitionsFromTemplates
|
import org.jetbrains.kotlin.idea.core.script.loadDefinitionsFromTemplates
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource
|
||||||
import org.jetbrains.kotlin.scripting.definitions.reporter
|
import org.jetbrains.kotlin.scripting.definitions.reporter
|
||||||
import kotlin.script.experimental.intellij.ScriptDefinitionsProvider
|
import kotlin.script.experimental.intellij.ScriptDefinitionsProvider
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
class BridgeScriptDefinitionsContributor(private val project: Project) : ScriptDefinitionContributor {
|
class BridgeScriptDefinitionsContributor(private val project: Project) : ScriptDefinitionSourceAsContributor {
|
||||||
override val id: String = "BridgeScriptDefinitionsContributor"
|
override val id: String = "BridgeScriptDefinitionsContributor"
|
||||||
|
|
||||||
override fun getDefinitions(): List<KotlinScriptDefinition> {
|
override val definitions: Sequence<ScriptDefinition>
|
||||||
val extensions = Extensions.getArea(project).getExtensionPoint(ScriptDefinitionsProvider.EP_NAME).extensions
|
get() {
|
||||||
val messageCollector = LoggingMessageCollector()
|
val extensions = Extensions.getArea(project).getExtensionPoint(ScriptDefinitionsProvider.EP_NAME).extensions
|
||||||
return extensions.flatMap { provider ->
|
val messageCollector = LoggingMessageCollector()
|
||||||
val explicitClasses = provider.getDefinitionClasses().toList()
|
return extensions.asSequence().flatMap { provider ->
|
||||||
val classPath = provider.getDefinitionsClassPath().toList()
|
val explicitClasses = provider.getDefinitionClasses().toList()
|
||||||
val explicitDefinitions =
|
val classPath = provider.getDefinitionsClassPath().toList()
|
||||||
if (explicitClasses.isNotEmpty()) loadDefinitionsFromTemplates(explicitClasses, classPath)
|
val hostConfiguration = defaultJvmScriptingHostConfiguration
|
||||||
else emptyList()
|
val explicitDefinitions =
|
||||||
val discoveredDefinitions =
|
if (explicitClasses.isEmpty()) emptySequence()
|
||||||
if (provider.useDiscovery()) emptySequence()
|
else loadDefinitionsFromTemplates(explicitClasses, classPath, hostConfiguration).asSequence()
|
||||||
else ScriptDefinitionsFromClasspathDiscoverySource(
|
val discoveredDefinitions =
|
||||||
classPath,
|
if (provider.useDiscovery()) emptySequence()
|
||||||
emptyMap(),
|
else ScriptDefinitionsFromClasspathDiscoverySource(
|
||||||
messageCollector.reporter
|
classPath,
|
||||||
).definitions
|
hostConfiguration,
|
||||||
explicitDefinitions + discoveredDefinitions
|
messageCollector.reporter
|
||||||
|
).definitions
|
||||||
|
explicitDefinitions + discoveredDefinitions
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LoggingMessageCollector : MessageCollector {
|
private class LoggingMessageCollector : MessageCollector {
|
||||||
|
|||||||
+9
-12
@@ -12,11 +12,10 @@ import com.intellij.util.ui.ListTableModel
|
|||||||
import org.jetbrains.kotlin.idea.core.script.StandardIdeScriptDefinition
|
import org.jetbrains.kotlin.idea.core.script.StandardIdeScriptDefinition
|
||||||
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
||||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinitionAdapterFromNewAPIBase
|
|
||||||
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
|
|
||||||
class KotlinScriptDefinitionsModelDescriptor(val definition: KotlinScriptDefinition, var isEnabled: Boolean)
|
class KotlinScriptDefinitionsModelDescriptor(val definition: ScriptDefinition, var isEnabled: Boolean)
|
||||||
|
|
||||||
class KotlinScriptDefinitionsModel private constructor(definitions: MutableList<KotlinScriptDefinitionsModelDescriptor>) :
|
class KotlinScriptDefinitionsModel private constructor(definitions: MutableList<KotlinScriptDefinitionsModelDescriptor>) :
|
||||||
ListTableModel<KotlinScriptDefinitionsModelDescriptor>(
|
ListTableModel<KotlinScriptDefinitionsModelDescriptor>(
|
||||||
@@ -30,7 +29,7 @@ class KotlinScriptDefinitionsModel private constructor(definitions: MutableList<
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
fun getDefinitions() = items.map { it.definition }
|
fun getDefinitions() = items.map { it.definition }
|
||||||
fun setDefinitions(definitions: List<KotlinScriptDefinition>, settings: KotlinScriptingSettings) {
|
fun setDefinitions(definitions: List<ScriptDefinition>, settings: KotlinScriptingSettings) {
|
||||||
items = definitions.mapTo(arrayListOf()) { KotlinScriptDefinitionsModelDescriptor(it, settings.isScriptDefinitionEnabled(it)) }
|
items = definitions.mapTo(arrayListOf()) { KotlinScriptDefinitionsModelDescriptor(it, settings.isScriptDefinitionEnabled(it)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,12 +40,9 @@ class KotlinScriptDefinitionsModel private constructor(definitions: MutableList<
|
|||||||
private class ScriptDefinitionPattern : ColumnInfo<KotlinScriptDefinitionsModelDescriptor, String>("Pattern/Extension") {
|
private class ScriptDefinitionPattern : ColumnInfo<KotlinScriptDefinitionsModelDescriptor, String>("Pattern/Extension") {
|
||||||
override fun valueOf(item: KotlinScriptDefinitionsModelDescriptor): String {
|
override fun valueOf(item: KotlinScriptDefinitionsModelDescriptor): String {
|
||||||
val definition = item.definition
|
val definition = item.definition
|
||||||
return when (definition) {
|
return definition.asLegacyOrNull<KotlinScriptDefinitionFromAnnotatedTemplate>()?.scriptFilePattern?.pattern
|
||||||
is KotlinScriptDefinitionFromAnnotatedTemplate -> definition.scriptFilePattern.pattern
|
?: definition.asLegacyOrNull<StandardIdeScriptDefinition>()?.let { KotlinParserDefinition.STD_SCRIPT_EXT }
|
||||||
is KotlinScriptDefinitionAdapterFromNewAPIBase -> definition.fileExtension
|
?: definition.fileExtension
|
||||||
is StandardIdeScriptDefinition -> KotlinParserDefinition.STD_SCRIPT_EXT
|
|
||||||
else -> ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,11 +54,12 @@ class KotlinScriptDefinitionsModel private constructor(definitions: MutableList<
|
|||||||
|
|
||||||
override fun getEditor(item: KotlinScriptDefinitionsModelDescriptor?) = BooleanTableCellEditor()
|
override fun getEditor(item: KotlinScriptDefinitionsModelDescriptor?) = BooleanTableCellEditor()
|
||||||
override fun getRenderer(item: KotlinScriptDefinitionsModelDescriptor?) = BooleanTableCellRenderer()
|
override fun getRenderer(item: KotlinScriptDefinitionsModelDescriptor?) = BooleanTableCellRenderer()
|
||||||
override fun isCellEditable(item: KotlinScriptDefinitionsModelDescriptor) = item.definition !is StandardIdeScriptDefinition
|
override fun isCellEditable(item: KotlinScriptDefinitionsModelDescriptor) =
|
||||||
|
item.definition.asLegacyOrNull<StandardIdeScriptDefinition>() == null
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun createModel(definitions: List<KotlinScriptDefinition>, settings: KotlinScriptingSettings): KotlinScriptDefinitionsModel {
|
fun createModel(definitions: List<ScriptDefinition>, settings: KotlinScriptingSettings): KotlinScriptDefinitionsModel {
|
||||||
return KotlinScriptDefinitionsModel(definitions.mapTo(arrayListOf()) {
|
return KotlinScriptDefinitionsModel(definitions.mapTo(arrayListOf()) {
|
||||||
KotlinScriptDefinitionsModelDescriptor(
|
KotlinScriptDefinitionsModelDescriptor(
|
||||||
it,
|
it,
|
||||||
|
|||||||
+2
-2
@@ -14,7 +14,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager;
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager;
|
||||||
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings;
|
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings;
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition;
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -64,7 +64,7 @@ public class KotlinScriptingSettingsConfigurable implements SearchableConfigurab
|
|||||||
|
|
||||||
if (isScriptDefinitionsChanged()) {
|
if (isScriptDefinitionsChanged()) {
|
||||||
for (KotlinScriptDefinitionsModelDescriptor item : model.getItems()) {
|
for (KotlinScriptDefinitionsModelDescriptor item : model.getItems()) {
|
||||||
KotlinScriptDefinition definition = item.getDefinition();
|
ScriptDefinition definition = item.getDefinition();
|
||||||
settings.setOrder(definition, model.getItems().indexOf(item));
|
settings.setOrder(definition, model.getItems().indexOf(item));
|
||||||
settings.setEnabled(definition, item.isEnabled());
|
settings.setEnabled(definition, item.isEnabled());
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-22
@@ -23,8 +23,7 @@ import org.jetbrains.kotlin.idea.core.script.StandardIdeScriptDefinition
|
|||||||
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
||||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinitionAdapterFromNewAPIBase
|
|
||||||
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
|
|
||||||
class MultipleScriptDefinitionsChecker(private val project: Project) : EditorNotifications.Provider<EditorNotificationPanel>() {
|
class MultipleScriptDefinitionsChecker(private val project: Project) : EditorNotifications.Provider<EditorNotificationPanel>() {
|
||||||
@@ -42,8 +41,7 @@ class MultipleScriptDefinitionsChecker(private val project: Project) : EditorNot
|
|||||||
val allApplicableDefinitions = ScriptDefinitionsManager.getInstance(project)
|
val allApplicableDefinitions = ScriptDefinitionsManager.getInstance(project)
|
||||||
.getAllDefinitions()
|
.getAllDefinitions()
|
||||||
.filter {
|
.filter {
|
||||||
it !is StandardIdeScriptDefinition &&
|
it.asLegacyOrNull<StandardIdeScriptDefinition>() == null && it.isScript(ktFile.name) &&
|
||||||
it.isScript(ktFile.name) &&
|
|
||||||
KotlinScriptingSettings.getInstance(project).isScriptDefinitionEnabled(it)
|
KotlinScriptingSettings.getInstance(project).isScriptDefinitionEnabled(it)
|
||||||
}
|
}
|
||||||
.toList()
|
.toList()
|
||||||
@@ -56,10 +54,10 @@ class MultipleScriptDefinitionsChecker(private val project: Project) : EditorNot
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun areDefinitionsForGradleKts(allApplicableDefinitions: List<KotlinScriptDefinition>): Boolean {
|
private fun areDefinitionsForGradleKts(allApplicableDefinitions: List<ScriptDefinition>): Boolean {
|
||||||
if (allApplicableDefinitions.size == 2) {
|
if (allApplicableDefinitions.size == 2) {
|
||||||
return (allApplicableDefinitions[0] as? KotlinScriptDefinitionFromAnnotatedTemplate)?.scriptFilePattern?.pattern == "^(settings|.+\\.settings)\\.gradle\\.kts\$"
|
return allApplicableDefinitions[0].asLegacyOrNull<KotlinScriptDefinitionFromAnnotatedTemplate>()?.scriptFilePattern?.pattern == "^(settings|.+\\.settings)\\.gradle\\.kts\$"
|
||||||
&& (allApplicableDefinitions[1] as? KotlinScriptDefinitionFromAnnotatedTemplate)?.scriptFilePattern?.pattern == ".*\\.gradle\\.kts"
|
&& allApplicableDefinitions[1].asLegacyOrNull<KotlinScriptDefinitionFromAnnotatedTemplate>()?.scriptFilePattern?.pattern == ".*\\.gradle\\.kts"
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -67,25 +65,18 @@ class MultipleScriptDefinitionsChecker(private val project: Project) : EditorNot
|
|||||||
companion object {
|
companion object {
|
||||||
private val KEY = Key.create<EditorNotificationPanel>("MultipleScriptDefinitionsChecker")
|
private val KEY = Key.create<EditorNotificationPanel>("MultipleScriptDefinitionsChecker")
|
||||||
|
|
||||||
private fun createNotification(psiFile: KtFile, defs: List<KotlinScriptDefinition>): EditorNotificationPanel {
|
private fun createNotification(psiFile: KtFile, defs: List<ScriptDefinition>): EditorNotificationPanel {
|
||||||
return EditorNotificationPanel().apply {
|
return EditorNotificationPanel().apply {
|
||||||
setText("Multiple script definitions are applicable for this script. ${defs.first().name} is used")
|
setText("Multiple script definitions are applicable for this script. ${defs.first().name} is used")
|
||||||
createComponentActionLabel("Show all") {
|
createComponentActionLabel("Show all") {
|
||||||
val list = JBPopupFactory.getInstance().createListPopup(
|
val list = JBPopupFactory.getInstance().createListPopup(
|
||||||
object : BaseListPopupStep<KotlinScriptDefinition>(null, defs) {
|
object : BaseListPopupStep<ScriptDefinition>(null, defs) {
|
||||||
override fun getTextFor(value: KotlinScriptDefinition): String {
|
override fun getTextFor(value: ScriptDefinition): String {
|
||||||
return when (value) {
|
return value.asLegacyOrNull<KotlinScriptDefinitionFromAnnotatedTemplate>()?.let {
|
||||||
is KotlinScriptDefinitionFromAnnotatedTemplate -> {
|
it.name + " (${it.scriptFilePattern})"
|
||||||
value.name + " (${value.scriptFilePattern})"
|
} ?: value.asLegacyOrNull<StandardIdeScriptDefinition>()?.let {
|
||||||
}
|
it.name + " (${KotlinParserDefinition.STD_SCRIPT_EXT})"
|
||||||
is KotlinScriptDefinitionAdapterFromNewAPIBase -> {
|
} ?: value.name + " (${value.fileExtension})"
|
||||||
value.name + " (${value.fileExtension})"
|
|
||||||
}
|
|
||||||
is StandardIdeScriptDefinition -> {
|
|
||||||
value.name + " (${KotlinParserDefinition.STD_SCRIPT_EXT})"
|
|
||||||
}
|
|
||||||
else -> value.name
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,16 +20,19 @@ import com.intellij.openapi.project.Project
|
|||||||
import org.jetbrains.kotlin.config.CompilerSettings
|
import org.jetbrains.kotlin.config.CompilerSettings
|
||||||
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettings
|
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettings
|
||||||
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettingsListener
|
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettingsListener
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionSourceAsContributor
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager
|
||||||
import org.jetbrains.kotlin.idea.core.script.loadDefinitionsFromTemplates
|
import org.jetbrains.kotlin.idea.core.script.loadDefinitionsFromTemplates
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.getEnvironment
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
class ScriptTemplatesFromCompilerSettingsProvider(
|
class ScriptTemplatesFromCompilerSettingsProvider(
|
||||||
private val project: Project,
|
private val project: Project,
|
||||||
private val compilerSettings: KotlinCompilerSettings
|
private val compilerSettings: KotlinCompilerSettings
|
||||||
) : ScriptDefinitionContributor {
|
) : ScriptDefinitionSourceAsContributor {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
project.messageBus.connect().subscribe(KotlinCompilerSettingsListener.TOPIC, object : KotlinCompilerSettingsListener {
|
project.messageBus.connect().subscribe(KotlinCompilerSettingsListener.TOPIC, object : KotlinCompilerSettingsListener {
|
||||||
@@ -41,17 +44,22 @@ class ScriptTemplatesFromCompilerSettingsProvider(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDefinitions(): List<KotlinScriptDefinition> {
|
override val definitions: Sequence<ScriptDefinition>
|
||||||
val kotlinSettings = compilerSettings.settings
|
get() {
|
||||||
return if (kotlinSettings.scriptTemplates.isBlank()) emptyList()
|
val kotlinSettings = compilerSettings.settings
|
||||||
else loadDefinitionsFromTemplates(
|
return if (kotlinSettings.scriptTemplates.isBlank()) emptySequence()
|
||||||
templateClassNames = kotlinSettings.scriptTemplates.split(',', ' '),
|
else loadDefinitionsFromTemplates(
|
||||||
templateClasspath = kotlinSettings.scriptTemplatesClasspath.split(File.pathSeparator).map(::File),
|
templateClassNames = kotlinSettings.scriptTemplates.split(',', ' '),
|
||||||
environment = mapOf(
|
templateClasspath = kotlinSettings.scriptTemplatesClasspath.split(File.pathSeparator).map(::File),
|
||||||
"projectRoot" to (project.basePath ?: project.baseDir.canonicalPath)?.let(::File)
|
baseHostConfiguration = ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration) {
|
||||||
)
|
getEnvironment {
|
||||||
)
|
mapOf(
|
||||||
}
|
"projectRoot" to (project.basePath ?: project.baseDir.canonicalPath)?.let(::File)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).asSequence()
|
||||||
|
}
|
||||||
|
|
||||||
override val id: String = "KotlinCompilerScriptTemplatesSettings"
|
override val id: String = "KotlinCompilerScriptTemplatesSettings"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ import com.intellij.openapi.vfs.JarFileSystem
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.idea.core.script.loadDefinitionsFromTemplates
|
import org.jetbrains.kotlin.idea.core.script.loadDefinitionsFromTemplates
|
||||||
import org.jetbrains.kotlin.idea.util.projectStructure.allModules
|
import org.jetbrains.kotlin.idea.util.projectStructure.allModules
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.*
|
||||||
import org.jetbrains.kotlin.scripting.definitions.SCRIPT_DEFINITION_MARKERS_EXTENSION_WITH_DOT
|
|
||||||
import org.jetbrains.kotlin.scripting.definitions.SCRIPT_DEFINITION_MARKERS_PATH
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
class ScriptTemplatesFromDependenciesProvider(project: Project) : AsyncScriptDefinitionsContributor(project) {
|
class ScriptTemplatesFromDependenciesProvider(project: Project) : AsyncScriptDefinitionsContributor(project) {
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ class ScriptTemplatesFromDependenciesProvider(project: Project) : AsyncScriptDef
|
|||||||
override val id = "ScriptTemplatesFromDependenciesProvider"
|
override val id = "ScriptTemplatesFromDependenciesProvider"
|
||||||
override val progressMessage = "Kotlin: scanning dependencies for script definitions..."
|
override val progressMessage = "Kotlin: scanning dependencies for script definitions..."
|
||||||
|
|
||||||
override fun loadScriptDefinitions(previous: List<KotlinScriptDefinition>?): List<KotlinScriptDefinition> {
|
override fun loadScriptDefinitions(previous: List<ScriptDefinition>?): List<ScriptDefinition> {
|
||||||
val templatesCopy = templatesLock.write {
|
val templatesCopy = templatesLock.write {
|
||||||
val newTemplates = scriptDefinitionsFromDependencies(project)
|
val newTemplates = scriptDefinitionsFromDependencies(project)
|
||||||
if (newTemplates != templates) {
|
if (newTemplates != templates) {
|
||||||
@@ -51,12 +51,17 @@ class ScriptTemplatesFromDependenciesProvider(project: Project) : AsyncScriptDef
|
|||||||
return@write null
|
return@write null
|
||||||
}
|
}
|
||||||
if (templatesCopy != null) {
|
if (templatesCopy != null) {
|
||||||
|
val hostConfiguration = ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration) {
|
||||||
|
getEnvironment {
|
||||||
|
mapOf(
|
||||||
|
"projectRoot" to (project.basePath ?: project.baseDir.canonicalPath)?.let(::File)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
return loadDefinitionsFromTemplates(
|
return loadDefinitionsFromTemplates(
|
||||||
templateClassNames = templatesCopy.templates,
|
templateClassNames = templatesCopy.templates,
|
||||||
templateClasspath = templatesCopy.classpath,
|
templateClasspath = templatesCopy.classpath,
|
||||||
environment = mapOf(
|
baseHostConfiguration = hostConfiguration
|
||||||
"projectRoot" to (project.basePath ?: project.baseDir.canonicalPath)?.let(::File)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return previous ?: emptyList()
|
return previous ?: emptyList()
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ import org.jetbrains.kotlin.resolve.scopes.utils.findVariable
|
|||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.script.experimental.api.valueOrNull
|
||||||
|
|
||||||
class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper() {
|
class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper() {
|
||||||
|
|
||||||
@@ -64,8 +65,9 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
|
|||||||
val allDefaultImports = platform.findAnalyzerServices.getDefaultImports(languageVersionSettings, includeLowPriorityImports = true)
|
val allDefaultImports = platform.findAnalyzerServices.getDefaultImports(languageVersionSettings, includeLowPriorityImports = true)
|
||||||
|
|
||||||
val scriptExtraImports = contextFile.takeIf { it.isScript() }?.let { ktFile ->
|
val scriptExtraImports = contextFile.takeIf { it.isScript() }?.let { ktFile ->
|
||||||
val scriptDependencies = ScriptDependenciesProvider.getInstance(ktFile.project)?.getScriptDependencies(ktFile.originalFile)
|
val scriptDependencies =
|
||||||
scriptDependencies?.imports?.map { ImportPath.fromString(it) }
|
ScriptDependenciesProvider.getInstance(ktFile.project)?.getScriptConfigurationResult(ktFile.originalFile)?.valueOrNull()
|
||||||
|
scriptDependencies?.defaultImports?.map { ImportPath.fromString(it) }
|
||||||
}.orEmpty()
|
}.orEmpty()
|
||||||
|
|
||||||
return importPath.isImported(allDefaultImports + scriptExtraImports, platform.findAnalyzerServices.excludedImports)
|
return importPath.isImported(allDefaultImports + scriptExtraImports, platform.findAnalyzerServices.excludedImports)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
<error descr="TestDependenciesResolver threw exception IllegalStateException:
|
<error descr="Exception from resolver (java.lang.IllegalStateException: Exception from resolver)"></error>
|
||||||
Exception from resolver"></error>
|
|
||||||
val s = 3
|
val s = 3
|
||||||
val g = 4
|
val g = 4
|
||||||
+3
-3
@@ -22,7 +22,7 @@ import com.intellij.testFramework.LightProjectDescriptor;
|
|||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesUpdaterKt;
|
import org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationUpdaterKt;
|
||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils;
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils;
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
import org.jetbrains.plugins.groovy.GroovyFileType;
|
import org.jetbrains.plugins.groovy.GroovyFileType;
|
||||||
@@ -42,12 +42,12 @@ public abstract class AbstractConfigureProjectByChangingFileTest<C extends Kotli
|
|||||||
ApplicationManager.getApplication().runWriteAction(
|
ApplicationManager.getApplication().runWriteAction(
|
||||||
() -> FileTypeManager.getInstance().associateExtension(GroovyFileType.GROOVY_FILE_TYPE, "gradle")
|
() -> FileTypeManager.getInstance().associateExtension(GroovyFileType.GROOVY_FILE_TYPE, "gradle")
|
||||||
);
|
);
|
||||||
ScriptDependenciesUpdaterKt.setScriptDependenciesUpdaterDisabled(ApplicationManager.getApplication(), true);
|
ScriptsCompilationConfigurationUpdaterKt.setScriptDependenciesUpdaterDisabled(ApplicationManager.getApplication(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void tearDown() throws Exception {
|
protected void tearDown() throws Exception {
|
||||||
ScriptDependenciesUpdaterKt.setScriptDependenciesUpdaterDisabled(ApplicationManager.getApplication(), false);
|
ScriptsCompilationConfigurationUpdaterKt.setScriptDependenciesUpdaterDisabled(ApplicationManager.getApplication(), false);
|
||||||
moduleInfoFile = null;
|
moduleInfoFile = null;
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,32 +5,41 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.script
|
package org.jetbrains.kotlin.idea.script
|
||||||
|
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionSourceAsContributor
|
||||||
import org.jetbrains.kotlin.idea.core.script.loadDefinitionsFromTemplates
|
import org.jetbrains.kotlin.idea.core.script.loadDefinitionsFromTemplates
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.getEnvironment
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.script.dependencies.Environment
|
import kotlin.script.dependencies.Environment
|
||||||
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
|
|
||||||
class CustomScriptTemplateProvider(
|
class CustomScriptTemplateProvider(val environment: Environment) : ScriptDefinitionSourceAsContributor {
|
||||||
val environment: Environment
|
|
||||||
) : ScriptDefinitionContributor {
|
|
||||||
override val id = "Test"
|
override val id = "Test"
|
||||||
|
|
||||||
override fun getDefinitions() = loadDefinitionsFromTemplates(
|
override val definitions: Sequence<ScriptDefinition>
|
||||||
|
get() = loadDefinitionsFromTemplates(
|
||||||
templateClassNames = environment["template-classes-names"] as List<String>,
|
templateClassNames = environment["template-classes-names"] as List<String>,
|
||||||
templateClasspath = listOfNotNull(environment["template-classes"] as? File),
|
templateClasspath = listOfNotNull(environment["template-classes"] as? File),
|
||||||
environment = environment
|
baseHostConfiguration = ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration) {
|
||||||
)
|
getEnvironment { environment }
|
||||||
|
}
|
||||||
|
).asSequence()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class FromTextTemplateProvider(
|
class FromTextTemplateProvider(val environment: Map<String, Any?>) : ScriptDefinitionSourceAsContributor {
|
||||||
val environment: Map<String, Any?>
|
|
||||||
) : ScriptDefinitionContributor {
|
|
||||||
override val id = "Test"
|
override val id = "Test"
|
||||||
override fun getDefinitions() = loadDefinitionsFromTemplates(
|
|
||||||
|
override val definitions: Sequence<ScriptDefinition>
|
||||||
|
get() = loadDefinitionsFromTemplates(
|
||||||
templateClassNames = listOf("org.jetbrains.kotlin.idea.script.Template"),
|
templateClassNames = listOf("org.jetbrains.kotlin.idea.script.Template"),
|
||||||
templateClasspath = listOfNotNull(environment["template-classes"] as? File),
|
templateClasspath = listOfNotNull(environment["template-classes"] as? File),
|
||||||
environment = environment
|
baseHostConfiguration = ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration) {
|
||||||
)
|
getEnvironment { environment }
|
||||||
|
}
|
||||||
|
).asSequence()
|
||||||
}
|
}
|
||||||
@@ -76,6 +76,10 @@ sealed class ResultWithDiagnostics<out R> {
|
|||||||
) : ResultWithDiagnostics<Nothing>() {
|
) : ResultWithDiagnostics<Nothing>() {
|
||||||
constructor(vararg reports: ScriptDiagnostic) : this(reports.asList())
|
constructor(vararg reports: ScriptDiagnostic) : this(reports.asList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean = this === other || (other is ResultWithDiagnostics<*> && this.reports == other.reports)
|
||||||
|
|
||||||
|
override fun hashCode(): Int = reports.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -162,9 +166,10 @@ fun makeFailureResult(message: String, path: String? = null, location: SourceCod
|
|||||||
fun Throwable.asDiagnostics(
|
fun Throwable.asDiagnostics(
|
||||||
customMessage: String? = null,
|
customMessage: String? = null,
|
||||||
path: String? = null,
|
path: String? = null,
|
||||||
location: SourceCode.Location? = null
|
location: SourceCode.Location? = null,
|
||||||
|
severity: ScriptDiagnostic.Severity = ScriptDiagnostic.Severity.ERROR
|
||||||
): ScriptDiagnostic =
|
): ScriptDiagnostic =
|
||||||
ScriptDiagnostic(customMessage ?: message ?: "$this", ScriptDiagnostic.Severity.ERROR, path, location, this)
|
ScriptDiagnostic(customMessage ?: message ?: "$this", severity, path, location, this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the receiver String to error diagnostic report with optional [path] and [location]
|
* Converts the receiver String to error diagnostic report with optional [path] and [location]
|
||||||
@@ -175,7 +180,7 @@ fun String.asErrorDiagnostics(path: String? = null, location: SourceCode.Locatio
|
|||||||
/**
|
/**
|
||||||
* Extracts the result value from the receiver wrapper or null if receiver represents a Failure
|
* Extracts the result value from the receiver wrapper or null if receiver represents a Failure
|
||||||
*/
|
*/
|
||||||
fun <R> ResultWithDiagnostics<R>.resultOrNull(): R? = when (this) {
|
fun <R> ResultWithDiagnostics<R>.valueOrNull(): R? = when (this) {
|
||||||
is ResultWithDiagnostics.Success<R> -> value
|
is ResultWithDiagnostics.Success<R> -> value
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
@@ -183,7 +188,7 @@ fun <R> ResultWithDiagnostics<R>.resultOrNull(): R? = when (this) {
|
|||||||
/**
|
/**
|
||||||
* Extracts the result value from the receiver wrapper or run non-returning lambda if receiver represents a Failure
|
* Extracts the result value from the receiver wrapper or run non-returning lambda if receiver represents a Failure
|
||||||
*/
|
*/
|
||||||
inline fun <R> ResultWithDiagnostics<R>.resultOr(body: (ResultWithDiagnostics.Failure) -> Nothing): R = when (this) {
|
inline fun <R> ResultWithDiagnostics<R>.valueOr(body: (ResultWithDiagnostics.Failure) -> Nothing): R = when (this) {
|
||||||
is ResultWithDiagnostics.Success<R> -> value
|
is ResultWithDiagnostics.Success<R> -> value
|
||||||
is ResultWithDiagnostics.Failure -> body(this)
|
is ResultWithDiagnostics.Failure -> body(this)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ val ScriptCompilationConfigurationKeys.fileExtension by PropertiesCollection.key
|
|||||||
/**
|
/**
|
||||||
* The superclass for target script class
|
* The superclass for target script class
|
||||||
*/
|
*/
|
||||||
val ScriptCompilationConfigurationKeys.baseClass by PropertiesCollection.key<KotlinType>() // script base class
|
val ScriptCompilationConfigurationKeys.baseClass by PropertiesCollection.key<KotlinType>(KotlinType(Any::class)) // script base class
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of classes that will be used as implicit receivers in the script body, as if the whole body is wrapped with "with" calls:
|
* The list of classes that will be used as implicit receivers in the script body, as if the whole body is wrapped with "with" calls:
|
||||||
|
|||||||
@@ -41,10 +41,14 @@ fun getMergedScriptText(script: SourceCode, configuration: ScriptCompilationConf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class FileBasedScriptSource() : ExternalSourceCode {
|
||||||
|
abstract val file: File
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The implementation of the SourceCode for a script located in a file
|
* The implementation of the SourceCode for a script located in a file
|
||||||
*/
|
*/
|
||||||
open class FileScriptSource(val file: File, private val preloadedText: String? = null) : ExternalSourceCode {
|
open class FileScriptSource(override val file: File, private val preloadedText: String? = null) : FileBasedScriptSource() {
|
||||||
override val externalLocation: URL get() = file.toURI().toURL()
|
override val externalLocation: URL get() = file.toURI().toURL()
|
||||||
override val text: String by lazy { preloadedText ?: file.readText() }
|
override val text: String by lazy { preloadedText ?: file.readText() }
|
||||||
override val name: String? get() = file.name
|
override val name: String? get() = file.name
|
||||||
|
|||||||
+7
-7
@@ -18,13 +18,13 @@ import java.util.jar.JarFile
|
|||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
import kotlin.script.experimental.host.BasicScriptingHost
|
import kotlin.script.experimental.host.BasicScriptingHost
|
||||||
import kotlin.script.experimental.host.FileScriptSource
|
import kotlin.script.experimental.host.FileBasedScriptSource
|
||||||
import kotlin.script.experimental.host.toScriptSource
|
import kotlin.script.experimental.host.toScriptSource
|
||||||
import kotlin.script.experimental.jvm.BasicJvmScriptEvaluator
|
import kotlin.script.experimental.jvm.BasicJvmScriptEvaluator
|
||||||
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
||||||
import kotlin.script.experimental.jvmhost.*
|
import kotlin.script.experimental.jvmhost.*
|
||||||
import kotlin.script.experimental.jvmhost.impl.CompiledScriptClassLoader
|
import kotlin.script.experimental.jvmhost.impl.CompiledScriptClassLoader
|
||||||
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
|
||||||
import kotlin.script.templates.standard.SimpleScriptTemplate
|
import kotlin.script.templates.standard.SimpleScriptTemplate
|
||||||
|
|
||||||
class ScriptingHostTest : TestCase() {
|
class ScriptingHostTest : TestCase() {
|
||||||
@@ -86,7 +86,7 @@ class ScriptingHostTest : TestCase() {
|
|||||||
val scriptName = "SavedRunnableScript"
|
val scriptName = "SavedRunnableScript"
|
||||||
val compiledScript = runBlocking {
|
val compiledScript = runBlocking {
|
||||||
compiler("println(\"$greeting\")".toScriptSource(name = "$scriptName.kts"), compilationConfiguration).throwOnFailure()
|
compiler("println(\"$greeting\")".toScriptSource(name = "$scriptName.kts"), compilationConfiguration).throwOnFailure()
|
||||||
.resultOrNull()!!
|
.valueOrNull()!!
|
||||||
}
|
}
|
||||||
val saver = BasicJvmScriptJarGenerator(outJar)
|
val saver = BasicJvmScriptJarGenerator(outJar)
|
||||||
runBlocking {
|
runBlocking {
|
||||||
@@ -353,8 +353,8 @@ class ScriptingHostTest : TestCase() {
|
|||||||
val compiledScriptClassRes = runBlocking { compiledScript!!.getClass(null) }
|
val compiledScriptClassRes = runBlocking { compiledScript!!.getClass(null) }
|
||||||
val cachedScriptClassRes = runBlocking { cachedScript!!.getClass(null) }
|
val cachedScriptClassRes = runBlocking { cachedScript!!.getClass(null) }
|
||||||
|
|
||||||
val compiledScriptClass = compiledScriptClassRes.resultOrNull()
|
val compiledScriptClass = compiledScriptClassRes.valueOrNull()
|
||||||
val cachedScriptClass = cachedScriptClassRes.resultOrNull()
|
val cachedScriptClass = cachedScriptClassRes.valueOrNull()
|
||||||
|
|
||||||
Assert.assertEquals(compiledScriptClass!!.qualifiedName, cachedScriptClass!!.qualifiedName)
|
Assert.assertEquals(compiledScriptClass!!.qualifiedName, cachedScriptClass!!.qualifiedName)
|
||||||
Assert.assertEquals(compiledScriptClass!!.supertypes, cachedScriptClass!!.supertypes)
|
Assert.assertEquals(compiledScriptClass!!.supertypes, cachedScriptClass!!.supertypes)
|
||||||
@@ -380,7 +380,7 @@ class ScriptingHostTest : TestCase() {
|
|||||||
val res = compiler(script.toScriptSource(), scriptCompilationConfiguration).throwOnFailure()
|
val res = compiler(script.toScriptSource(), scriptCompilationConfiguration).throwOnFailure()
|
||||||
(res as ResultWithDiagnostics.Success<CompiledScript<*>>).value
|
(res as ResultWithDiagnostics.Success<CompiledScript<*>>).value
|
||||||
}
|
}
|
||||||
val compiledScriptClass = runBlocking { compiledScript.getClass(null).throwOnFailure().resultOrNull()!! as KClass<*> }
|
val compiledScriptClass = runBlocking { compiledScript.getClass(null).throwOnFailure().valueOrNull()!! as KClass<*> }
|
||||||
val classLoader = compiledScriptClass.java.classLoader
|
val classLoader = compiledScriptClass.java.classLoader
|
||||||
|
|
||||||
Assert.assertTrue(classLoader is CompiledScriptClassLoader)
|
Assert.assertTrue(classLoader is CompiledScriptClassLoader)
|
||||||
@@ -463,7 +463,7 @@ private fun ScriptCompilationConfiguration.Builder.makeSimpleConfigurationWithTe
|
|||||||
refineConfiguration {
|
refineConfiguration {
|
||||||
beforeCompiling { ctx ->
|
beforeCompiling { ctx ->
|
||||||
val importedScript = File(ScriptingHostTest.TEST_DATA_DIR, "importTest/helloWithVal.kts")
|
val importedScript = File(ScriptingHostTest.TEST_DATA_DIR, "importTest/helloWithVal.kts")
|
||||||
if ((ctx.script as? FileScriptSource)?.file?.canonicalFile == importedScript.canonicalFile) {
|
if ((ctx.script as? FileBasedScriptSource)?.file?.canonicalFile == importedScript.canonicalFile) {
|
||||||
ctx.compilationConfiguration
|
ctx.compilationConfiguration
|
||||||
} else {
|
} else {
|
||||||
ScriptCompilationConfiguration(ctx.compilationConfiguration) {
|
ScriptCompilationConfiguration(ctx.compilationConfiguration) {
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ class KJvmCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) : KJvm
|
|||||||
|
|
||||||
val mainKtFile =
|
val mainKtFile =
|
||||||
getScriptKtFile(script, context.baseScriptCompilationConfiguration, context.environment.project, messageCollector)
|
getScriptKtFile(script, context.baseScriptCompilationConfiguration, context.environment.project, messageCollector)
|
||||||
.resultOr { return it }
|
.valueOr { return it }
|
||||||
|
|
||||||
context.scriptCompilationState.configureFor(script, context.baseScriptCompilationConfiguration)
|
context.scriptCompilationState.configureFor(script, context.baseScriptCompilationConfiguration)
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -31,7 +31,7 @@ class KJvmReplCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) :
|
|||||||
override fun createReplCompilationState(scriptCompilationConfiguration: ScriptCompilationConfiguration): JvmReplCompilerState.Compilation {
|
override fun createReplCompilationState(scriptCompilationConfiguration: ScriptCompilationConfiguration): JvmReplCompilerState.Compilation {
|
||||||
val context = withMessageCollectorAndDisposable(disposeOnSuccess = false) { messageCollector, disposable ->
|
val context = withMessageCollectorAndDisposable(disposeOnSuccess = false) { messageCollector, disposable ->
|
||||||
createSharedCompilationContext(scriptCompilationConfiguration, hostConfiguration, messageCollector, disposable).asSuccess()
|
createSharedCompilationContext(scriptCompilationConfiguration, hostConfiguration, messageCollector, disposable).asSuccess()
|
||||||
}.resultOr { throw IllegalStateException("Unable to initialize repl compiler:\n ${it.reports.joinToString("\n ")}") }
|
}.valueOr { throw IllegalStateException("Unable to initialize repl compiler:\n ${it.reports.joinToString("\n ")}") }
|
||||||
return ReplCompilationState(context)
|
return ReplCompilationState(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ class KJvmReplCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) :
|
|||||||
): ResultWithDiagnostics<Boolean> =
|
): ResultWithDiagnostics<Boolean> =
|
||||||
withMessageCollector(script) { messageCollector ->
|
withMessageCollector(script) { messageCollector ->
|
||||||
val ktFile = getScriptKtFile(script, scriptCompilationConfiguration, project, messageCollector)
|
val ktFile = getScriptKtFile(script, scriptCompilationConfiguration, project, messageCollector)
|
||||||
.resultOr { return it }
|
.valueOr { return it }
|
||||||
val errorHolder = object : MessageCollectorBasedReporter {
|
val errorHolder = object : MessageCollectorBasedReporter {
|
||||||
override val messageCollector = messageCollector
|
override val messageCollector = messageCollector
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ class KJvmReplCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) :
|
|||||||
|
|
||||||
val snippetKtFile =
|
val snippetKtFile =
|
||||||
getScriptKtFile(snippet, context.baseScriptCompilationConfiguration, context.environment.project, messageCollector)
|
getScriptKtFile(snippet, context.baseScriptCompilationConfiguration, context.environment.project, messageCollector)
|
||||||
.resultOr { return it }
|
.valueOr { return it }
|
||||||
|
|
||||||
val (sourceFiles, sourceDependencies) = collectRefinedSourcesAndUpdateEnvironment(context, snippetKtFile, messageCollector)
|
val (sourceFiles, sourceDependencies) = collectRefinedSourcesAndUpdateEnvironment(context, snippetKtFile, messageCollector)
|
||||||
|
|
||||||
|
|||||||
+7
-3
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.config.JvmTarget
|
|||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar
|
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar
|
||||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.dependencies.ScriptsCompilationDependencies
|
import org.jetbrains.kotlin.scripting.dependencies.ScriptsCompilationDependencies
|
||||||
import org.jetbrains.kotlin.scripting.dependencies.collectScriptsCompilationDependencies
|
import org.jetbrains.kotlin.scripting.dependencies.collectScriptsCompilationDependencies
|
||||||
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
||||||
@@ -88,10 +89,13 @@ internal fun createInitialConfigurations(
|
|||||||
|
|
||||||
kotlinCompilerConfiguration.add(
|
kotlinCompilerConfiguration.add(
|
||||||
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS,
|
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS,
|
||||||
BridgeScriptDefinition(
|
ScriptDefinition.FromLegacy(
|
||||||
scriptCompilationConfiguration,
|
|
||||||
hostConfiguration,
|
hostConfiguration,
|
||||||
scriptCompilationState
|
BridgeScriptDefinition(
|
||||||
|
scriptCompilationConfiguration,
|
||||||
|
hostConfiguration,
|
||||||
|
scriptCompilationState
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+3
-15
@@ -8,11 +8,8 @@ package kotlin.script.experimental.jvmhost.impl
|
|||||||
import com.intellij.openapi.Disposable
|
import com.intellij.openapi.Disposable
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.Disposer
|
import com.intellij.openapi.util.Disposer
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
|
||||||
import com.intellij.openapi.vfs.CharsetToolkit
|
|
||||||
import com.intellij.psi.PsiFileFactory
|
import com.intellij.psi.PsiFileFactory
|
||||||
import com.intellij.psi.impl.PsiFileFactoryImpl
|
import com.intellij.psi.impl.PsiFileFactoryImpl
|
||||||
import com.intellij.testFramework.LightVirtualFile
|
|
||||||
import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback
|
import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
@@ -20,24 +17,15 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
import org.jetbrains.kotlin.psi.KtScript
|
import org.jetbrains.kotlin.psi.KtScript
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.scripting.dependencies.ScriptsCompilationDependencies
|
import org.jetbrains.kotlin.scripting.dependencies.ScriptsCompilationDependencies
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.ScriptLightVirtualFile
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
|
import kotlin.script.experimental.host.FileBasedScriptSource
|
||||||
import kotlin.script.experimental.host.FileScriptSource
|
import kotlin.script.experimental.host.FileScriptSource
|
||||||
import kotlin.script.experimental.host.getMergedScriptText
|
import kotlin.script.experimental.host.getMergedScriptText
|
||||||
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
||||||
|
|
||||||
internal class ScriptLightVirtualFile(name: String, private val _path: String?, text: String) :
|
|
||||||
LightVirtualFile(name, KotlinLanguage.INSTANCE, StringUtil.convertLineSeparators(text)) {
|
|
||||||
|
|
||||||
init {
|
|
||||||
charset = CharsetToolkit.UTF8_CHARSET
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getPath(): String = _path ?: super.getPath()
|
|
||||||
override fun getCanonicalPath(): String? = path
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun makeCompiledModule(generationState: GenerationState) =
|
internal fun makeCompiledModule(generationState: GenerationState) =
|
||||||
KJvmCompiledModuleInMemory(
|
KJvmCompiledModuleInMemory(
|
||||||
generationState.factory.asList()
|
generationState.factory.asList()
|
||||||
@@ -98,7 +86,7 @@ internal fun getScriptKtFile(
|
|||||||
val scriptText = getMergedScriptText(script, scriptCompilationConfiguration)
|
val scriptText = getMergedScriptText(script, scriptCompilationConfiguration)
|
||||||
val virtualFile = ScriptLightVirtualFile(
|
val virtualFile = ScriptLightVirtualFile(
|
||||||
script.scriptFileName(script, scriptCompilationConfiguration),
|
script.scriptFileName(script, scriptCompilationConfiguration),
|
||||||
(script as? FileScriptSource)?.file?.path,
|
(script as? FileBasedScriptSource)?.file?.path,
|
||||||
scriptText
|
scriptText
|
||||||
)
|
)
|
||||||
val ktFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile?
|
val ktFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile?
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ open class BasicJvmScriptEvaluator : ScriptEvaluator {
|
|||||||
?.onFailure {
|
?.onFailure {
|
||||||
return@invoke ResultWithDiagnostics.Failure(it.reports)
|
return@invoke ResultWithDiagnostics.Failure(it.reports)
|
||||||
}
|
}
|
||||||
?.resultOrNull()
|
?.valueOrNull()
|
||||||
?: configuration
|
?: configuration
|
||||||
|
|
||||||
val instance =
|
val instance =
|
||||||
|
|||||||
+7
-2
@@ -48,8 +48,13 @@ fun mapLegacyScriptPosition(pos: ScriptReport.Position?): SourceCode.Location? =
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun mapToLegacyScriptReportPosition(pos: SourceCode.Location?): ScriptReport.Position? =
|
fun mapToLegacyScriptReportPosition(pos: SourceCode.Location?): ScriptReport.Position? =
|
||||||
pos?.let { ScriptReport.Position(pos.start.line, pos.start.col) }
|
pos?.let { ScriptReport.Position(pos.start.line, pos.start.col, pos.end?.line, pos.end?.col) }
|
||||||
|
|
||||||
fun Iterable<ScriptReport>.mapToDiagnostics(): List<ScriptDiagnostic> = map { (message, severity, position: ScriptReport.Position?) ->
|
fun Iterable<ScriptReport>.mapToDiagnostics(): List<ScriptDiagnostic> = map { (message, severity, position) ->
|
||||||
ScriptDiagnostic(message, mapLegacyDiagnosticSeverity(severity), null, mapLegacyScriptPosition(position))
|
ScriptDiagnostic(message, mapLegacyDiagnosticSeverity(severity), null, mapLegacyScriptPosition(position))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Iterable<ScriptDiagnostic>.mapToLegacyReports(): List<ScriptReport> = map { (message, severity, _, location, exception) ->
|
||||||
|
val reportMessage = if (exception == null) message else "$message ($exception)"
|
||||||
|
ScriptReport(reportMessage, mapToLegacyScriptReportSeverity(severity), mapToLegacyScriptReportPosition(location))
|
||||||
|
}
|
||||||
|
|||||||
+12
-11
@@ -41,16 +41,6 @@ class BridgeDependenciesResolver(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val defaultImports = scriptCompilationConfiguration[ScriptCompilationConfiguration.defaultImports]?.toList() ?: emptyList()
|
|
||||||
|
|
||||||
fun ScriptCompilationConfiguration.toDependencies(classpath: List<File>): ScriptDependencies =
|
|
||||||
ScriptDependencies(
|
|
||||||
classpath = classpath,
|
|
||||||
sources = this[ScriptCompilationConfiguration.ide.dependenciesSources].toClassPathOrEmpty(),
|
|
||||||
imports = defaultImports,
|
|
||||||
scripts = this[ScriptCompilationConfiguration.importScripts].toFilesOrEmpty()
|
|
||||||
)
|
|
||||||
|
|
||||||
val script = getScriptSource(scriptContents) ?: scriptContents.toScriptSource()
|
val script = getScriptSource(scriptContents) ?: scriptContents.toScriptSource()
|
||||||
|
|
||||||
val refineResults = scriptCompilationConfiguration.refineWith(
|
val refineResults = scriptCompilationConfiguration.refineWith(
|
||||||
@@ -92,6 +82,17 @@ class BridgeDependenciesResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ScriptCompilationConfiguration.toDependencies(classpath: List<File>): ScriptDependencies {
|
||||||
|
val defaultImports = this[ScriptCompilationConfiguration.defaultImports]?.toList() ?: emptyList()
|
||||||
|
|
||||||
|
return ScriptDependencies(
|
||||||
|
classpath = classpath,
|
||||||
|
sources = this[ScriptCompilationConfiguration.ide.dependenciesSources].toClassPathOrEmpty(),
|
||||||
|
imports = defaultImports,
|
||||||
|
scripts = this[ScriptCompilationConfiguration.importScripts].toFilesOrEmpty()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
internal fun List<ScriptDiagnostic>.mapScriptReportsToDiagnostics() =
|
internal fun List<ScriptDiagnostic>.mapScriptReportsToDiagnostics() =
|
||||||
map { ScriptReport(it.message, mapToLegacyScriptReportSeverity(it.severity), mapToLegacyScriptReportPosition(it.location)) }
|
map { ScriptReport(it.message, mapToLegacyScriptReportSeverity(it.severity), mapToLegacyScriptReportPosition(it.location)) }
|
||||||
|
|
||||||
@@ -101,7 +102,7 @@ internal fun ScriptContents.toScriptSource(): SourceCode = when {
|
|||||||
else -> throw IllegalArgumentException("Unable to convert script contents $this into script source")
|
else -> throw IllegalArgumentException("Unable to convert script contents $this into script source")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun List<ScriptDependency>?.toClassPathOrEmpty() = this?.flatMap { (it as JvmDependency).classpath } ?: emptyList()
|
fun List<ScriptDependency>?.toClassPathOrEmpty() = this?.flatMap { (it as JvmDependency).classpath } ?: emptyList()
|
||||||
|
|
||||||
internal fun List<SourceCode>?.toFilesOrEmpty() = this?.map {
|
internal fun List<SourceCode>?.toFilesOrEmpty() = this?.map {
|
||||||
val externalSource = it as? ExternalSourceCode
|
val externalSource = it as? ExternalSourceCode
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ package kotlin.script.experimental.jvm
|
|||||||
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
import kotlin.script.experimental.util.PropertiesCollection
|
import kotlin.script.experimental.util.PropertiesCollection
|
||||||
|
|
||||||
interface JvmScriptEvaluationConfigurationKeys
|
interface JvmScriptEvaluationConfigurationKeys
|
||||||
@@ -21,7 +22,10 @@ open class JvmScriptEvaluationConfigurationBuilder : PropertiesCollection.Builde
|
|||||||
/**
|
/**
|
||||||
* The base classloader to use for script classes loading
|
* The base classloader to use for script classes loading
|
||||||
*/
|
*/
|
||||||
val JvmScriptEvaluationConfigurationKeys.baseClassLoader by PropertiesCollection.key<ClassLoader?>(Thread.currentThread().contextClassLoader)
|
val JvmScriptEvaluationConfigurationKeys.baseClassLoader by PropertiesCollection.key<ClassLoader?> {
|
||||||
|
get(ScriptEvaluationConfiguration.hostConfiguration)?.get(ScriptingHostConfiguration.jvm.baseClassLoader)
|
||||||
|
?: Thread.currentThread().contextClassLoader
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load script dependencies before evaluation, true by default
|
* Load script dependencies before evaluation, true by default
|
||||||
|
|||||||
+16
-7
@@ -11,6 +11,7 @@ import java.net.URLClassLoader
|
|||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
import kotlin.script.experimental.host.*
|
import kotlin.script.experimental.host.*
|
||||||
|
import kotlin.script.experimental.jvm.impl.toClassPathOrEmpty
|
||||||
import kotlin.script.experimental.util.PropertiesCollection
|
import kotlin.script.experimental.util.PropertiesCollection
|
||||||
|
|
||||||
interface JvmScriptingHostConfigurationKeys
|
interface JvmScriptingHostConfigurationKeys
|
||||||
@@ -25,6 +26,12 @@ val JvmScriptingHostConfigurationKeys.javaHome by PropertiesCollection.key<File>
|
|||||||
|
|
||||||
val JvmScriptingHostConfigurationKeys.jdkHome by PropertiesCollection.key<File>()
|
val JvmScriptingHostConfigurationKeys.jdkHome by PropertiesCollection.key<File>()
|
||||||
|
|
||||||
|
val JvmScriptingHostConfigurationKeys.baseClassLoader by PropertiesCollection.key<ClassLoader> {
|
||||||
|
get(ScriptingHostConfiguration.configurationDependencies)?.let {
|
||||||
|
URLClassLoader(it.toClassPathOrEmpty().map { f -> f.toURI().toURL() }.toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val ScriptingHostConfigurationKeys.jvm
|
val ScriptingHostConfigurationKeys.jvm
|
||||||
get() = JvmScriptingHostConfigurationBuilder()
|
get() = JvmScriptingHostConfigurationBuilder()
|
||||||
@@ -49,15 +56,17 @@ class JvmGetScriptingClass : GetScriptingClass, Serializable {
|
|||||||
@Transient
|
@Transient
|
||||||
private var baseClassLoader: ClassLoader? = null
|
private var baseClassLoader: ClassLoader? = null
|
||||||
|
|
||||||
|
override fun invoke(classType: KotlinType, contextClass: KClass<*>, hostConfiguration: ScriptingHostConfiguration): KClass<*> =
|
||||||
|
invoke(classType, contextClass.java.classLoader, hostConfiguration)
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun invoke(classType: KotlinType, contextClass: KClass<*>, hostConfiguration: ScriptingHostConfiguration): KClass<*> {
|
operator fun invoke(classType: KotlinType, contextClassLoader: ClassLoader?, hostConfiguration: ScriptingHostConfiguration): KClass<*> {
|
||||||
|
|
||||||
// checking if class already loaded in the same context
|
// checking if class already loaded in the same context
|
||||||
val contextClassloader = contextClass.java.classLoader
|
|
||||||
val fromClass = classType.fromClass
|
val fromClass = classType.fromClass
|
||||||
if (fromClass != null) {
|
if (fromClass != null) {
|
||||||
if (fromClass.java.classLoader == null) return fromClass // root classloader
|
if (fromClass.java.classLoader == null) return fromClass // root classloader
|
||||||
val actualClassLoadersChain = generateSequence(contextClassloader) { it.parent }
|
val actualClassLoadersChain = generateSequence(contextClassLoader) { it.parent }
|
||||||
if (actualClassLoadersChain.any { it == fromClass.java.classLoader }) return fromClass
|
if (actualClassLoadersChain.any { it == fromClass.java.classLoader }) return fromClass
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +80,7 @@ class JvmGetScriptingClass : GetScriptingClass, Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (baseClassLoaderIsInitialized != true) {
|
if (baseClassLoaderIsInitialized != true) {
|
||||||
baseClassLoader = contextClassloader
|
baseClassLoader = contextClassLoader
|
||||||
baseClassLoaderIsInitialized = true
|
baseClassLoaderIsInitialized = true
|
||||||
}
|
}
|
||||||
// TODO: this check breaks testLazyScriptDefinition, find out the reason and fix
|
// TODO: this check breaks testLazyScriptDefinition, find out the reason and fix
|
||||||
@@ -88,12 +97,12 @@ class JvmGetScriptingClass : GetScriptingClass, Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
classLoader =
|
classLoader =
|
||||||
if (classpath == null || classpath.isEmpty()) baseClassLoader
|
if (classpath == null || classpath.isEmpty()) baseClassLoader
|
||||||
else URLClassLoader(classpath.toTypedArray(), baseClassLoader)
|
else URLClassLoader(classpath.toTypedArray(), baseClassLoader)
|
||||||
}
|
}
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
classLoader!!.loadClass(classType.typeName).kotlin
|
(classLoader ?: ClassLoader.getSystemClassLoader()).loadClass(classType.typeName).kotlin
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
throw IllegalArgumentException("unable to load class $classType", e)
|
throw IllegalArgumentException("unable to load class $classType", e)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
|
|||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource
|
||||||
import org.jetbrains.kotlin.scripting.definitions.reporter
|
import org.jetbrains.kotlin.scripting.definitions.reporter
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
private const val MIN_SUPPORTED_GRADLE_MAJOR_VERSION = 5
|
private const val MIN_SUPPORTED_GRADLE_MAJOR_VERSION = 5
|
||||||
private const val MIN_SUPPORTED_GRADLE_MINOR_VERSION = 0
|
private const val MIN_SUPPORTED_GRADLE_MINOR_VERSION = 0
|
||||||
@@ -166,7 +167,8 @@ internal class DiscoverScriptExtensionsTransform : ArtifactTransform() {
|
|||||||
override fun transform(input: File): List<File> {
|
override fun transform(input: File): List<File> {
|
||||||
val definitions =
|
val definitions =
|
||||||
ScriptDefinitionsFromClasspathDiscoverySource(
|
ScriptDefinitionsFromClasspathDiscoverySource(
|
||||||
listOf(input), emptyMap(),
|
listOf(input),
|
||||||
|
defaultJvmScriptingHostConfiguration,
|
||||||
PrintingMessageCollector(System.out, MessageRenderer.WITHOUT_PATHS, false).reporter
|
PrintingMessageCollector(System.out, MessageRenderer.WITHOUT_PATHS, false).reporter
|
||||||
).definitions
|
).definitions
|
||||||
val extensions = definitions.mapTo(arrayListOf()) { it.fileExtension }
|
val extensions = definitions.mapTo(arrayListOf()) { it.fileExtension }
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import kotlin.script.dependencies.ScriptContents
|
|||||||
import kotlin.script.dependencies.ScriptDependenciesResolver
|
import kotlin.script.dependencies.ScriptDependenciesResolver
|
||||||
import kotlin.script.experimental.annotations.KotlinScript
|
import kotlin.script.experimental.annotations.KotlinScript
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
|
import kotlin.script.experimental.host.FileBasedScriptSource
|
||||||
import kotlin.script.experimental.host.FileScriptSource
|
import kotlin.script.experimental.host.FileScriptSource
|
||||||
import kotlin.script.experimental.jvm.compat.mapLegacyDiagnosticSeverity
|
import kotlin.script.experimental.jvm.compat.mapLegacyDiagnosticSeverity
|
||||||
import kotlin.script.experimental.jvm.compat.mapLegacyScriptPosition
|
import kotlin.script.experimental.jvm.compat.mapLegacyScriptPosition
|
||||||
@@ -59,7 +60,7 @@ class MainKtsConfigurator : RefineScriptCompilationConfigurationHandler {
|
|||||||
val annotations = context.collectedData?.get(ScriptCollectedData.foundAnnotations)?.takeIf { it.isNotEmpty() }
|
val annotations = context.collectedData?.get(ScriptCollectedData.foundAnnotations)?.takeIf { it.isNotEmpty() }
|
||||||
?: return context.compilationConfiguration.asSuccess()
|
?: return context.compilationConfiguration.asSuccess()
|
||||||
|
|
||||||
val scriptBaseDir = (context.script as? FileScriptSource)?.file?.parentFile
|
val scriptBaseDir = (context.script as? FileBasedScriptSource)?.file?.parentFile
|
||||||
val importedSources = annotations.flatMap {
|
val importedSources = annotations.flatMap {
|
||||||
(it as? Import)?.paths?.map { sourceName ->
|
(it as? Import)?.paths?.map { sourceName ->
|
||||||
FileScriptSource(scriptBaseDir?.resolve(sourceName) ?: File(sourceName))
|
FileScriptSource(scriptBaseDir?.resolve(sourceName) ?: File(sourceName))
|
||||||
|
|||||||
+3
-1
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.maven;
|
|||||||
|
|
||||||
import com.intellij.openapi.Disposable;
|
import com.intellij.openapi.Disposable;
|
||||||
import com.intellij.openapi.util.Disposer;
|
import com.intellij.openapi.util.Disposer;
|
||||||
|
import kotlin.script.experimental.jvm.JvmScriptingHostConfigurationKt;
|
||||||
import org.apache.maven.artifact.Artifact;
|
import org.apache.maven.artifact.Artifact;
|
||||||
import org.apache.maven.artifact.DefaultArtifact;
|
import org.apache.maven.artifact.DefaultArtifact;
|
||||||
import org.apache.maven.artifact.handler.ArtifactHandler;
|
import org.apache.maven.artifact.handler.ArtifactHandler;
|
||||||
@@ -188,7 +189,8 @@ public class ExecuteKotlinScriptMojo extends AbstractMojo {
|
|||||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, JvmProtoBufUtil.DEFAULT_MODULE_NAME);
|
configuration.put(CommonConfigurationKeys.MODULE_NAME, JvmProtoBufUtil.DEFAULT_MODULE_NAME);
|
||||||
|
|
||||||
ConfigurationKt.configureScriptDefinitions(
|
ConfigurationKt.configureScriptDefinitions(
|
||||||
scriptTemplates, configuration, this.getClass().getClassLoader(), messageCollector, new HashMap<>()
|
scriptTemplates, configuration, this.getClass().getClassLoader(), messageCollector,
|
||||||
|
JvmScriptingHostConfigurationKt.getDefaultJvmScriptingHostConfiguration()
|
||||||
);
|
);
|
||||||
|
|
||||||
KotlinCoreEnvironment environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
KotlinCoreEnvironment environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
||||||
|
|||||||
+8
-1
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.script.util.templates.StandardArgsScriptTemplateWith
|
|||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar
|
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar
|
||||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
import org.jetbrains.kotlin.utils.PathUtil.getResourcePathForClass
|
import org.jetbrains.kotlin.utils.PathUtil.getResourcePathForClass
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
@@ -44,6 +45,7 @@ import java.io.ByteArrayOutputStream
|
|||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
const val KOTLIN_JAVA_RUNTIME_JAR = "kotlin-stdlib.jar"
|
const val KOTLIN_JAVA_RUNTIME_JAR = "kotlin-stdlib.jar"
|
||||||
|
|
||||||
@@ -155,7 +157,12 @@ done
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
put(CommonConfigurationKeys.MODULE_NAME, "kotlin-script-util-test")
|
put(CommonConfigurationKeys.MODULE_NAME, "kotlin-script-util-test")
|
||||||
add(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, scriptDefinition)
|
add(
|
||||||
|
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS,
|
||||||
|
ScriptDefinition.FromLegacy(
|
||||||
|
defaultJvmScriptingHostConfiguration, scriptDefinition
|
||||||
|
)
|
||||||
|
)
|
||||||
put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
|
put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
|
||||||
|
|
||||||
add(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS, ScriptingCompilerConfigurationComponentRegistrar())
|
add(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS, ScriptingCompilerConfigurationComponentRegistrar())
|
||||||
|
|||||||
+6
-1
@@ -19,8 +19,10 @@ package org.jetbrains.kotlin.samWithReceiver
|
|||||||
import org.jetbrains.kotlin.checkers.AbstractDiagnosticsTest
|
import org.jetbrains.kotlin.checkers.AbstractDiagnosticsTest
|
||||||
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
|
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
|
||||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
import kotlin.script.extensions.SamWithReceiverAnnotations
|
import kotlin.script.extensions.SamWithReceiverAnnotations
|
||||||
import kotlin.script.templates.ScriptTemplateDefinition
|
import kotlin.script.templates.ScriptTemplateDefinition
|
||||||
|
|
||||||
@@ -31,7 +33,10 @@ abstract class AbstractSamWithReceiverScriptTest : AbstractDiagnosticsTest() {
|
|||||||
|
|
||||||
override fun createEnvironment(file: File) = super.createEnvironment(file).apply {
|
override fun createEnvironment(file: File) = super.createEnvironment(file).apply {
|
||||||
StorageComponentContainerContributor.registerExtension(project, CliSamWithReceiverComponentContributor(TEST_ANNOTATIONS))
|
StorageComponentContainerContributor.registerExtension(project, CliSamWithReceiverComponentContributor(TEST_ANNOTATIONS))
|
||||||
val def = KotlinScriptDefinitionFromAnnotatedTemplate(ScriptForSamWithReceivers::class, emptyMap())
|
val def = ScriptDefinition.FromLegacy(
|
||||||
|
defaultJvmScriptingHostConfiguration,
|
||||||
|
KotlinScriptDefinitionFromAnnotatedTemplate(ScriptForSamWithReceivers::class, emptyMap())
|
||||||
|
)
|
||||||
configuration.add(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, def)
|
configuration.add(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, def)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -65,12 +65,12 @@ class IdeSamWithReceiverComponentContributor(val project: Project) : StorageComp
|
|||||||
|
|
||||||
val moduleInfo = moduleDescriptor.getCapability(ModuleInfo.Capability)
|
val moduleInfo = moduleDescriptor.getCapability(ModuleInfo.Capability)
|
||||||
val annotations =
|
val annotations =
|
||||||
when (moduleInfo) {
|
when (moduleInfo) {
|
||||||
is ScriptModuleInfo -> moduleInfo.scriptDefinition.annotationsForSamWithReceivers
|
is ScriptModuleInfo -> moduleInfo.scriptDefinition.legacyDefinition.annotationsForSamWithReceivers
|
||||||
is ScriptDependenciesInfo.ForFile -> moduleInfo.scriptDefinition.annotationsForSamWithReceivers
|
is ScriptDependenciesInfo.ForFile -> moduleInfo.scriptDefinition.legacyDefinition.annotationsForSamWithReceivers
|
||||||
is ModuleProductionSourceInfo -> getAnnotationsForModule(moduleInfo.module)
|
is ModuleProductionSourceInfo -> getAnnotationsForModule(moduleInfo.module)
|
||||||
else -> null
|
else -> null
|
||||||
} ?: return
|
} ?: return
|
||||||
|
|
||||||
container.useInstance(SamWithReceiverResolverExtension(annotations))
|
container.useInstance(SamWithReceiverResolverExtension(annotations))
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -6,13 +6,13 @@
|
|||||||
package org.jetbrains.kotlin.scripting.configuration
|
package org.jetbrains.kotlin.scripting.configuration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.config.CompilerConfigurationKey
|
import org.jetbrains.kotlin.config.CompilerConfigurationKey
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsSource
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsSource
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
object ScriptingConfigurationKeys {
|
object ScriptingConfigurationKeys {
|
||||||
|
|
||||||
val SCRIPT_DEFINITIONS = CompilerConfigurationKey.create<List<KotlinScriptDefinition>>("script definitions")
|
val SCRIPT_DEFINITIONS = CompilerConfigurationKey.create<List<ScriptDefinition>>("script definitions")
|
||||||
|
|
||||||
val SCRIPT_DEFINITIONS_SOURCES =
|
val SCRIPT_DEFINITIONS_SOURCES =
|
||||||
CompilerConfigurationKey.create<List<ScriptDefinitionsSource>>("script definitions sources")
|
CompilerConfigurationKey.create<List<ScriptDefinitionsSource>>("script definitions sources")
|
||||||
|
|||||||
+9
-2
@@ -5,11 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.scripting.configuration
|
package org.jetbrains.kotlin.scripting.configuration
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
|
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.scripting.definitions.loadScriptTemplatesFromClasspath
|
import org.jetbrains.kotlin.scripting.definitions.loadScriptTemplatesFromClasspath
|
||||||
import org.jetbrains.kotlin.scripting.definitions.reporter
|
import org.jetbrains.kotlin.scripting.definitions.reporter
|
||||||
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
const val KOTLIN_SCRIPTING_PLUGIN_ID = "kotlin.scripting"
|
const val KOTLIN_SCRIPTING_PLUGIN_ID = "kotlin.scripting"
|
||||||
|
|
||||||
@@ -18,12 +21,16 @@ fun configureScriptDefinitions(
|
|||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
baseClassloader: ClassLoader,
|
baseClassloader: ClassLoader,
|
||||||
messageCollector: MessageCollector,
|
messageCollector: MessageCollector,
|
||||||
scriptResolverEnv: Map<String, Any?>
|
hostConfiguration: ScriptingHostConfiguration
|
||||||
) {
|
) {
|
||||||
// TODO: consider using escaping to allow kotlin escaped names in class names
|
// TODO: consider using escaping to allow kotlin escaped names in class names
|
||||||
val templatesFromClasspath = loadScriptTemplatesFromClasspath(
|
val templatesFromClasspath = loadScriptTemplatesFromClasspath(
|
||||||
scriptTemplates, configuration.jvmClasspathRoots, emptyList(), baseClassloader, scriptResolverEnv, messageCollector.reporter
|
scriptTemplates, configuration.jvmClasspathRoots, emptyList(), baseClassloader, hostConfiguration, messageCollector.reporter
|
||||||
)
|
)
|
||||||
configuration.addAll(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, templatesFromClasspath.toList())
|
configuration.addAll(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, templatesFromClasspath.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun makeHostConfiguration(project: Project, configuration: CompilerConfiguration): ScriptingHostConfiguration =
|
||||||
|
ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration) {
|
||||||
|
// TODO: add jdk path and other params if needed
|
||||||
|
}
|
||||||
+2
@@ -17,6 +17,8 @@ import kotlin.reflect.KType
|
|||||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||||
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
||||||
|
|
||||||
|
// Legacy definition, will be obsolete soon
|
||||||
|
// TODO: make deprecated and drop usages where possible
|
||||||
open class KotlinScriptDefinition(open val template: KClass<out Any>) : UserDataHolderBase() {
|
open class KotlinScriptDefinition(open val template: KClass<out Any>) : UserDataHolderBase() {
|
||||||
|
|
||||||
open val name: String = "Kotlin Script"
|
open val name: String = "Kotlin Script"
|
||||||
|
|||||||
+3
-9
@@ -17,6 +17,7 @@ import kotlin.script.experimental.api.*
|
|||||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
import kotlin.script.experimental.host.getScriptingClass
|
import kotlin.script.experimental.host.getScriptingClass
|
||||||
|
import kotlin.script.experimental.jvm.compat.mapToLegacyExpectedLocations
|
||||||
import kotlin.script.experimental.jvm.impl.BridgeDependenciesResolver
|
import kotlin.script.experimental.jvm.impl.BridgeDependenciesResolver
|
||||||
import kotlin.script.experimental.location.ScriptExpectedLocation
|
import kotlin.script.experimental.location.ScriptExpectedLocation
|
||||||
import kotlin.script.experimental.util.getOrError
|
import kotlin.script.experimental.util.getOrError
|
||||||
@@ -80,15 +81,8 @@ abstract class KotlinScriptDefinitionAdapterFromNewAPIBase : KotlinScriptDefinit
|
|||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
override val scriptExpectedLocations: List<ScriptExpectedLocation>
|
override val scriptExpectedLocations: List<ScriptExpectedLocation>
|
||||||
get() = scriptCompilationConfiguration[ScriptCompilationConfiguration.ide.acceptedLocations]?.map {
|
get() = scriptCompilationConfiguration[ScriptCompilationConfiguration.ide.acceptedLocations]?.mapToLegacyExpectedLocations()
|
||||||
when (it) {
|
?: listOf(ScriptExpectedLocation.SourcesOnly, ScriptExpectedLocation.TestsOnly)
|
||||||
ScriptAcceptedLocation.Sources -> ScriptExpectedLocation.SourcesOnly
|
|
||||||
ScriptAcceptedLocation.Tests -> ScriptExpectedLocation.TestsOnly
|
|
||||||
ScriptAcceptedLocation.Libraries -> ScriptExpectedLocation.Libraries
|
|
||||||
ScriptAcceptedLocation.Project -> ScriptExpectedLocation.Project
|
|
||||||
ScriptAcceptedLocation.Everywhere -> ScriptExpectedLocation.Everywhere
|
|
||||||
}
|
|
||||||
} ?: listOf(ScriptExpectedLocation.SourcesOnly, ScriptExpectedLocation.TestsOnly)
|
|
||||||
|
|
||||||
private val scriptingClassGetter by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
private val scriptingClassGetter by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||||
hostConfiguration[ScriptingHostConfiguration.getScriptingClass]
|
hostConfiguration[ScriptingHostConfiguration.getScriptingClass]
|
||||||
|
|||||||
+8
-2
@@ -9,10 +9,17 @@ import com.intellij.openapi.components.ServiceManager
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
|
||||||
interface ScriptDefinitionProvider {
|
interface ScriptDefinitionProvider {
|
||||||
|
@Deprecated("Migrating to configuration refinement", level = DeprecationLevel.ERROR)
|
||||||
fun findScriptDefinition(fileName: String): KotlinScriptDefinition?
|
fun findScriptDefinition(fileName: String): KotlinScriptDefinition?
|
||||||
fun isScript(fileName: String): Boolean
|
|
||||||
|
@Deprecated("Migrating to configuration refinement", level = DeprecationLevel.ERROR)
|
||||||
fun getDefaultScriptDefinition(): KotlinScriptDefinition
|
fun getDefaultScriptDefinition(): KotlinScriptDefinition
|
||||||
|
|
||||||
|
fun isScript(fileName: String): Boolean
|
||||||
|
|
||||||
|
fun findDefinition(fileName: String): ScriptDefinition?
|
||||||
|
fun getDefaultDefinition(): ScriptDefinition
|
||||||
|
|
||||||
fun getKnownFilenameExtensions(): Sequence<String>
|
fun getKnownFilenameExtensions(): Sequence<String>
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -21,4 +28,3 @@ interface ScriptDefinitionProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+26
-11
@@ -10,44 +10,56 @@ import java.io.File
|
|||||||
import kotlin.script.experimental.annotations.KotlinScript
|
import kotlin.script.experimental.annotations.KotlinScript
|
||||||
import kotlin.script.experimental.api.KotlinType
|
import kotlin.script.experimental.api.KotlinType
|
||||||
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
||||||
|
import kotlin.script.experimental.api.ScriptEvaluationConfiguration
|
||||||
import kotlin.script.experimental.api.fileExtension
|
import kotlin.script.experimental.api.fileExtension
|
||||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
import kotlin.script.experimental.host.configurationDependencies
|
import kotlin.script.experimental.host.configurationDependencies
|
||||||
import kotlin.script.experimental.host.createCompilationConfigurationFromTemplate
|
import kotlin.script.experimental.host.createCompilationConfigurationFromTemplate
|
||||||
|
import kotlin.script.experimental.host.createEvaluationConfigurationFromTemplate
|
||||||
import kotlin.script.experimental.jvm.JvmDependency
|
import kotlin.script.experimental.jvm.JvmDependency
|
||||||
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
class LazyScriptDefinitionFromDiscoveredClass internal constructor(
|
class LazyScriptDefinitionFromDiscoveredClass internal constructor(
|
||||||
|
baseHostConfiguration: ScriptingHostConfiguration,
|
||||||
private val annotationsFromAsm: ArrayList<BinAnnData>,
|
private val annotationsFromAsm: ArrayList<BinAnnData>,
|
||||||
private val className: String,
|
private val className: String,
|
||||||
private val classpath: List<File>,
|
private val classpath: List<File>,
|
||||||
private val messageReporter: MessageReporter
|
private val messageReporter: MessageReporter
|
||||||
) : KotlinScriptDefinitionAdapterFromNewAPIBase() {
|
) : ScriptDefinition.FromConfigurationsBase() {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
baseHostConfiguration: ScriptingHostConfiguration,
|
||||||
classBytes: ByteArray,
|
classBytes: ByteArray,
|
||||||
className: String,
|
className: String,
|
||||||
classpath: List<File>,
|
classpath: List<File>,
|
||||||
messageReporter: MessageReporter
|
messageReporter: MessageReporter
|
||||||
) : this(loadAnnotationsFromClass(classBytes), className, classpath, messageReporter)
|
) : this(baseHostConfiguration, loadAnnotationsFromClass(classBytes), className, classpath, messageReporter)
|
||||||
|
|
||||||
override val hostConfiguration: ScriptingHostConfiguration by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
override val hostConfiguration: ScriptingHostConfiguration by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||||
ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration) {
|
ScriptingHostConfiguration(baseHostConfiguration) {
|
||||||
configurationDependencies.append(JvmDependency(classpath))
|
configurationDependencies.append(JvmDependency(classpath))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val scriptCompilationConfiguration: ScriptCompilationConfiguration by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
private val configurations by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||||
messageReporter(
|
messageReporter(
|
||||||
CompilerMessageSeverity.LOGGING,
|
CompilerMessageSeverity.LOGGING,
|
||||||
"Configure scripting: loading script definition class $className using classpath $classpath\n. ${Thread.currentThread().stackTrace}"
|
"Configure scripting: loading script definition class $className using classpath $classpath\n. ${Thread.currentThread().stackTrace}"
|
||||||
)
|
)
|
||||||
try {
|
try {
|
||||||
createCompilationConfigurationFromTemplate(
|
val compileCfg =
|
||||||
KotlinType(className),
|
createCompilationConfigurationFromTemplate(
|
||||||
hostConfiguration,
|
KotlinType(className),
|
||||||
LazyScriptDefinitionFromDiscoveredClass::class
|
hostConfiguration,
|
||||||
)
|
LazyScriptDefinitionFromDiscoveredClass::class
|
||||||
|
)
|
||||||
|
val evalCfg =
|
||||||
|
createEvaluationConfigurationFromTemplate(
|
||||||
|
KotlinType(className),
|
||||||
|
hostConfiguration,
|
||||||
|
LazyScriptDefinitionFromDiscoveredClass::class
|
||||||
|
)
|
||||||
|
compileCfg to evalCfg
|
||||||
} catch (ex: ClassNotFoundException) {
|
} catch (ex: ClassNotFoundException) {
|
||||||
messageReporter(CompilerMessageSeverity.ERROR, "Cannot find script definition class $className")
|
messageReporter(CompilerMessageSeverity.ERROR, "Cannot find script definition class $className")
|
||||||
InvalidScriptDefinition
|
InvalidScriptDefinition
|
||||||
@@ -60,10 +72,13 @@ class LazyScriptDefinitionFromDiscoveredClass internal constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val compilationConfiguration: ScriptCompilationConfiguration get() = configurations.first
|
||||||
|
override val evaluationConfiguration: ScriptEvaluationConfiguration get() = configurations.second
|
||||||
|
|
||||||
override val fileExtension: String by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
override val fileExtension: String by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||||
annotationsFromAsm.find { it.name == KotlinScript::class.simpleName }?.args
|
annotationsFromAsm.find { it.name == KotlinScript::class.simpleName }?.args
|
||||||
?.find { it.name == "fileExtension" }?.value
|
?.find { it.name == "fileExtension" }?.value
|
||||||
?: scriptCompilationConfiguration.let {
|
?: compilationConfiguration.let {
|
||||||
it[ScriptCompilationConfiguration.fileExtension] ?: super.fileExtension
|
it[ScriptCompilationConfiguration.fileExtension] ?: super.fileExtension
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,4 +89,4 @@ class LazyScriptDefinitionFromDiscoveredClass internal constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val InvalidScriptDefinition = ScriptCompilationConfiguration()
|
val InvalidScriptDefinition = ScriptCompilationConfiguration() to ScriptEvaluationConfiguration()
|
||||||
|
|||||||
+16
-5
@@ -10,15 +10,22 @@ import org.jetbrains.kotlin.idea.KotlinFileType
|
|||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
import kotlin.concurrent.read
|
import kotlin.concurrent.read
|
||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
abstract class LazyScriptDefinitionProvider : ScriptDefinitionProvider {
|
abstract class LazyScriptDefinitionProvider : ScriptDefinitionProvider {
|
||||||
|
|
||||||
protected val lock = ReentrantReadWriteLock()
|
protected val lock = ReentrantReadWriteLock()
|
||||||
|
|
||||||
protected abstract val currentDefinitions: Sequence<KotlinScriptDefinition>
|
protected abstract val currentDefinitions: Sequence<ScriptDefinition>
|
||||||
|
|
||||||
private var _cachedDefinitions: Sequence<KotlinScriptDefinition>? = null
|
protected open fun getScriptingHostConfiguration(): ScriptingHostConfiguration = defaultJvmScriptingHostConfiguration
|
||||||
private val cachedDefinitions: Sequence<KotlinScriptDefinition>
|
|
||||||
|
override fun getDefaultDefinition(): ScriptDefinition =
|
||||||
|
ScriptDefinition.FromLegacy(getScriptingHostConfiguration(), StandardScriptDefinition)
|
||||||
|
|
||||||
|
private var _cachedDefinitions: Sequence<ScriptDefinition>? = null
|
||||||
|
private val cachedDefinitions: Sequence<ScriptDefinition>
|
||||||
get() {
|
get() {
|
||||||
assert(lock.readLockCount > 0) { "cachedDefinitions should only be used under the read lock" }
|
assert(lock.readLockCount > 0) { "cachedDefinitions should only be used under the read lock" }
|
||||||
if (_cachedDefinitions == null) lock.write {
|
if (_cachedDefinitions == null) lock.write {
|
||||||
@@ -37,18 +44,22 @@ abstract class LazyScriptDefinitionProvider : ScriptDefinitionProvider {
|
|||||||
fileName.endsWith(it, ignoreCase = true)
|
fileName.endsWith(it, ignoreCase = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findScriptDefinition(fileName: String): KotlinScriptDefinition? =
|
override fun findDefinition(fileName: String): ScriptDefinition? =
|
||||||
if (nonScriptFileName(fileName)) null
|
if (nonScriptFileName(fileName)) null
|
||||||
else lock.read {
|
else lock.read {
|
||||||
cachedDefinitions.firstOrNull { it.isScript(fileName) }
|
cachedDefinitions.firstOrNull { it.isScript(fileName) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isScript(fileName: String) = findScriptDefinition(fileName) != null
|
override fun findScriptDefinition(fileName: String): KotlinScriptDefinition? = findDefinition(fileName)?.legacyDefinition
|
||||||
|
|
||||||
|
override fun isScript(fileName: String) = findDefinition(fileName) != null
|
||||||
|
|
||||||
override fun getKnownFilenameExtensions(): Sequence<String> = lock.read {
|
override fun getKnownFilenameExtensions(): Sequence<String> = lock.read {
|
||||||
cachedDefinitions.map { it.fileExtension }
|
cachedDefinitions.map { it.fileExtension }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getDefaultScriptDefinition(): KotlinScriptDefinition = getDefaultDefinition().legacyDefinition
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// TODO: find a common place for storing kotlin-related extensions and reuse values from it everywhere
|
// TODO: find a common place for storing kotlin-related extensions and reuse values from it everywhere
|
||||||
protected val nonScriptFilenameSuffixes = arrayOf(".${KotlinFileType.EXTENSION}", ".${JavaFileType.DEFAULT_EXTENSION}")
|
protected val nonScriptFilenameSuffixes = arrayOf(".${KotlinFileType.EXTENSION}", ".${JavaFileType.DEFAULT_EXTENSION}")
|
||||||
|
|||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.scripting.definitions
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.script.dependencies.Environment
|
||||||
|
import kotlin.script.dependencies.ScriptContents
|
||||||
|
import kotlin.script.experimental.api.*
|
||||||
|
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||||
|
import kotlin.script.experimental.host.FileBasedScriptSource
|
||||||
|
import kotlin.script.experimental.host.FileScriptSource
|
||||||
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.host.ScriptingHostConfigurationKeys
|
||||||
|
import kotlin.script.experimental.jvm.JvmDependency
|
||||||
|
import kotlin.script.experimental.jvm.compat.mapLegacyDiagnosticSeverity
|
||||||
|
import kotlin.script.experimental.jvm.compat.mapLegacyExpectedLocations
|
||||||
|
import kotlin.script.experimental.jvm.jdkHome
|
||||||
|
import kotlin.script.experimental.jvm.jvm
|
||||||
|
import kotlin.script.experimental.util.PropertiesCollection
|
||||||
|
|
||||||
|
class ScriptCompilationConfigurationFromDefinition(
|
||||||
|
val hostConfiguration: ScriptingHostConfiguration,
|
||||||
|
val scriptDefinition: KotlinScriptDefinition
|
||||||
|
) : ScriptCompilationConfiguration(
|
||||||
|
{
|
||||||
|
hostConfiguration(hostConfiguration)
|
||||||
|
displayName(scriptDefinition.name)
|
||||||
|
fileExtension(scriptDefinition.fileExtension)
|
||||||
|
baseClass(KotlinType(scriptDefinition.template))
|
||||||
|
implicitReceivers.putIfAny(scriptDefinition.implicitReceivers.map(::KotlinType))
|
||||||
|
providedProperties.putIfAny(scriptDefinition.providedProperties.map { it.first to KotlinType(it.second) })
|
||||||
|
annotationsForSamWithReceivers.put(scriptDefinition.annotationsForSamWithReceivers.map(::KotlinType))
|
||||||
|
platform(scriptDefinition.platform)
|
||||||
|
compilerOptions.putIfAny(scriptDefinition.additionalCompilerArguments)
|
||||||
|
ide {
|
||||||
|
acceptedLocations.put(scriptDefinition.scriptExpectedLocations.mapLegacyExpectedLocations())
|
||||||
|
}
|
||||||
|
if (scriptDefinition.dependencyResolver != DependenciesResolver.NoDependencies) {
|
||||||
|
refineConfiguration {
|
||||||
|
onAnnotations(scriptDefinition.acceptedAnnotations.map(::KotlinType)) { context ->
|
||||||
|
|
||||||
|
val resolveResult: DependenciesResolver.ResolveResult = scriptDefinition.dependencyResolver.resolve(
|
||||||
|
ScriptContentsFromRefinementContext(context),
|
||||||
|
context.compilationConfiguration[ScriptCompilationConfiguration.hostConfiguration]?.let {
|
||||||
|
it[ScriptingHostConfiguration.getEnvironment]?.invoke()
|
||||||
|
}.orEmpty()
|
||||||
|
)
|
||||||
|
|
||||||
|
val reports = resolveResult.reports.map { ScriptDiagnostic(it.message, mapLegacyDiagnosticSeverity(it.severity)) }
|
||||||
|
val resolvedDeps = (resolveResult as? DependenciesResolver.ResolveResult.Success)?.dependencies
|
||||||
|
|
||||||
|
if (resolvedDeps == null) ResultWithDiagnostics.Failure(reports)
|
||||||
|
else ScriptCompilationConfiguration(context.compilationConfiguration) {
|
||||||
|
if (resolvedDeps.classpath.isNotEmpty()) {
|
||||||
|
dependencies.append(JvmDependency(resolvedDeps.classpath))
|
||||||
|
}
|
||||||
|
defaultImports.append(resolvedDeps.imports)
|
||||||
|
importScripts.append(resolvedDeps.scripts.map { FileScriptSource(it) })
|
||||||
|
jvm {
|
||||||
|
jdkHome.putIfNotNull(resolvedDeps.javaHome) // TODO: check if it is correct to supply javaHome as jdkHome
|
||||||
|
}
|
||||||
|
if (resolvedDeps.sources.isNotEmpty()) {
|
||||||
|
ide {
|
||||||
|
dependenciesSources.append(JvmDependency(resolvedDeps.sources))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.asSuccess(reports)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
private class ScriptContentsFromRefinementContext(val context: ScriptConfigurationRefinementContext) : ScriptContents {
|
||||||
|
override val file: File?
|
||||||
|
get() = (context.script as? FileBasedScriptSource)?.file
|
||||||
|
override val annotations: Iterable<Annotation>
|
||||||
|
get() = context.collectedData?.get(ScriptCollectedData.foundAnnotations) ?: emptyList()
|
||||||
|
override val text: CharSequence?
|
||||||
|
get() = context.script.text
|
||||||
|
}
|
||||||
|
|
||||||
|
val ScriptCompilationConfigurationKeys.annotationsForSamWithReceivers by PropertiesCollection.key<List<KotlinType>>()
|
||||||
|
|
||||||
|
val ScriptCompilationConfigurationKeys.platform by PropertiesCollection.key<String>()
|
||||||
|
|
||||||
|
val ScriptingHostConfigurationKeys.getEnvironment by PropertiesCollection.key<() -> Environment?>()
|
||||||
+164
@@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.scripting.definitions
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.UserDataHolderBase
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.script.experimental.api.*
|
||||||
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.host.createCompilationConfigurationFromTemplate
|
||||||
|
import kotlin.script.experimental.host.createEvaluationConfigurationFromTemplate
|
||||||
|
import kotlin.script.experimental.jvm.baseClassLoader
|
||||||
|
import kotlin.script.experimental.jvm.jvm
|
||||||
|
|
||||||
|
// Transitional class/implementation - migrating to the new API
|
||||||
|
// TODO: deprecate KotlinScriptDefinition
|
||||||
|
// TODO: name could be confused with KotlinScriptDefinition, discuss naming
|
||||||
|
abstract class ScriptDefinition : UserDataHolderBase() {
|
||||||
|
|
||||||
|
abstract val legacyDefinition: KotlinScriptDefinition
|
||||||
|
abstract val hostConfiguration: ScriptingHostConfiguration
|
||||||
|
abstract val compilationConfiguration: ScriptCompilationConfiguration
|
||||||
|
abstract val evaluationConfiguration: ScriptEvaluationConfiguration
|
||||||
|
|
||||||
|
abstract fun isScript(fileName: String): Boolean
|
||||||
|
abstract val fileExtension: String
|
||||||
|
abstract val name: String
|
||||||
|
// TODO: used in settings, find out the reason and refactor accordingly
|
||||||
|
abstract val definitionId: String
|
||||||
|
|
||||||
|
abstract val contextClassLoader: ClassLoader?
|
||||||
|
|
||||||
|
// Target platform for script, ex. "JVM", "JS", "NATIVE"
|
||||||
|
open val platform: String
|
||||||
|
get() = "JVM"
|
||||||
|
|
||||||
|
open val isDefault = false
|
||||||
|
|
||||||
|
abstract val baseClassType: KotlinType
|
||||||
|
abstract val compilerOptions: Iterable<String>
|
||||||
|
|
||||||
|
inline fun <reified T : KotlinScriptDefinition> asLegacyOrNull(): T? =
|
||||||
|
if (this is FromLegacy) legacyDefinition as? T else null
|
||||||
|
|
||||||
|
open class FromLegacy(
|
||||||
|
override val hostConfiguration: ScriptingHostConfiguration,
|
||||||
|
override val legacyDefinition: KotlinScriptDefinition
|
||||||
|
) : ScriptDefinition() {
|
||||||
|
|
||||||
|
override val compilationConfiguration by lazy {
|
||||||
|
ScriptCompilationConfigurationFromDefinition(
|
||||||
|
hostConfiguration,
|
||||||
|
legacyDefinition
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val evaluationConfiguration by lazy {
|
||||||
|
ScriptEvaluationConfigurationFromDefinition(
|
||||||
|
hostConfiguration,
|
||||||
|
legacyDefinition
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isScript(fileName: String): Boolean = legacyDefinition.isScript(fileName)
|
||||||
|
|
||||||
|
override val fileExtension: String get() = legacyDefinition.fileExtension
|
||||||
|
|
||||||
|
override val name: String get() = legacyDefinition.name
|
||||||
|
|
||||||
|
override val definitionId: String get() = legacyDefinition::class.qualifiedName ?: "unknown"
|
||||||
|
|
||||||
|
override val platform: String
|
||||||
|
get() = legacyDefinition.platform
|
||||||
|
|
||||||
|
override val contextClassLoader: ClassLoader?
|
||||||
|
get() = legacyDefinition.template.java.classLoader
|
||||||
|
|
||||||
|
override val baseClassType: KotlinType
|
||||||
|
get() = KotlinType(legacyDefinition.template)
|
||||||
|
|
||||||
|
override val compilerOptions: Iterable<String>
|
||||||
|
get() = legacyDefinition.additionalCompilerArguments ?: emptyList()
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean = this === other || legacyDefinition == (other as? FromLegacy)?.legacyDefinition
|
||||||
|
|
||||||
|
override fun hashCode(): Int = legacyDefinition.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
open class FromLegacyTemplate(
|
||||||
|
hostConfiguration: ScriptingHostConfiguration,
|
||||||
|
template: KClass<*>,
|
||||||
|
templateClasspath: List<File> = emptyList()
|
||||||
|
) : FromLegacy(
|
||||||
|
hostConfiguration,
|
||||||
|
KotlinScriptDefinitionFromAnnotatedTemplate(
|
||||||
|
template,
|
||||||
|
hostConfiguration[ScriptingHostConfiguration.getEnvironment]?.invoke(),
|
||||||
|
templateClasspath
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
abstract class FromConfigurationsBase : ScriptDefinition() {
|
||||||
|
|
||||||
|
override val legacyDefinition by lazy {
|
||||||
|
KotlinScriptDefinitionAdapterFromNewAPI(
|
||||||
|
compilationConfiguration,
|
||||||
|
hostConfiguration
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isScript(fileName: String): Boolean = fileName.endsWith(".$fileExtension")
|
||||||
|
|
||||||
|
override val fileExtension: String get() = compilationConfiguration[ScriptCompilationConfiguration.fileExtension]!!
|
||||||
|
|
||||||
|
override val name: String get() = compilationConfiguration[ScriptCompilationConfiguration.displayName]!!
|
||||||
|
|
||||||
|
override val definitionId: String get() = compilationConfiguration[ScriptCompilationConfiguration.baseClass]!!.typeName
|
||||||
|
|
||||||
|
override val contextClassLoader: ClassLoader? by lazy {
|
||||||
|
compilationConfiguration[ScriptCompilationConfiguration.baseClass]?.fromClass?.java?.classLoader
|
||||||
|
?: hostConfiguration[ScriptingHostConfiguration.jvm.baseClassLoader]
|
||||||
|
}
|
||||||
|
|
||||||
|
override val baseClassType: KotlinType
|
||||||
|
get() = compilationConfiguration[ScriptCompilationConfiguration.baseClass]!!
|
||||||
|
|
||||||
|
override val compilerOptions: Iterable<String>
|
||||||
|
get() = compilationConfiguration[ScriptCompilationConfiguration.compilerOptions].orEmpty()
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean = this === other ||
|
||||||
|
(other as? FromConfigurations)?.let {
|
||||||
|
compilationConfiguration == it.compilationConfiguration && evaluationConfiguration == it.evaluationConfiguration
|
||||||
|
} == true
|
||||||
|
|
||||||
|
override fun hashCode(): Int = compilationConfiguration.hashCode() + 37 * evaluationConfiguration.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
open class FromConfigurations(
|
||||||
|
override val hostConfiguration: ScriptingHostConfiguration,
|
||||||
|
override val compilationConfiguration: ScriptCompilationConfiguration,
|
||||||
|
override val evaluationConfiguration: ScriptEvaluationConfiguration
|
||||||
|
) : FromConfigurationsBase()
|
||||||
|
|
||||||
|
open class FromTemplate(
|
||||||
|
hostConfiguration: ScriptingHostConfiguration,
|
||||||
|
template: KClass<*>,
|
||||||
|
contextClass: KClass<*> = ScriptCompilationConfiguration::class
|
||||||
|
) : FromConfigurations(
|
||||||
|
hostConfiguration,
|
||||||
|
createCompilationConfigurationFromTemplate(KotlinType(template), hostConfiguration, contextClass),
|
||||||
|
createEvaluationConfigurationFromTemplate(KotlinType(template), hostConfiguration, contextClass)
|
||||||
|
)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getDefault(hostConfiguration: ScriptingHostConfiguration) =
|
||||||
|
object : FromLegacy(hostConfiguration, StandardScriptDefinition) {
|
||||||
|
override val isDefault = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -7,5 +7,5 @@ package org.jetbrains.kotlin.scripting.definitions
|
|||||||
|
|
||||||
interface ScriptDefinitionsSource {
|
interface ScriptDefinitionsSource {
|
||||||
|
|
||||||
val definitions: Sequence<KotlinScriptDefinition>
|
val definitions: Sequence<ScriptDefinition>
|
||||||
}
|
}
|
||||||
+15
-2
@@ -9,11 +9,24 @@ import com.intellij.openapi.components.ServiceManager
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||||
|
import kotlin.script.experimental.api.valueOrNull
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||||
|
|
||||||
interface ScriptDependenciesProvider {
|
interface ScriptDependenciesProvider {
|
||||||
fun getScriptDependencies(file: VirtualFile): ScriptDependencies?
|
|
||||||
fun getScriptDependencies(file: PsiFile) = getScriptDependencies(file.virtualFile ?: file.originalFile.virtualFile)
|
@Deprecated("Migrating to configuration refinement", level = DeprecationLevel.ERROR)
|
||||||
|
fun getScriptDependencies(file: VirtualFile): ScriptDependencies? =
|
||||||
|
getScriptConfigurationResult(file)?.valueOrNull()?.legacyDependencies
|
||||||
|
|
||||||
|
@Deprecated("Migrating to configuration refinement", level = DeprecationLevel.ERROR)
|
||||||
|
fun getScriptDependencies(file: PsiFile): ScriptDependencies? =
|
||||||
|
getScriptConfigurationResult(file.virtualFile ?: file.originalFile.virtualFile)?.valueOrNull()?.legacyDependencies
|
||||||
|
|
||||||
|
fun getScriptConfigurationResult(file: VirtualFile): ScriptCompilationConfigurationResult? = null
|
||||||
|
|
||||||
|
fun getScriptConfigurationResult(file: PsiFile): ScriptCompilationConfigurationResult? =
|
||||||
|
getScriptConfigurationResult(file.virtualFile ?: file.originalFile.virtualFile)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getInstance(project: Project): ScriptDependenciesProvider? =
|
fun getInstance(project: Project): ScriptDependenciesProvider? =
|
||||||
|
|||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.scripting.definitions
|
||||||
|
|
||||||
|
import kotlin.script.experimental.api.ScriptEvaluationConfiguration
|
||||||
|
import kotlin.script.experimental.api.hostConfiguration
|
||||||
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
|
||||||
|
class ScriptEvaluationConfigurationFromDefinition(
|
||||||
|
val hostConfiguration: ScriptingHostConfiguration,
|
||||||
|
val scriptDefinition: KotlinScriptDefinition
|
||||||
|
) : ScriptEvaluationConfiguration(
|
||||||
|
{
|
||||||
|
hostConfiguration(hostConfiguration)
|
||||||
|
}
|
||||||
|
)
|
||||||
+46
-47
@@ -11,13 +11,13 @@ import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotate
|
|||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.lang.IllegalArgumentException
|
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.util.jar.JarFile
|
import java.util.jar.JarFile
|
||||||
import kotlin.script.experimental.annotations.KotlinScript
|
import kotlin.script.experimental.annotations.KotlinScript
|
||||||
import kotlin.script.experimental.api.KotlinType
|
import kotlin.script.experimental.api.KotlinType
|
||||||
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
import kotlin.script.experimental.host.createCompilationConfigurationFromTemplate
|
import kotlin.script.experimental.host.createCompilationConfigurationFromTemplate
|
||||||
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
import kotlin.script.experimental.host.createEvaluationConfigurationFromTemplate
|
||||||
import kotlin.script.templates.ScriptTemplateDefinition
|
import kotlin.script.templates.ScriptTemplateDefinition
|
||||||
|
|
||||||
const val SCRIPT_DEFINITION_MARKERS_PATH = "META-INF/kotlin/script/templates/"
|
const val SCRIPT_DEFINITION_MARKERS_PATH = "META-INF/kotlin/script/templates/"
|
||||||
@@ -32,15 +32,15 @@ val MessageCollector.reporter: MessageReporter
|
|||||||
|
|
||||||
class ScriptDefinitionsFromClasspathDiscoverySource(
|
class ScriptDefinitionsFromClasspathDiscoverySource(
|
||||||
private val classpath: List<File>,
|
private val classpath: List<File>,
|
||||||
private val scriptResolverEnv: Map<String, Any?>,
|
private val hostConfiguration: ScriptingHostConfiguration,
|
||||||
private val messageReporter: MessageReporter
|
private val messageReporter: MessageReporter
|
||||||
) : ScriptDefinitionsSource {
|
) : ScriptDefinitionsSource {
|
||||||
|
|
||||||
override val definitions: Sequence<KotlinScriptDefinition> = run {
|
override val definitions: Sequence<ScriptDefinition> = run {
|
||||||
discoverScriptTemplatesInClasspath(
|
discoverScriptTemplatesInClasspath(
|
||||||
classpath,
|
classpath,
|
||||||
this::class.java.classLoader,
|
this::class.java.classLoader,
|
||||||
scriptResolverEnv,
|
hostConfiguration,
|
||||||
messageReporter
|
messageReporter
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -50,9 +50,9 @@ private const val MANIFEST_RESOURCE_NAME = "/META-INF/MANIFEST.MF"
|
|||||||
|
|
||||||
fun discoverScriptTemplatesInClassLoader(
|
fun discoverScriptTemplatesInClassLoader(
|
||||||
classLoader: ClassLoader,
|
classLoader: ClassLoader,
|
||||||
scriptResolverEnv: Map<String, Any?>,
|
hostConfiguration: ScriptingHostConfiguration,
|
||||||
messageReporter: MessageReporter
|
messageReporter: MessageReporter
|
||||||
): Sequence<KotlinScriptDefinition> {
|
): Sequence<ScriptDefinition> {
|
||||||
val classpath = classLoader.getResources(MANIFEST_RESOURCE_NAME).asSequence().mapNotNull {
|
val classpath = classLoader.getResources(MANIFEST_RESOURCE_NAME).asSequence().mapNotNull {
|
||||||
try {
|
try {
|
||||||
File(it.toURI()).takeIf(File::exists)
|
File(it.toURI()).takeIf(File::exists)
|
||||||
@@ -61,26 +61,26 @@ fun discoverScriptTemplatesInClassLoader(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val classpathWithLoader = SimpleClasspathWithClassLoader(classpath.toList(), classLoader)
|
val classpathWithLoader = SimpleClasspathWithClassLoader(classpath.toList(), classLoader)
|
||||||
return scriptTemplatesDiscoverySequence(classpathWithLoader, scriptResolverEnv, messageReporter)
|
return scriptTemplatesDiscoverySequence(classpathWithLoader, hostConfiguration, messageReporter)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun discoverScriptTemplatesInClasspath(
|
fun discoverScriptTemplatesInClasspath(
|
||||||
classpath: List<File>,
|
classpath: List<File>,
|
||||||
baseClassLoader: ClassLoader?,
|
baseClassLoader: ClassLoader?,
|
||||||
scriptResolverEnv: Map<String, Any?>,
|
hostConfiguration: ScriptingHostConfiguration,
|
||||||
messageReporter: MessageReporter
|
messageReporter: MessageReporter
|
||||||
): Sequence<KotlinScriptDefinition> {
|
): Sequence<ScriptDefinition> {
|
||||||
// TODO: try to find a way to reduce classpath (and classloader) to minimal one needed to load script definition and its dependencies
|
// TODO: try to find a way to reduce classpath (and classloader) to minimal one needed to load script definition and its dependencies
|
||||||
val classpathWithLoader = LazyClasspathWithClassLoader(baseClassLoader) { classpath }
|
val classpathWithLoader = LazyClasspathWithClassLoader(baseClassLoader) { classpath }
|
||||||
|
|
||||||
return scriptTemplatesDiscoverySequence(classpathWithLoader, scriptResolverEnv, messageReporter)
|
return scriptTemplatesDiscoverySequence(classpathWithLoader, hostConfiguration, messageReporter)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun scriptTemplatesDiscoverySequence(
|
private fun scriptTemplatesDiscoverySequence(
|
||||||
classpathWithLoader: ClasspathWithClassLoader,
|
classpathWithLoader: ClasspathWithClassLoader,
|
||||||
scriptResolverEnv: Map<String, Any?>,
|
hostConfiguration: ScriptingHostConfiguration,
|
||||||
messageReporter: MessageReporter
|
messageReporter: MessageReporter
|
||||||
): Sequence<KotlinScriptDefinition> {
|
): Sequence<ScriptDefinition> {
|
||||||
return sequence {
|
return sequence {
|
||||||
// for jar files the definition class is expected in the same jar as the discovery file
|
// for jar files the definition class is expected in the same jar as the discovery file
|
||||||
// in case of directories, the class output may come separate from the resources, so some candidates should be deffered and processed later
|
// in case of directories, the class output may come separate from the resources, so some candidates should be deffered and processed later
|
||||||
@@ -102,7 +102,7 @@ private fun scriptTemplatesDiscoverySequence(
|
|||||||
definitionNames.partitionLoadJarDefinitions(
|
definitionNames.partitionLoadJarDefinitions(
|
||||||
jar,
|
jar,
|
||||||
classpathWithLoader,
|
classpathWithLoader,
|
||||||
scriptResolverEnv,
|
hostConfiguration,
|
||||||
messageReporter
|
messageReporter
|
||||||
)
|
)
|
||||||
if (notFoundClasses.isNotEmpty()) {
|
if (notFoundClasses.isNotEmpty()) {
|
||||||
@@ -122,7 +122,7 @@ private fun scriptTemplatesDiscoverySequence(
|
|||||||
val discoveryMarkers = File(dep, SCRIPT_DEFINITION_MARKERS_PATH).listFiles()
|
val discoveryMarkers = File(dep, SCRIPT_DEFINITION_MARKERS_PATH).listFiles()
|
||||||
if (discoveryMarkers?.isEmpty() == false) {
|
if (discoveryMarkers?.isEmpty() == false) {
|
||||||
val (foundDefinitionClasses, notFoundDefinitions) = discoveryMarkers.map { it.name }
|
val (foundDefinitionClasses, notFoundDefinitions) = discoveryMarkers.map { it.name }
|
||||||
.partitionLoadDirDefinitions(dep, classpathWithLoader, scriptResolverEnv, messageReporter)
|
.partitionLoadDirDefinitions(dep, classpathWithLoader, hostConfiguration, messageReporter)
|
||||||
foundDefinitionClasses.forEach {
|
foundDefinitionClasses.forEach {
|
||||||
yield(it)
|
yield(it)
|
||||||
}
|
}
|
||||||
@@ -145,7 +145,7 @@ private fun scriptTemplatesDiscoverySequence(
|
|||||||
if (remainingDefinitionCandidates.isEmpty()) break
|
if (remainingDefinitionCandidates.isEmpty()) break
|
||||||
try {
|
try {
|
||||||
val (foundDefinitionClasses, notFoundDefinitions) =
|
val (foundDefinitionClasses, notFoundDefinitions) =
|
||||||
remainingDefinitionCandidates.partitionLoadDirDefinitions(dep, classpathWithLoader, scriptResolverEnv, messageReporter)
|
remainingDefinitionCandidates.partitionLoadDirDefinitions(dep, classpathWithLoader, hostConfiguration, messageReporter)
|
||||||
foundDefinitionClasses.forEach {
|
foundDefinitionClasses.forEach {
|
||||||
yield(it)
|
yield(it)
|
||||||
}
|
}
|
||||||
@@ -170,9 +170,9 @@ fun loadScriptTemplatesFromClasspath(
|
|||||||
classpath: List<File>,
|
classpath: List<File>,
|
||||||
dependenciesClasspath: List<File>,
|
dependenciesClasspath: List<File>,
|
||||||
baseClassLoader: ClassLoader,
|
baseClassLoader: ClassLoader,
|
||||||
scriptResolverEnv: Map<String, Any?>,
|
hostConfiguration: ScriptingHostConfiguration,
|
||||||
messageReporter: MessageReporter
|
messageReporter: MessageReporter
|
||||||
): Sequence<KotlinScriptDefinition> =
|
): Sequence<ScriptDefinition> =
|
||||||
if (scriptTemplates.isEmpty()) emptySequence()
|
if (scriptTemplates.isEmpty()) emptySequence()
|
||||||
else sequence {
|
else sequence {
|
||||||
// trying the direct classloading from baseClassloader first, since this is the most performant variant
|
// trying the direct classloading from baseClassloader first, since this is the most performant variant
|
||||||
@@ -180,7 +180,7 @@ fun loadScriptTemplatesFromClasspath(
|
|||||||
loadScriptDefinition(
|
loadScriptDefinition(
|
||||||
baseClassLoader,
|
baseClassLoader,
|
||||||
it,
|
it,
|
||||||
scriptResolverEnv,
|
hostConfiguration,
|
||||||
messageReporter
|
messageReporter
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -199,11 +199,11 @@ fun loadScriptTemplatesFromClasspath(
|
|||||||
val (loadedDefinitions, notFoundTemplates) = when {
|
val (loadedDefinitions, notFoundTemplates) = when {
|
||||||
dep.isFile && dep.extension == "jar" -> { // checking for extension is the compiler current behaviour, so the same logic is implemented here
|
dep.isFile && dep.extension == "jar" -> { // checking for extension is the compiler current behaviour, so the same logic is implemented here
|
||||||
JarFile(dep).use { jar ->
|
JarFile(dep).use { jar ->
|
||||||
remainingTemplates.partitionLoadJarDefinitions(jar, classpathWithLoader, scriptResolverEnv, messageReporter)
|
remainingTemplates.partitionLoadJarDefinitions(jar, classpathWithLoader, hostConfiguration, messageReporter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dep.isDirectory -> {
|
dep.isDirectory -> {
|
||||||
remainingTemplates.partitionLoadDirDefinitions(dep, classpathWithLoader, scriptResolverEnv, messageReporter)
|
remainingTemplates.partitionLoadDirDefinitions(dep, classpathWithLoader, hostConfiguration, messageReporter)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
// assuming that invalid classpath entries will be reported elsewhere anyway, so do not spam user with additional warnings here
|
// assuming that invalid classpath entries will be reported elsewhere anyway, so do not spam user with additional warnings here
|
||||||
@@ -237,17 +237,17 @@ fun loadScriptTemplatesFromClasspath(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private data class DefinitionsLoadPartitionResult(
|
private data class DefinitionsLoadPartitionResult(
|
||||||
val loaded: List<KotlinScriptDefinition>,
|
val loaded: List<ScriptDefinition>,
|
||||||
val notFound: List<String>
|
val notFound: List<String>
|
||||||
)
|
)
|
||||||
|
|
||||||
private inline fun List<String>.partitionLoadDefinitions(
|
private inline fun List<String>.partitionLoadDefinitions(
|
||||||
classpathWithLoader: ClasspathWithClassLoader,
|
classpathWithLoader: ClasspathWithClassLoader,
|
||||||
scriptResolverEnv: Map<String, Any?>,
|
hostConfiguration: ScriptingHostConfiguration,
|
||||||
noinline messageReporter: MessageReporter,
|
noinline messageReporter: MessageReporter,
|
||||||
getBytes: (String) -> ByteArray?
|
getBytes: (String) -> ByteArray?
|
||||||
): DefinitionsLoadPartitionResult {
|
): DefinitionsLoadPartitionResult {
|
||||||
val loaded = ArrayList<KotlinScriptDefinition>()
|
val loaded = ArrayList<ScriptDefinition>()
|
||||||
val notFound = ArrayList<String>()
|
val notFound = ArrayList<String>()
|
||||||
for (definitionName in this) {
|
for (definitionName in this) {
|
||||||
val classBytes = getBytes(definitionName)
|
val classBytes = getBytes(definitionName)
|
||||||
@@ -256,7 +256,7 @@ private inline fun List<String>.partitionLoadDefinitions(
|
|||||||
it,
|
it,
|
||||||
definitionName,
|
definitionName,
|
||||||
classpathWithLoader,
|
classpathWithLoader,
|
||||||
scriptResolverEnv,
|
hostConfiguration,
|
||||||
messageReporter
|
messageReporter
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -273,18 +273,18 @@ private inline fun List<String>.partitionLoadDefinitions(
|
|||||||
private fun List<String>.partitionLoadJarDefinitions(
|
private fun List<String>.partitionLoadJarDefinitions(
|
||||||
jar: JarFile,
|
jar: JarFile,
|
||||||
classpathWithLoader: ClasspathWithClassLoader,
|
classpathWithLoader: ClasspathWithClassLoader,
|
||||||
scriptResolverEnv: Map<String, Any?>,
|
hostConfiguration: ScriptingHostConfiguration,
|
||||||
messageReporter: MessageReporter
|
messageReporter: MessageReporter
|
||||||
): DefinitionsLoadPartitionResult = partitionLoadDefinitions(classpathWithLoader, scriptResolverEnv, messageReporter) { definitionName ->
|
): DefinitionsLoadPartitionResult = partitionLoadDefinitions(classpathWithLoader, hostConfiguration, messageReporter) { definitionName ->
|
||||||
jar.getJarEntry("${definitionName.replace('.', '/')}.class")?.let { jar.getInputStream(it).readBytes() }
|
jar.getJarEntry("${definitionName.replace('.', '/')}.class")?.let { jar.getInputStream(it).readBytes() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun List<String>.partitionLoadDirDefinitions(
|
private fun List<String>.partitionLoadDirDefinitions(
|
||||||
dir: File,
|
dir: File,
|
||||||
classpathWithLoader: ClasspathWithClassLoader,
|
classpathWithLoader: ClasspathWithClassLoader,
|
||||||
scriptResolverEnv: Map<String, Any?>,
|
hostConfiguration: ScriptingHostConfiguration,
|
||||||
messageReporter: MessageReporter
|
messageReporter: MessageReporter
|
||||||
): DefinitionsLoadPartitionResult = partitionLoadDefinitions(classpathWithLoader, scriptResolverEnv, messageReporter) { definitionName ->
|
): DefinitionsLoadPartitionResult = partitionLoadDefinitions(classpathWithLoader, hostConfiguration, messageReporter) { definitionName ->
|
||||||
File(dir, "${definitionName.replace('.', '/')}.class").takeIf { it.exists() && it.isFile }?.readBytes()
|
File(dir, "${definitionName.replace('.', '/')}.class").takeIf { it.exists() && it.isFile }?.readBytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,14 +292,15 @@ private fun loadScriptDefinition(
|
|||||||
templateClassBytes: ByteArray,
|
templateClassBytes: ByteArray,
|
||||||
templateClassName: String,
|
templateClassName: String,
|
||||||
classpathWithLoader: ClasspathWithClassLoader,
|
classpathWithLoader: ClasspathWithClassLoader,
|
||||||
scriptResolverEnv: Map<String, Any?>,
|
hostConfiguration: ScriptingHostConfiguration,
|
||||||
messageReporter: MessageReporter
|
messageReporter: MessageReporter
|
||||||
): KotlinScriptDefinition? {
|
): ScriptDefinition? {
|
||||||
val anns = loadAnnotationsFromClass(templateClassBytes)
|
val anns = loadAnnotationsFromClass(templateClassBytes)
|
||||||
for (ann in anns) {
|
for (ann in anns) {
|
||||||
var def: KotlinScriptDefinition? = null
|
var def: ScriptDefinition? = null
|
||||||
if (ann.name == KotlinScript::class.simpleName) {
|
if (ann.name == KotlinScript::class.simpleName) {
|
||||||
def = LazyScriptDefinitionFromDiscoveredClass(
|
def = LazyScriptDefinitionFromDiscoveredClass(
|
||||||
|
hostConfiguration,
|
||||||
anns,
|
anns,
|
||||||
templateClassName,
|
templateClassName,
|
||||||
classpathWithLoader.classpath,
|
classpathWithLoader.classpath,
|
||||||
@@ -307,7 +308,14 @@ private fun loadScriptDefinition(
|
|||||||
)
|
)
|
||||||
} else if (ann.name == ScriptTemplateDefinition::class.simpleName) {
|
} else if (ann.name == ScriptTemplateDefinition::class.simpleName) {
|
||||||
val templateClass = classpathWithLoader.classLoader.loadClass(templateClassName).kotlin
|
val templateClass = classpathWithLoader.classLoader.loadClass(templateClassName).kotlin
|
||||||
def = KotlinScriptDefinitionFromAnnotatedTemplate(templateClass, scriptResolverEnv, classpathWithLoader.classpath)
|
def = ScriptDefinition.FromLegacy(
|
||||||
|
hostConfiguration,
|
||||||
|
KotlinScriptDefinitionFromAnnotatedTemplate(
|
||||||
|
templateClass,
|
||||||
|
hostConfiguration[ScriptingHostConfiguration.getEnvironment]?.invoke().orEmpty(),
|
||||||
|
classpathWithLoader.classpath
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (def != null) {
|
if (def != null) {
|
||||||
messageReporter(
|
messageReporter(
|
||||||
@@ -327,29 +335,20 @@ private fun loadScriptDefinition(
|
|||||||
private fun loadScriptDefinition(
|
private fun loadScriptDefinition(
|
||||||
classLoader: ClassLoader,
|
classLoader: ClassLoader,
|
||||||
template: String,
|
template: String,
|
||||||
scriptResolverEnv: Map<String, Any?>,
|
hostConfiguration: ScriptingHostConfiguration,
|
||||||
messageReporter: MessageReporter
|
messageReporter: MessageReporter
|
||||||
): KotlinScriptDefinition? {
|
): ScriptDefinition? {
|
||||||
try {
|
try {
|
||||||
val cls = classLoader.loadClass(template)
|
val cls = classLoader.loadClass(template)
|
||||||
val def =
|
val def =
|
||||||
if (cls.annotations.firstIsInstanceOrNull<KotlinScript>() != null) {
|
if (cls.annotations.firstIsInstanceOrNull<KotlinScript>() != null) {
|
||||||
val environment = defaultJvmScriptingHostConfiguration
|
ScriptDefinition.FromTemplate(hostConfiguration, cls.kotlin, ScriptDefinition::class)
|
||||||
KotlinScriptDefinitionAdapterFromNewAPI(
|
|
||||||
createCompilationConfigurationFromTemplate(
|
|
||||||
KotlinType(cls.kotlin),
|
|
||||||
environment,
|
|
||||||
KotlinScriptDefinition::class
|
|
||||||
),
|
|
||||||
environment
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
KotlinScriptDefinitionFromAnnotatedTemplate(cls.kotlin, scriptResolverEnv)
|
ScriptDefinition.FromLegacyTemplate(hostConfiguration, cls.kotlin)
|
||||||
}
|
}
|
||||||
messageReporter(
|
messageReporter(
|
||||||
CompilerMessageSeverity.INFO,
|
CompilerMessageSeverity.INFO,
|
||||||
"Added script definition $template to configuration: name = ${def.name}, " +
|
"Added script definition $template to configuration: name = ${def.name}"
|
||||||
"resolver = ${def.dependencyResolver.javaClass.name}"
|
|
||||||
)
|
)
|
||||||
return def
|
return def
|
||||||
} catch (ex: ClassNotFoundException) {
|
} catch (ex: ClassNotFoundException) {
|
||||||
|
|||||||
+9
-7
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.scripting.definitions
|
package org.jetbrains.kotlin.scripting.definitions
|
||||||
|
|
||||||
import com.intellij.ide.highlighter.JavaClassFileType
|
import com.intellij.ide.highlighter.JavaClassFileType
|
||||||
|
import com.intellij.openapi.application.runReadAction
|
||||||
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
@@ -14,30 +15,31 @@ import com.intellij.psi.PsiManager
|
|||||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
fun PsiFile.scriptDefinition(): KotlinScriptDefinition? {
|
fun PsiFile.findScriptDefinition(): ScriptDefinition? {
|
||||||
// Do not use psiFile.script, see comments in findScriptDefinition
|
// Do not use psiFile.script, see comments in findScriptDefinition
|
||||||
if (this !is KtFile/* || this.script == null*/) return null
|
if (this !is KtFile/* || this.script == null*/) return null
|
||||||
val file = virtualFile ?: originalFile.virtualFile ?: return null
|
val file = virtualFile ?: originalFile.virtualFile ?: return null
|
||||||
if (file.isNonScript()) return null
|
if (file.isNonScript()) return null
|
||||||
|
|
||||||
return scriptDefinitionByFileName(project, file.name)
|
return findScriptDefinitionByFileName(project, file.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VirtualFile.findScriptDefinition(project: Project): KotlinScriptDefinition? {
|
fun VirtualFile.findScriptDefinition(project: Project): ScriptDefinition? {
|
||||||
if (!isValid || isNonScript()) return null
|
if (!isValid || isNonScript()) return null
|
||||||
// Do not use psiFile.script here because this method can be called during indexes access
|
// Do not use psiFile.script here because this method can be called during indexes access
|
||||||
// and accessing stubs may cause deadlock
|
// and accessing stubs may cause deadlock
|
||||||
// TODO: measure performance effect and if necessary consider detecting indexing here or using separate logic for non-IDE operations to speed up filtering
|
// TODO: measure performance effect and if necessary consider detecting indexing here or using separate logic for non-IDE operations to speed up filtering
|
||||||
if ((PsiManager.getInstance(project).findFile(this) as? KtFile)/*?.script*/ == null) return null
|
|
||||||
|
|
||||||
return scriptDefinitionByFileName(project, name)
|
if (runReadAction { PsiManager.getInstance(project).findFile(this) as? KtFile }/*?.script*/ == null) return null
|
||||||
|
|
||||||
|
return findScriptDefinitionByFileName(project, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun scriptDefinitionByFileName(project: Project, fileName: String): KotlinScriptDefinition {
|
fun findScriptDefinitionByFileName(project: Project, fileName: String): ScriptDefinition {
|
||||||
val scriptDefinitionProvider = ScriptDefinitionProvider.getInstance(project) ?: return null
|
val scriptDefinitionProvider = ScriptDefinitionProvider.getInstance(project) ?: return null
|
||||||
?: throw IllegalStateException("Unable to get script definition: ScriptDefinitionProvider is not configured.")
|
?: throw IllegalStateException("Unable to get script definition: ScriptDefinitionProvider is not configured.")
|
||||||
|
|
||||||
return scriptDefinitionProvider.findScriptDefinition(fileName) ?: scriptDefinitionProvider.getDefaultScriptDefinition()
|
return scriptDefinitionProvider.findDefinition(fileName) ?: scriptDefinitionProvider.getDefaultDefinition()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun VirtualFile.isNonScript(): Boolean =
|
private fun VirtualFile.isNonScript(): Boolean =
|
||||||
|
|||||||
+5
-4
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
|
|||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.script.experimental.api.valueOrNull
|
||||||
|
|
||||||
data class ScriptsCompilationDependencies(
|
data class ScriptsCompilationDependencies(
|
||||||
val classpath: List<File>,
|
val classpath: List<File>,
|
||||||
@@ -41,11 +42,11 @@ fun collectScriptsCompilationDependencies(
|
|||||||
while (true) {
|
while (true) {
|
||||||
val newRemainingSources = ArrayList<KtFile>()
|
val newRemainingSources = ArrayList<KtFile>()
|
||||||
for (source in remainingSources) {
|
for (source in remainingSources) {
|
||||||
val dependencies = importsProvider.getScriptDependencies(source)
|
val refinedConfiguration = importsProvider.getScriptConfigurationResult(source)?.valueOrNull()
|
||||||
if (dependencies != null) {
|
if (refinedConfiguration != null) {
|
||||||
collectedClassPath.addAll(dependencies.classpath)
|
collectedClassPath.addAll(refinedConfiguration.dependenciesClassPath)
|
||||||
|
|
||||||
val sourceDependenciesRoots = dependencies.scripts.map {
|
val sourceDependenciesRoots = refinedConfiguration.importedScripts.map {
|
||||||
KotlinSourceRoot(it.path, false)
|
KotlinSourceRoot(it.path, false)
|
||||||
}
|
}
|
||||||
val sourceDependencies =
|
val sourceDependencies =
|
||||||
|
|||||||
+3
-2
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.psi.KtImportInfo
|
|||||||
import org.jetbrains.kotlin.resolve.ImportPath
|
import org.jetbrains.kotlin.resolve.ImportPath
|
||||||
import org.jetbrains.kotlin.resolve.extensions.ExtraImportsProviderExtension
|
import org.jetbrains.kotlin.resolve.extensions.ExtraImportsProviderExtension
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
||||||
|
import kotlin.script.experimental.api.valueOrNull
|
||||||
|
|
||||||
class ScriptExtraImportsProviderExtension : ExtraImportsProviderExtension {
|
class ScriptExtraImportsProviderExtension : ExtraImportsProviderExtension {
|
||||||
|
|
||||||
@@ -28,8 +29,8 @@ class ScriptExtraImportsProviderExtension : ExtraImportsProviderExtension {
|
|||||||
|
|
||||||
override fun getExtraImports(ktFile: KtFile): Collection<KtImportInfo> =
|
override fun getExtraImports(ktFile: KtFile): Collection<KtImportInfo> =
|
||||||
ktFile.takeIf { it.isScript() }?.let { file ->
|
ktFile.takeIf { it.isScript() }?.let { file ->
|
||||||
val scriptDependencies = ScriptDependenciesProvider.getInstance(file.project)?.getScriptDependencies(file.originalFile)
|
val refinedConfiguration = ScriptDependenciesProvider.getInstance(file.project)?.getScriptConfigurationResult(file.originalFile)?.valueOrNull()
|
||||||
scriptDependencies?.imports?.map {
|
refinedConfiguration?.defaultImports?.map {
|
||||||
ScriptExtraImportImpl(
|
ScriptExtraImportImpl(
|
||||||
ImportPath.fromString(it)
|
ImportPath.fromString(it)
|
||||||
)
|
)
|
||||||
|
|||||||
+3
-1
@@ -25,8 +25,10 @@ import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
|||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.repl.messages.ConsoleDiagnosticMessageHolder
|
import org.jetbrains.kotlin.scripting.repl.messages.ConsoleDiagnosticMessageHolder
|
||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
const val KOTLIN_REPL_JVM_TARGET_PROPERTY = "kotlin.repl.jvm.target"
|
const val KOTLIN_REPL_JVM_TARGET_PROPERTY = "kotlin.repl.jvm.target"
|
||||||
|
|
||||||
@@ -39,7 +41,7 @@ open class GenericReplChecker(
|
|||||||
|
|
||||||
internal val environment = run {
|
internal val environment = run {
|
||||||
compilerConfiguration.apply {
|
compilerConfiguration.apply {
|
||||||
add(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, scriptDefinition)
|
add(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, ScriptDefinition.FromLegacy(defaultJvmScriptingHostConfiguration, scriptDefinition))
|
||||||
put<MessageCollector>(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
put<MessageCollector>(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
||||||
put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
|
put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
|
import kotlin.script.experimental.api.valueOrNull
|
||||||
|
|
||||||
// WARNING: not thread safe, assuming external synchronization
|
// WARNING: not thread safe, assuming external synchronization
|
||||||
|
|
||||||
@@ -64,7 +65,9 @@ open class GenericReplCompiler(
|
|||||||
Pair(compilerState.lastLineState!!.psiFile, compilerState.lastLineState!!.errorHolder)
|
Pair(compilerState.lastLineState!!.psiFile, compilerState.lastLineState!!.errorHolder)
|
||||||
}
|
}
|
||||||
|
|
||||||
val newDependencies = ScriptDependenciesProvider.getInstance(checker.environment.project)?.getScriptDependencies(psiFile)
|
val newDependencies =
|
||||||
|
ScriptDependenciesProvider.getInstance(checker.environment.project)?.getScriptConfigurationResult(psiFile)?.valueOrNull()
|
||||||
|
?.legacyDependencies
|
||||||
var classpathAddendum: List<File>? = null
|
var classpathAddendum: List<File>? = null
|
||||||
if (compilerState.lastDependencies != newDependencies) {
|
if (compilerState.lastDependencies != newDependencies) {
|
||||||
compilerState.lastDependencies = newDependencies
|
compilerState.lastDependencies = newDependencies
|
||||||
|
|||||||
+10
-8
@@ -33,10 +33,10 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeImpl
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeImpl
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
|
||||||
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptPriorities
|
import org.jetbrains.kotlin.scripting.definitions.ScriptPriorities
|
||||||
import org.jetbrains.kotlin.scripting.definitions.scriptDefinitionByFileName
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinitionByFileName
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.script.experimental.api.valueOrNull
|
||||||
|
|
||||||
|
|
||||||
class LazyScriptDescriptor(
|
class LazyScriptDescriptor(
|
||||||
@@ -104,8 +105,9 @@ class LazyScriptDescriptor(
|
|||||||
|
|
||||||
override fun getPriority() = priority
|
override fun getPriority() = priority
|
||||||
|
|
||||||
val scriptDefinition: () -> KotlinScriptDefinition = resolveSession.storageManager.createLazyValue {
|
// rewrite without using legacyDefinition below
|
||||||
scriptDefinitionByFileName(
|
val scriptDefinition: () -> ScriptDefinition = resolveSession.storageManager.createLazyValue {
|
||||||
|
findScriptDefinitionByFileName(
|
||||||
resolveSession.project,
|
resolveSession.project,
|
||||||
scriptInfo.script.containingKtFile.name
|
scriptInfo.script.containingKtFile.name
|
||||||
)
|
)
|
||||||
@@ -128,7 +130,7 @@ class LazyScriptDescriptor(
|
|||||||
override fun getUnsubstitutedPrimaryConstructor() = super.getUnsubstitutedPrimaryConstructor()!!
|
override fun getUnsubstitutedPrimaryConstructor() = super.getUnsubstitutedPrimaryConstructor()!!
|
||||||
|
|
||||||
internal val baseClassDescriptor: () -> ClassDescriptor? = resolveSession.storageManager.createNullableLazyValue {
|
internal val baseClassDescriptor: () -> ClassDescriptor? = resolveSession.storageManager.createNullableLazyValue {
|
||||||
val template = scriptDefinition().template
|
val template = scriptDefinition().legacyDefinition.template
|
||||||
findTypeDescriptor(
|
findTypeDescriptor(
|
||||||
template,
|
template,
|
||||||
if (template.qualifiedName?.startsWith("kotlin.script.templates.standard") == true) Errors.MISSING_SCRIPT_STANDARD_TEMPLATE
|
if (template.qualifiedName?.startsWith("kotlin.script.templates.standard") == true) Errors.MISSING_SCRIPT_STANDARD_TEMPLATE
|
||||||
@@ -167,7 +169,7 @@ class LazyScriptDescriptor(
|
|||||||
val res = ArrayList<ClassDescriptor>()
|
val res = ArrayList<ClassDescriptor>()
|
||||||
|
|
||||||
val importedScriptsFiles = ScriptDependenciesProvider.getInstance(scriptInfo.script.project)
|
val importedScriptsFiles = ScriptDependenciesProvider.getInstance(scriptInfo.script.project)
|
||||||
?.getScriptDependencies(scriptInfo.script.containingKtFile)?.scripts
|
?.getScriptConfigurationResult(scriptInfo.script.containingKtFile)?.valueOrNull()?.importedScripts
|
||||||
if (importedScriptsFiles != null) {
|
if (importedScriptsFiles != null) {
|
||||||
val findImportedScriptDescriptor = ImportedScriptDescriptorsFinder()
|
val findImportedScriptDescriptor = ImportedScriptDescriptorsFinder()
|
||||||
importedScriptsFiles.mapNotNullTo(res) {
|
importedScriptsFiles.mapNotNullTo(res) {
|
||||||
@@ -175,7 +177,7 @@ class LazyScriptDescriptor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptDefinition().implicitReceivers.mapNotNullTo(res) { receiver ->
|
scriptDefinition().legacyDefinition.implicitReceivers.mapNotNullTo(res) { receiver ->
|
||||||
findTypeDescriptor(receiver, Errors.MISSING_SCRIPT_RECEIVER_CLASS)
|
findTypeDescriptor(receiver, Errors.MISSING_SCRIPT_RECEIVER_CLASS)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +224,7 @@ class LazyScriptDescriptor(
|
|||||||
private val scriptOuterScope: () -> LexicalScope = resolveSession.storageManager.createLazyValue {
|
private val scriptOuterScope: () -> LexicalScope = resolveSession.storageManager.createLazyValue {
|
||||||
var outerScope = super.getOuterScope()
|
var outerScope = super.getOuterScope()
|
||||||
val outerScopeReceivers = implicitReceivers.let {
|
val outerScopeReceivers = implicitReceivers.let {
|
||||||
if (scriptDefinition().providedProperties.isEmpty()) {
|
if (scriptDefinition().legacyDefinition.providedProperties.isEmpty()) {
|
||||||
it
|
it
|
||||||
} else {
|
} else {
|
||||||
it + ScriptProvidedPropertiesDescriptor(this)
|
it + ScriptProvidedPropertiesDescriptor(this)
|
||||||
|
|||||||
+12
-41
@@ -5,16 +5,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.scripting.resolve
|
package org.jetbrains.kotlin.scripting.resolve
|
||||||
|
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.PsiFile
|
|
||||||
import com.intellij.psi.PsiManager
|
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.reflect.KClass
|
|
||||||
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
|
||||||
@@ -22,43 +16,20 @@ 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) {
|
||||||
fun getScriptContents(scriptDefinition: KotlinScriptDefinition, file: VirtualFile)
|
fun getScriptContents(scriptDefinition: KotlinScriptDefinition, file: VirtualFile) =
|
||||||
= BasicScriptContents(
|
makeScriptContents(
|
||||||
file,
|
file,
|
||||||
getAnnotations = { loadAnnotations(scriptDefinition, file) })
|
scriptDefinition,
|
||||||
|
project,
|
||||||
private fun loadAnnotations(scriptDefinition: KotlinScriptDefinition, file: VirtualFile): List<Annotation> {
|
scriptDefinition.template::class.java.classLoader
|
||||||
val classLoader = scriptDefinition.template.java.classLoader
|
)
|
||||||
// TODO_R: report error on failure to load annotation class
|
|
||||||
return ApplicationManager.getApplication().runReadAction<List<Annotation>> {
|
|
||||||
getAnnotationEntries(file, project)
|
|
||||||
.mapNotNull { psiAnn ->
|
|
||||||
// TODO: consider advanced matching using semantic similar to actual resolving
|
|
||||||
scriptDefinition.acceptedAnnotations.find { ann ->
|
|
||||||
psiAnn.typeName.let { it == ann.simpleName || it == ann.qualifiedName }
|
|
||||||
}?.let {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
constructAnnotation(
|
|
||||||
psiAnn,
|
|
||||||
classLoader.loadClass(it.qualifiedName).kotlin as KClass<out Annotation>,
|
|
||||||
project
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getAnnotationEntries(file: VirtualFile, project: Project): Iterable<KtAnnotationEntry> {
|
|
||||||
val psiFile: PsiFile = PsiManager.getInstance(project).findFile(file)
|
|
||||||
?: throw IllegalArgumentException("Unable to load PSI from ${file.canonicalPath}")
|
|
||||||
return (psiFile as? KtFile)?.annotationEntries
|
|
||||||
?: throw IllegalArgumentException("Unable to extract kotlin annotations from ${file.name} (${file.fileType})")
|
|
||||||
}
|
|
||||||
|
|
||||||
class BasicScriptContents(virtualFile: VirtualFile, getAnnotations: () -> Iterable<Annotation>) : ScriptContents {
|
class BasicScriptContents(virtualFile: VirtualFile, getAnnotations: () -> Iterable<Annotation>) : ScriptContents {
|
||||||
override val file: File = File(virtualFile.path)
|
override val file: File = File(virtualFile.path)
|
||||||
override val annotations: Iterable<Annotation> by lazy(LazyThreadSafetyMode.PUBLICATION) { getAnnotations() }
|
override val annotations: Iterable<Annotation> by lazy(LazyThreadSafetyMode.PUBLICATION) { getAnnotations() }
|
||||||
override val text: CharSequence? by lazy(LazyThreadSafetyMode.PUBLICATION) { virtualFile.inputStream.reader(charset = virtualFile.charset).readText() }
|
override val text: CharSequence? by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||||
|
virtualFile.inputStream.reader(charset = virtualFile.charset).readText()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadContentsAndResolveDependencies(
|
fun loadContentsAndResolveDependencies(
|
||||||
@@ -80,11 +51,11 @@ class ScriptContentLoader(private val project: Project) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getEnvironment(scriptDef: KotlinScriptDefinition) =
|
fun getEnvironment(scriptDef: KotlinScriptDefinition) =
|
||||||
(scriptDef as? KotlinScriptDefinitionFromAnnotatedTemplate)?.environment.orEmpty()
|
(scriptDef as? KotlinScriptDefinitionFromAnnotatedTemplate)?.environment.orEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ScriptDependencies.adjustByDefinition(
|
fun ScriptDependencies.adjustByDefinition(
|
||||||
scriptDef: KotlinScriptDefinition
|
scriptDef: KotlinScriptDefinition
|
||||||
): ScriptDependencies {
|
): ScriptDependencies {
|
||||||
val additionalClasspath = (scriptDef as? KotlinScriptDefinitionFromAnnotatedTemplate)?.templateClasspath ?: return this
|
val additionalClasspath = (scriptDef as? KotlinScriptDefinitionFromAnnotatedTemplate)?.templateClasspath ?: return this
|
||||||
if (additionalClasspath.isEmpty()) return this
|
if (additionalClasspath.isEmpty()) return this
|
||||||
|
|||||||
+1
-1
@@ -42,7 +42,7 @@ class ScriptProvidedPropertiesDescriptor(script: LazyScriptDescriptor) :
|
|||||||
override fun getUnsubstitutedMemberScope(): MemberScope = memberScope()
|
override fun getUnsubstitutedMemberScope(): MemberScope = memberScope()
|
||||||
|
|
||||||
val properties: () -> List<ScriptProvidedPropertyDescriptor> = script.resolveSession.storageManager.createLazyValue {
|
val properties: () -> List<ScriptProvidedPropertyDescriptor> = script.resolveSession.storageManager.createLazyValue {
|
||||||
script.scriptDefinition().providedProperties.mapNotNull { (name, type) ->
|
script.scriptDefinition().legacyDefinition.providedProperties.mapNotNull { (name, type) ->
|
||||||
script.findTypeDescriptor(type, Errors.MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS)?.let {
|
script.findTypeDescriptor(type, Errors.MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS)?.let {
|
||||||
name to it
|
name to it
|
||||||
}
|
}
|
||||||
|
|||||||
+338
@@ -0,0 +1,338 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.scripting.resolve
|
||||||
|
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
|
import com.intellij.openapi.vfs.CharsetToolkit
|
||||||
|
import com.intellij.openapi.vfs.LocalFileSystem
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
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
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
|
import java.io.File
|
||||||
|
import java.net.URL
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.script.experimental.api.*
|
||||||
|
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.jvm.JvmGetScriptingClass
|
||||||
|
import kotlin.script.experimental.jvm.compat.mapToDiagnostics
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.impl.refineWith
|
||||||
|
import kotlin.script.experimental.jvm.impl.toClassPathOrEmpty
|
||||||
|
import kotlin.script.experimental.jvm.impl.toDependencies
|
||||||
|
import kotlin.script.experimental.jvm.jdkHome
|
||||||
|
import kotlin.script.experimental.jvm.jvm
|
||||||
|
|
||||||
|
internal fun VirtualFile.loadAnnotations(
|
||||||
|
acceptedAnnotations: List<KClass<out Annotation>>,
|
||||||
|
project: Project,
|
||||||
|
classLoader: ClassLoader?
|
||||||
|
): List<Annotation> =
|
||||||
|
// TODO_R: report error on failure to load annotation class
|
||||||
|
ApplicationManager.getApplication().runReadAction<List<Annotation>> {
|
||||||
|
this.getAnnotationEntries(project).construct(classLoader, acceptedAnnotations, project)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun VirtualFile.getAnnotationEntries(project: Project): Iterable<KtAnnotationEntry> {
|
||||||
|
val psiFile: PsiFile = PsiManager.getInstance(project).findFile(this)
|
||||||
|
?: throw IllegalArgumentException("Unable to load PSI from $canonicalPath")
|
||||||
|
return (psiFile as? KtFile)?.annotationEntries
|
||||||
|
?: throw IllegalArgumentException("Unable to extract kotlin annotations from $name ($fileType)")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The implementation of the SourceCode for a script located in a virtual file
|
||||||
|
*/
|
||||||
|
open class VirtualFileScriptSource(val virtualFile: VirtualFile, private val preloadedText: String? = null) :
|
||||||
|
FileBasedScriptSource()
|
||||||
|
{
|
||||||
|
override val file: File get() = File(virtualFile.path)
|
||||||
|
override val externalLocation: URL get() = URL(virtualFile.url)
|
||||||
|
override val text: String by lazy { preloadedText ?: virtualFile.inputStream.bufferedReader().readText() }
|
||||||
|
override val name: String? get() = virtualFile.name
|
||||||
|
override val locationId: String? get() = virtualFile.path
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
this === other || (other as? VirtualFileScriptSource)?.let { virtualFile == it.virtualFile } == true
|
||||||
|
|
||||||
|
override fun hashCode(): Int = virtualFile.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The implementation of the SourceCode for a script located in a KtFile
|
||||||
|
*/
|
||||||
|
open class KtFileScriptSource(val ktFile: KtFile, preloadedText: String? = null) :
|
||||||
|
VirtualFileScriptSource(ktFile.virtualFile ?: ktFile.originalFile.virtualFile, preloadedText) {
|
||||||
|
|
||||||
|
override val text: String by lazy { preloadedText ?: ktFile.text }
|
||||||
|
override val name: String? get() = ktFile.name
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
this === other
|
||||||
|
|| (other as? KtFileScriptSource)?.let { ktFile == it.ktFile } == true
|
||||||
|
|| super.equals(other)
|
||||||
|
|
||||||
|
override fun hashCode(): Int = ktFile.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScriptLightVirtualFile(name: String, private val _path: String?, text: String) :
|
||||||
|
LightVirtualFile(
|
||||||
|
name,
|
||||||
|
KotlinLanguage.INSTANCE,
|
||||||
|
StringUtil.convertLineSeparators(text)
|
||||||
|
) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
charset = CharsetToolkit.UTF8_CHARSET
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPath(): String = _path ?: super.getPath()
|
||||||
|
override fun getCanonicalPath(): String? = path
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ScriptCompilationConfigurationWrapper(val script: SourceCode) {
|
||||||
|
abstract val configuration: ScriptCompilationConfiguration?
|
||||||
|
|
||||||
|
@Deprecated("Use configuration collection instead")
|
||||||
|
abstract val legacyDependencies: ScriptDependencies?
|
||||||
|
|
||||||
|
// optimizing most common ops for the IDE
|
||||||
|
// TODO: consider dropping after complete migration
|
||||||
|
abstract val dependenciesClassPath: List<File>
|
||||||
|
abstract val dependenciesSources: List<File>
|
||||||
|
abstract val javaHome: File?
|
||||||
|
abstract val defaultImports: List<String>
|
||||||
|
abstract val importedScripts: List<File>
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean = script == (other as? ScriptCompilationConfigurationWrapper)?.script
|
||||||
|
|
||||||
|
override fun hashCode(): Int = script.hashCode()
|
||||||
|
|
||||||
|
class FromCompilationConfiguration(
|
||||||
|
script: SourceCode,
|
||||||
|
override val configuration: ScriptCompilationConfiguration?
|
||||||
|
) : ScriptCompilationConfigurationWrapper(script) {
|
||||||
|
|
||||||
|
// TODO: check whether implemented optimization for frequent calls makes sense here
|
||||||
|
override val dependenciesClassPath: List<File> by lazy {
|
||||||
|
configuration?.get(ScriptCompilationConfiguration.dependencies).toClassPathOrEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check whether implemented optimization for frequent calls makes sense here
|
||||||
|
override val dependenciesSources: List<File> by lazy {
|
||||||
|
configuration?.get(ScriptCompilationConfiguration.ide.dependenciesSources).toClassPathOrEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val javaHome: File?
|
||||||
|
get() = configuration?.get(ScriptCompilationConfiguration.hostConfiguration)?.get(ScriptingHostConfiguration.jvm.jdkHome)
|
||||||
|
|
||||||
|
override val defaultImports: List<String>
|
||||||
|
get() = configuration?.get(ScriptCompilationConfiguration.defaultImports).orEmpty()
|
||||||
|
|
||||||
|
override val importedScripts: List<File>
|
||||||
|
get() = configuration?.get(ScriptCompilationConfiguration.importScripts)
|
||||||
|
?.mapNotNull { (it as? FileBasedScriptSource)?.file }.orEmpty()
|
||||||
|
|
||||||
|
override val legacyDependencies: ScriptDependencies?
|
||||||
|
get() = configuration?.toDependencies(dependenciesClassPath)
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
super.equals(other) && other is FromCompilationConfiguration && configuration == other.configuration
|
||||||
|
|
||||||
|
override fun hashCode(): Int = super.hashCode() + 23 * (configuration?.hashCode() ?: 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
class FromLegacy(
|
||||||
|
script: SourceCode,
|
||||||
|
override val legacyDependencies: ScriptDependencies?
|
||||||
|
) : ScriptCompilationConfigurationWrapper(script) {
|
||||||
|
|
||||||
|
override val dependenciesClassPath: List<File>
|
||||||
|
get() = legacyDependencies?.classpath.orEmpty()
|
||||||
|
|
||||||
|
override val dependenciesSources: List<File>
|
||||||
|
get() = legacyDependencies?.sources.orEmpty()
|
||||||
|
|
||||||
|
override val javaHome: File?
|
||||||
|
get() = legacyDependencies?.javaHome
|
||||||
|
|
||||||
|
override val defaultImports: List<String>
|
||||||
|
get() = legacyDependencies?.imports.orEmpty()
|
||||||
|
|
||||||
|
override val importedScripts: List<File>
|
||||||
|
get() = legacyDependencies?.scripts.orEmpty()
|
||||||
|
|
||||||
|
override val configuration: ScriptCompilationConfiguration?
|
||||||
|
get() = legacyDependencies?.let {
|
||||||
|
TODO("drop or implement")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
super.equals(other) && other is FromLegacy && legacyDependencies == other.legacyDependencies
|
||||||
|
|
||||||
|
override fun hashCode(): Int = super.hashCode() + 31 * (legacyDependencies?.hashCode() ?: 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias ScriptCompilationConfigurationResult = ResultWithDiagnostics<ScriptCompilationConfigurationWrapper>
|
||||||
|
|
||||||
|
fun refineScriptCompilationConfiguration(
|
||||||
|
script: SourceCode,
|
||||||
|
definition: ScriptDefinition,
|
||||||
|
project: Project
|
||||||
|
): ScriptCompilationConfigurationResult {
|
||||||
|
val ktFileSource = script.toKtFileSource(definition, project)
|
||||||
|
val legacyDefinition = definition.asLegacyOrNull<KotlinScriptDefinition>()
|
||||||
|
if (legacyDefinition == null) {
|
||||||
|
val compilationConfiguration = definition.compilationConfiguration
|
||||||
|
val collectedData =
|
||||||
|
getScriptCollectedData(ktFileSource.ktFile, compilationConfiguration, project, definition.contextClassLoader)
|
||||||
|
|
||||||
|
return compilationConfiguration.refineWith(
|
||||||
|
compilationConfiguration[ScriptCompilationConfiguration.refineConfigurationOnAnnotations]?.handler, collectedData, script
|
||||||
|
).onSuccess {
|
||||||
|
it.refineWith(
|
||||||
|
compilationConfiguration[ScriptCompilationConfiguration.refineConfigurationBeforeCompiling]?.handler, collectedData, script
|
||||||
|
)
|
||||||
|
}.onSuccess {
|
||||||
|
ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(ktFileSource, it).asSuccess()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val file = script.getVirtualFile(definition)
|
||||||
|
val scriptContents =
|
||||||
|
makeScriptContents(file, legacyDefinition, project, definition.contextClassLoader)
|
||||||
|
val environment = (legacyDefinition as? KotlinScriptDefinitionFromAnnotatedTemplate)?.environment.orEmpty()
|
||||||
|
|
||||||
|
val result: DependenciesResolver.ResolveResult = try {
|
||||||
|
val resolver = legacyDefinition.dependencyResolver
|
||||||
|
if (resolver is AsyncDependenciesResolver) {
|
||||||
|
// since the only known async resolver is gradle, the following logic is taken from AsyncScriptDependenciesLoader
|
||||||
|
// 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 {
|
||||||
|
resolver.resolveAsync(scriptContents, environment)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resolver.resolve(scriptContents, environment)
|
||||||
|
}
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
return makeFailureResult(e.asDiagnostics(severity = ScriptDiagnostic.Severity.FATAL))
|
||||||
|
}
|
||||||
|
return if (result is DependenciesResolver.ResolveResult.Failure)
|
||||||
|
makeFailureResult(
|
||||||
|
result.reports.mapToDiagnostics()
|
||||||
|
)
|
||||||
|
else
|
||||||
|
ScriptCompilationConfigurationWrapper.FromLegacy(
|
||||||
|
ktFileSource,
|
||||||
|
result.dependencies?.adjustByDefinition(definition.legacyDefinition)
|
||||||
|
).asSuccess(result.reports.mapToDiagnostics())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun makeScriptContents(
|
||||||
|
file: VirtualFile,
|
||||||
|
legacyDefinition: KotlinScriptDefinition,
|
||||||
|
project: Project,
|
||||||
|
classLoader: ClassLoader?
|
||||||
|
): ScriptContentLoader.BasicScriptContents =
|
||||||
|
ScriptContentLoader.BasicScriptContents(
|
||||||
|
file,
|
||||||
|
getAnnotations = {
|
||||||
|
file.loadAnnotations(legacyDefinition.acceptedAnnotations, project, classLoader)
|
||||||
|
})
|
||||||
|
|
||||||
|
fun SourceCode.getVirtualFile(definition: ScriptDefinition): VirtualFile {
|
||||||
|
if (this is VirtualFileScriptSource) return virtualFile
|
||||||
|
if (this is KtFileScriptSource) {
|
||||||
|
val vFile = virtualFile
|
||||||
|
if (vFile != null) return vFile
|
||||||
|
}
|
||||||
|
if (this is FileScriptSource) {
|
||||||
|
val vFile = LocalFileSystem.getInstance().findFileByIoFile(file)
|
||||||
|
if (vFile != null) return vFile
|
||||||
|
}
|
||||||
|
val scriptName = name ?: "script.${definition.fileExtension}"
|
||||||
|
val scriptPath = when (this) {
|
||||||
|
is FileScriptSource -> file.path
|
||||||
|
is ExternalSourceCode -> externalLocation.toString()
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
val scriptText = definition.asLegacyOrNull<KotlinScriptDefinition>()?.let { text }
|
||||||
|
?: getMergedScriptText(this, definition.compilationConfiguration)
|
||||||
|
|
||||||
|
return ScriptLightVirtualFile(scriptName, scriptPath, scriptText)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun SourceCode.getKtFile(definition: ScriptDefinition, project: Project): KtFile =
|
||||||
|
if (this is KtFileScriptSource) ktFile
|
||||||
|
else {
|
||||||
|
val file = getVirtualFile(definition)
|
||||||
|
ApplicationManager.getApplication().runReadAction<KtFile> {
|
||||||
|
val psiFile: PsiFile = PsiManager.getInstance(project).findFile(file)
|
||||||
|
?: throw IllegalArgumentException("Unable to load PSI from ${file.path}")
|
||||||
|
(psiFile as? KtFile)
|
||||||
|
?: throw IllegalArgumentException("Not a kotlin file ${file.path} (${file.fileType})")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun SourceCode.toKtFileSource(definition: ScriptDefinition, project: Project): KtFileScriptSource =
|
||||||
|
if (this is KtFileScriptSource) this
|
||||||
|
else {
|
||||||
|
KtFileScriptSource(this.getKtFile(definition, project))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getScriptCollectedData(
|
||||||
|
scriptFile: KtFile,
|
||||||
|
compilationConfiguration: ScriptCompilationConfiguration,
|
||||||
|
project: Project,
|
||||||
|
contextClassLoader: ClassLoader?
|
||||||
|
): ScriptCollectedData {
|
||||||
|
val hostConfiguration =
|
||||||
|
compilationConfiguration[ScriptCompilationConfiguration.hostConfiguration] ?: defaultJvmScriptingHostConfiguration
|
||||||
|
val getScriptingClass = hostConfiguration[ScriptingHostConfiguration.getScriptingClass]
|
||||||
|
val jvmGetScriptingClass = (getScriptingClass as? JvmGetScriptingClass)
|
||||||
|
?: throw IllegalArgumentException("Expecting JvmGetScriptingClass in the hostConfiguration[getScriptingClass], got $getScriptingClass")
|
||||||
|
val acceptedAnnotations =
|
||||||
|
compilationConfiguration[ScriptCompilationConfiguration.refineConfigurationOnAnnotations]?.annotations?.mapNotNull {
|
||||||
|
jvmGetScriptingClass(it, contextClassLoader, hostConfiguration) as? KClass<Annotation> // TODO errors
|
||||||
|
}.orEmpty()
|
||||||
|
val annotations = scriptFile.annotationEntries.construct(contextClassLoader, acceptedAnnotations, project)
|
||||||
|
return ScriptCollectedData(
|
||||||
|
mapOf(
|
||||||
|
ScriptCollectedData.foundAnnotations to annotations
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Iterable<KtAnnotationEntry>.construct(
|
||||||
|
classLoader: ClassLoader?, acceptedAnnotations: List<KClass<out Annotation>>, project: Project
|
||||||
|
): List<Annotation> =
|
||||||
|
mapNotNull { psiAnn ->
|
||||||
|
// TODO: consider advanced matching using semantic similar to actual resolving
|
||||||
|
acceptedAnnotations.find { ann ->
|
||||||
|
psiAnn.typeName.let { it == ann.simpleName || it == ann.qualifiedName }
|
||||||
|
}?.let {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
(constructAnnotation(
|
||||||
|
psiAnn,
|
||||||
|
(classLoader ?: ClassLoader.getSystemClassLoader()).loadClass(it.qualifiedName).kotlin as KClass<out Annotation>,
|
||||||
|
project
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -43,7 +43,7 @@ class JvmCliScriptEvaluationExtension : ScriptEvaluationExtension {
|
|||||||
val scriptFile = File(sourcePath)
|
val scriptFile = File(sourcePath)
|
||||||
if (scriptFile.isDirectory || !scriptDefinitionProvider.isScript(scriptFile.name)) {
|
if (scriptFile.isDirectory || !scriptDefinitionProvider.isScript(scriptFile.name)) {
|
||||||
val extensionHint =
|
val extensionHint =
|
||||||
if (configuration.get(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS) == listOf(StandardScriptDefinition)) " (.kts)"
|
if (configuration.get(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS)?.let { it.size == 1 && it.first().isDefault } == true) " (.kts)"
|
||||||
else ""
|
else ""
|
||||||
messageCollector.report(ERROR, "Specify path to the script file$extensionHint as the first argument")
|
messageCollector.report(ERROR, "Specify path to the script file$extensionHint as the first argument")
|
||||||
return COMPILATION_ERROR
|
return COMPILATION_ERROR
|
||||||
|
|||||||
+26
-32
@@ -18,13 +18,14 @@ import org.jetbrains.kotlin.idea.KotlinFileType
|
|||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.definitions.CliScriptDefinitionProvider
|
import org.jetbrains.kotlin.scripting.compiler.plugin.definitions.CliScriptDefinitionProvider
|
||||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
import org.jetbrains.kotlin.scripting.configuration.configureScriptDefinitions
|
import org.jetbrains.kotlin.scripting.configuration.configureScriptDefinitions
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider
|
import org.jetbrains.kotlin.scripting.definitions.*
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource
|
|
||||||
import org.jetbrains.kotlin.scripting.definitions.StandardScriptDefinition
|
|
||||||
import org.jetbrains.kotlin.scripting.definitions.reporter
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
|
||||||
class ScriptingCompilerConfigurationExtension(val project: MockProject) : CompilerConfigurationExtension {
|
class ScriptingCompilerConfigurationExtension(
|
||||||
|
val project: MockProject,
|
||||||
|
val baseHostConfiguration: ScriptingHostConfiguration
|
||||||
|
) : CompilerConfigurationExtension {
|
||||||
|
|
||||||
override fun updateConfiguration(configuration: CompilerConfiguration) {
|
override fun updateConfiguration(configuration: CompilerConfiguration) {
|
||||||
|
|
||||||
@@ -39,7 +40,11 @@ class ScriptingCompilerConfigurationExtension(val project: MockProject) : Compil
|
|||||||
projectRoot
|
projectRoot
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val scriptResolverEnv = configuration.getMap(ScriptingConfigurationKeys.LEGACY_SCRIPT_RESOLVER_ENVIRONMENT_OPTION)
|
val hostConfiguration = ScriptingHostConfiguration(baseHostConfiguration) {
|
||||||
|
getEnvironment {
|
||||||
|
configuration.getMap(ScriptingConfigurationKeys.LEGACY_SCRIPT_RESOLVER_ENVIRONMENT_OPTION)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val explicitScriptDefinitions = configuration.getList(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS_CLASSES)
|
val explicitScriptDefinitions = configuration.getList(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS_CLASSES)
|
||||||
|
|
||||||
@@ -49,16 +54,16 @@ class ScriptingCompilerConfigurationExtension(val project: MockProject) : Compil
|
|||||||
configuration,
|
configuration,
|
||||||
this::class.java.classLoader,
|
this::class.java.classLoader,
|
||||||
messageCollector,
|
messageCollector,
|
||||||
scriptResolverEnv
|
hostConfiguration
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// If not disabled explicitly, we should always support at least the standard script definition
|
// If not disabled explicitly, we should always support at least the standard script definition
|
||||||
if (!configuration.getBoolean(JVMConfigurationKeys.DISABLE_STANDARD_SCRIPT_DEFINITION) &&
|
if (!configuration.getBoolean(JVMConfigurationKeys.DISABLE_STANDARD_SCRIPT_DEFINITION) &&
|
||||||
!configuration.getList(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS).contains(StandardScriptDefinition)
|
configuration.getList(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS).none { it.isDefault }
|
||||||
) {
|
) {
|
||||||
configuration.add(
|
configuration.add(
|
||||||
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS,
|
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS,
|
||||||
StandardScriptDefinition
|
ScriptDefinition.getDefault(hostConfiguration)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,37 +71,26 @@ class ScriptingCompilerConfigurationExtension(val project: MockProject) : Compil
|
|||||||
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS_SOURCES,
|
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS_SOURCES,
|
||||||
ScriptDefinitionsFromClasspathDiscoverySource(
|
ScriptDefinitionsFromClasspathDiscoverySource(
|
||||||
configuration.jvmClasspathRoots,
|
configuration.jvmClasspathRoots,
|
||||||
configuration.get(ScriptingConfigurationKeys.LEGACY_SCRIPT_RESOLVER_ENVIRONMENT_OPTION) ?: emptyMap(),
|
hostConfiguration,
|
||||||
messageCollector.reporter
|
messageCollector.reporter
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
// If not disabled explicitly, we should always support at least the standard script definition
|
val scriptDefinitionProvider = ScriptDefinitionProvider.getInstance(project) as? CliScriptDefinitionProvider
|
||||||
if (!configuration.getBoolean(JVMConfigurationKeys.DISABLE_STANDARD_SCRIPT_DEFINITION) &&
|
if (scriptDefinitionProvider != null) {
|
||||||
StandardScriptDefinition !in configuration.getList(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS)
|
scriptDefinitionProvider.setScriptDefinitionsSources(configuration.getList(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS_SOURCES))
|
||||||
) {
|
scriptDefinitionProvider.setScriptDefinitions(configuration.getList(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS))
|
||||||
configuration.add(
|
|
||||||
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS,
|
|
||||||
StandardScriptDefinition
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val scriptDefinitionProvider = ScriptDefinitionProvider.getInstance(project) as? CliScriptDefinitionProvider
|
// Register new file extensions
|
||||||
if (scriptDefinitionProvider != null) {
|
val fileTypeRegistry = FileTypeRegistry.getInstance() as CoreFileTypeRegistry
|
||||||
scriptDefinitionProvider.setScriptDefinitionsSources(configuration.getList(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS_SOURCES))
|
|
||||||
scriptDefinitionProvider.setScriptDefinitions(configuration.getList(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS))
|
|
||||||
|
|
||||||
// Register new file extensions
|
scriptDefinitionProvider.getKnownFilenameExtensions().filter {
|
||||||
val fileTypeRegistry = FileTypeRegistry.getInstance() as CoreFileTypeRegistry
|
fileTypeRegistry.getFileTypeByExtension(it) != KotlinFileType.INSTANCE
|
||||||
|
}.forEach {
|
||||||
scriptDefinitionProvider.getKnownFilenameExtensions().filter {
|
fileTypeRegistry.registerFileType(KotlinFileType.INSTANCE, it)
|
||||||
fileTypeRegistry.getFileTypeByExtension(it) != KotlinFileType.INSTANCE
|
}
|
||||||
}.forEach {
|
|
||||||
fileTypeRegistry.registerFileType(KotlinFileType.INSTANCE, it)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-14
@@ -5,33 +5,29 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.scripting.compiler.plugin.definitions
|
package org.jetbrains.kotlin.scripting.compiler.plugin.definitions
|
||||||
|
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
|
||||||
import org.jetbrains.kotlin.scripting.definitions.LazyScriptDefinitionProvider
|
import org.jetbrains.kotlin.scripting.definitions.LazyScriptDefinitionProvider
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsSource
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsSource
|
||||||
import org.jetbrains.kotlin.scripting.definitions.StandardScriptDefinition
|
|
||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
|
|
||||||
open class CliScriptDefinitionProvider : LazyScriptDefinitionProvider() {
|
open class CliScriptDefinitionProvider : LazyScriptDefinitionProvider() {
|
||||||
private val definitionsFromSources: MutableList<Sequence<KotlinScriptDefinition>> = arrayListOf()
|
private val definitionsFromSources: MutableList<Sequence<ScriptDefinition>> = arrayListOf()
|
||||||
private val definitions: MutableList<KotlinScriptDefinition> = arrayListOf()
|
private val definitions: MutableList<ScriptDefinition> = arrayListOf()
|
||||||
private var hasStandardDefinition = true
|
private var defaultDefinition: ScriptDefinition? = null
|
||||||
|
|
||||||
override val currentDefinitions: Sequence<KotlinScriptDefinition>
|
override val currentDefinitions: Sequence<ScriptDefinition>
|
||||||
get() {
|
get() {
|
||||||
val base = definitions.asSequence() + definitionsFromSources.asSequence().flatMap { it }
|
val base = definitions.asSequence() + definitionsFromSources.asSequence().flatMap { it }
|
||||||
return if (hasStandardDefinition) base + getDefaultScriptDefinition() else base
|
return base + getDefaultDefinition()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDefaultScriptDefinition(): KotlinScriptDefinition {
|
fun setScriptDefinitions(newDefinitions: List<ScriptDefinition>) {
|
||||||
return StandardScriptDefinition
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setScriptDefinitions(newDefinitions: List<KotlinScriptDefinition>) {
|
|
||||||
lock.write {
|
lock.write {
|
||||||
definitions.clear()
|
definitions.clear()
|
||||||
val (withoutStdDef, stdDef) = newDefinitions.partition { it != getDefaultScriptDefinition() }
|
val (withoutStdDef, stdDef) = newDefinitions.partition { !it.isDefault }
|
||||||
definitions.addAll(withoutStdDef)
|
definitions.addAll(withoutStdDef)
|
||||||
hasStandardDefinition = stdDef.isNotEmpty()
|
// TODO: consider reporting an error when several default definitions are supplied
|
||||||
|
defaultDefinition = stdDef.firstOrNull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,4 +39,6 @@ open class CliScriptDefinitionProvider : LazyScriptDefinitionProvider() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getDefaultDefinition(): ScriptDefinition = defaultDefinition ?: super.getDefaultDefinition()
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-16
@@ -11,44 +11,45 @@ import com.intellij.openapi.project.Project
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
||||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptContentLoader
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
|
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
|
||||||
import org.jetbrains.kotlin.scripting.resolve.adjustByDefinition
|
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.refineScriptCompilationConfiguration
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
import kotlin.concurrent.read
|
import kotlin.concurrent.read
|
||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
import kotlin.script.experimental.api.ResultWithDiagnostics
|
||||||
|
import kotlin.script.experimental.jvm.compat.mapToLegacyReports
|
||||||
|
|
||||||
class CliScriptDependenciesProvider(private val project: Project) : ScriptDependenciesProvider {
|
class CliScriptDependenciesProvider(private val project: Project) : ScriptDependenciesProvider {
|
||||||
private val cacheLock = ReentrantReadWriteLock()
|
private val cacheLock = ReentrantReadWriteLock()
|
||||||
private val cache = hashMapOf<String, ScriptDependencies?>()
|
private val cache = hashMapOf<String, ScriptCompilationConfigurationResult?>()
|
||||||
private val scriptContentLoader = ScriptContentLoader(project)
|
|
||||||
|
|
||||||
override fun getScriptDependencies(file: VirtualFile): ScriptDependencies? = cacheLock.read {
|
override fun getScriptConfigurationResult(file: VirtualFile): ScriptCompilationConfigurationResult? = cacheLock.read {
|
||||||
calculateExternalDependencies(file)
|
calculateRefinedConfiguration(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun calculateExternalDependencies(file: VirtualFile): ScriptDependencies? {
|
private fun calculateRefinedConfiguration(file: VirtualFile): ScriptCompilationConfigurationResult? {
|
||||||
val path = file.path
|
val path = file.path
|
||||||
val cached = cache[path]
|
val cached = cache[path]
|
||||||
return if (cached != null) cached
|
return if (cached != null) cached
|
||||||
else {
|
else {
|
||||||
val scriptDef = file.findScriptDefinition(project)
|
val scriptDef = file.findScriptDefinition(project)
|
||||||
if (scriptDef != null) {
|
if (scriptDef != null) {
|
||||||
val result = scriptContentLoader.loadContentsAndResolveDependencies(scriptDef, file)
|
val result = refineScriptCompilationConfiguration(VirtualFileScriptSource(file), scriptDef, project)
|
||||||
|
|
||||||
ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file, result.reports)
|
ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file, result.reports.mapToLegacyReports())
|
||||||
|
|
||||||
val deps = result.dependencies?.adjustByDefinition(scriptDef)
|
if (result is ResultWithDiagnostics.Success) {
|
||||||
|
log.info("[kts] new cached deps for $path: ${result.value.dependenciesClassPath.joinToString(File.pathSeparator)}")
|
||||||
if (deps != null) {
|
} else {
|
||||||
log.info("[kts] new cached deps for $path: ${deps.classpath.joinToString(File.pathSeparator)}")
|
log.info("[kts] new cached errors for $path:\n ${result.reports.joinToString("\n ") { it.message + if (it.exception == null) "" else ": ${it.exception}" }}")
|
||||||
}
|
}
|
||||||
cacheLock.write {
|
cacheLock.write {
|
||||||
cache.put(path, deps)
|
cache.put(path, result)
|
||||||
}
|
}
|
||||||
deps
|
result
|
||||||
} else null
|
} else null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
|
|||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.definitions.CliScriptDefinitionProvider
|
import org.jetbrains.kotlin.scripting.compiler.plugin.definitions.CliScriptDefinitionProvider
|
||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.definitions.CliScriptDependenciesProvider
|
import org.jetbrains.kotlin.scripting.compiler.plugin.definitions.CliScriptDependenciesProvider
|
||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.definitions.CliScriptReportSink
|
import org.jetbrains.kotlin.scripting.compiler.plugin.definitions.CliScriptReportSink
|
||||||
|
import org.jetbrains.kotlin.scripting.configuration.makeHostConfiguration
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
||||||
import org.jetbrains.kotlin.scripting.extensions.*
|
import org.jetbrains.kotlin.scripting.extensions.*
|
||||||
@@ -39,8 +40,9 @@ private fun <T> ProjectExtensionDescriptor<T>.registerExtensionIfRequired(projec
|
|||||||
class ScriptingCompilerConfigurationComponentRegistrar : ComponentRegistrar {
|
class ScriptingCompilerConfigurationComponentRegistrar : ComponentRegistrar {
|
||||||
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
|
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
|
||||||
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||||
|
val hostConfiguration = makeHostConfiguration(project, configuration)
|
||||||
withClassloadingProblemsReporting(messageCollector) {
|
withClassloadingProblemsReporting(messageCollector) {
|
||||||
CompilerConfigurationExtension.registerExtension(project, ScriptingCompilerConfigurationExtension(project))
|
CompilerConfigurationExtension.registerExtension(project, ScriptingCompilerConfigurationExtension(project, hostConfiguration))
|
||||||
CollectAdditionalSourcesExtension.registerExtension(project, ScriptingCollectAdditionalSourcesExtension(project))
|
CollectAdditionalSourcesExtension.registerExtension(project, ScriptingCollectAdditionalSourcesExtension(project))
|
||||||
ScriptEvaluationExtension.registerExtensionIfRequired(project, JvmCliScriptEvaluationExtension())
|
ScriptEvaluationExtension.registerExtensionIfRequired(project, JvmCliScriptEvaluationExtension())
|
||||||
ShellExtension.registerExtensionIfRequired(project, JvmCliReplShellExtension())
|
ShellExtension.registerExtensionIfRequired(project, JvmCliReplShellExtension())
|
||||||
|
|||||||
+11
-4
@@ -7,11 +7,13 @@ package org.jetbrains.kotlin.scripting.compiler.plugin
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.definitions.CliScriptDefinitionProvider
|
import org.jetbrains.kotlin.scripting.compiler.plugin.definitions.CliScriptDefinitionProvider
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsSource
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsSource
|
||||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
||||||
|
|
||||||
class ScriptProviderTest : KtUsefulTestCase() {
|
class ScriptProviderTest : KtUsefulTestCase() {
|
||||||
@@ -64,11 +66,16 @@ class ScriptProviderTest : KtUsefulTestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private open class FakeScriptDefinition(val suffix: String = ".kts") : KotlinScriptDefinition(ScriptTemplateWithArgs::class) {
|
private open class FakeScriptDefinition(val suffix: String = ".kts") :
|
||||||
|
ScriptDefinition.FromLegacy(defaultJvmScriptingHostConfiguration, KotlinScriptDefinition(ScriptTemplateWithArgs::class))
|
||||||
|
{
|
||||||
val matchCounter = AtomicInteger()
|
val matchCounter = AtomicInteger()
|
||||||
override fun isScript(fileName: String): Boolean = fileName.endsWith(suffix).also {
|
override fun isScript(fileName: String): Boolean = fileName.endsWith(suffix).also {
|
||||||
if (it) matchCounter.incrementAndGet()
|
if (it) matchCounter.incrementAndGet()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val isDefault: Boolean
|
||||||
|
get() = suffix == ".kts"
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestScriptDefinitionSource(val counter: AtomicInteger, val defGens: Iterable<() -> FakeScriptDefinition>) :
|
private class TestScriptDefinitionSource(val counter: AtomicInteger, val defGens: Iterable<() -> FakeScriptDefinition>) :
|
||||||
@@ -80,7 +87,7 @@ private class TestScriptDefinitionSource(val counter: AtomicInteger, val defGens
|
|||||||
)
|
)
|
||||||
} })
|
} })
|
||||||
|
|
||||||
override val definitions: Sequence<KotlinScriptDefinition> = sequence {
|
override val definitions: Sequence<ScriptDefinition> = sequence {
|
||||||
for (gen in defGens) {
|
for (gen in defGens) {
|
||||||
counter.incrementAndGet()
|
counter.incrementAndGet()
|
||||||
yield(gen())
|
yield(gen())
|
||||||
@@ -88,6 +95,6 @@ private class TestScriptDefinitionSource(val counter: AtomicInteger, val defGens
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestCliScriptDefinitionProvider(private val standardDef: KotlinScriptDefinition) : CliScriptDefinitionProvider() {
|
private class TestCliScriptDefinitionProvider(private val standardDef: ScriptDefinition) : CliScriptDefinitionProvider() {
|
||||||
override fun getDefaultScriptDefinition(): KotlinScriptDefinition = standardDef
|
override fun getDefaultScriptDefinition(): KotlinScriptDefinition = standardDef.legacyDefinition
|
||||||
}
|
}
|
||||||
+4
-3
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.utils.KotlinPaths
|
|||||||
import org.jetbrains.kotlin.utils.PathUtil
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
class ScriptingCompilerPluginTest : TestCaseWithTmpdir() {
|
class ScriptingCompilerPluginTest : TestCaseWithTmpdir() {
|
||||||
|
|
||||||
@@ -116,7 +117,7 @@ class ScriptingCompilerPluginTest : TestCaseWithTmpdir() {
|
|||||||
|
|
||||||
loadScriptTemplatesFromClasspath(
|
loadScriptTemplatesFromClasspath(
|
||||||
listOf("TestScriptWithReceivers", "TestScriptWithSimpleEnvVars"),
|
listOf("TestScriptWithReceivers", "TestScriptWithSimpleEnvVars"),
|
||||||
listOf(defsOut), emptyList(), this::class.java.classLoader, emptyMap(), messageCollector.reporter
|
listOf(defsOut), emptyList(), this::class.java.classLoader, defaultJvmScriptingHostConfiguration, messageCollector.reporter
|
||||||
).toList()
|
).toList()
|
||||||
|
|
||||||
for (def in defClasses) {
|
for (def in defClasses) {
|
||||||
@@ -141,7 +142,7 @@ class ScriptingCompilerPluginTest : TestCaseWithTmpdir() {
|
|||||||
discoverScriptTemplatesInClasspath(
|
discoverScriptTemplatesInClasspath(
|
||||||
listOf(defsOut),
|
listOf(defsOut),
|
||||||
this::class.java.classLoader,
|
this::class.java.classLoader,
|
||||||
emptyMap(),
|
defaultJvmScriptingHostConfiguration,
|
||||||
messageCollector.reporter
|
messageCollector.reporter
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -212,7 +213,7 @@ class ScriptingCompilerPluginTest : TestCaseWithTmpdir() {
|
|||||||
discoverScriptTemplatesInClasspath(
|
discoverScriptTemplatesInClasspath(
|
||||||
listOf(defsOut),
|
listOf(defsOut),
|
||||||
this::class.java.classLoader,
|
this::class.java.classLoader,
|
||||||
emptyMap(),
|
defaultJvmScriptingHostConfiguration,
|
||||||
messageCollector.reporter
|
messageCollector.reporter
|
||||||
).toList()
|
).toList()
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.daemon.common.*
|
|||||||
import org.jetbrains.kotlin.integration.KotlinIntegrationTestBase.getKotlinPaths
|
import org.jetbrains.kotlin.integration.KotlinIntegrationTestBase.getKotlinPaths
|
||||||
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
||||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.StandardScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.StandardScriptDefinition
|
||||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
@@ -46,6 +47,7 @@ import java.lang.management.ManagementFactory
|
|||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
|
||||||
class SourceSectionsTest : TestCaseWithTmpdir() {
|
class SourceSectionsTest : TestCaseWithTmpdir() {
|
||||||
|
|
||||||
@@ -73,7 +75,7 @@ class SourceSectionsTest : TestCaseWithTmpdir() {
|
|||||||
CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY,
|
CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY,
|
||||||
PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, false)
|
PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, false)
|
||||||
)
|
)
|
||||||
configuration.add(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, StandardScriptDefinition)
|
configuration.add(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, ScriptDefinition.getDefault(defaultJvmScriptingHostConfiguration))
|
||||||
if (withSourceSectionsPlugin) {
|
if (withSourceSectionsPlugin) {
|
||||||
configuration.addAll(SourceSectionsConfigurationKeys.SECTIONS_OPTION, TEST_ALLOWED_SECTIONS)
|
configuration.addAll(SourceSectionsConfigurationKeys.SECTIONS_OPTION, TEST_ALLOWED_SECTIONS)
|
||||||
configuration.add(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS, SourceSectionsComponentRegistrar())
|
configuration.add(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS, SourceSectionsComponentRegistrar())
|
||||||
|
|||||||
Reference in New Issue
Block a user