Refactor script definitions loading
Make ScriptDefinitionProvider an interface
and provide different implementation for cli and IDEA
Rework ide extension point to a simpler interface (ScriptDefinitionContributor)
Move template loading logic into a top level function
Allow script definitions to be reloaded in IDE
This commit is contained in:
+44
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.cli.common.script
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.script.ScriptDefinitionProvider
|
||||||
|
import org.jetbrains.kotlin.script.StandardScriptDefinition
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
|
import kotlin.concurrent.read
|
||||||
|
import kotlin.concurrent.write
|
||||||
|
|
||||||
|
class CliScriptDefinitionProvider : ScriptDefinitionProvider {
|
||||||
|
private val definitions: MutableList<KotlinScriptDefinition> = arrayListOf(StandardScriptDefinition)
|
||||||
|
private val lock = ReentrantReadWriteLock()
|
||||||
|
|
||||||
|
override fun findScriptDefinition(fileName: String) = lock.read {
|
||||||
|
definitions.firstOrNull { it.isScript(fileName) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isScript(fileName: String) = lock.read {
|
||||||
|
definitions.any { it.isScript(fileName) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setScriptDefinitions(newDefinitions: List<KotlinScriptDefinition>) {
|
||||||
|
lock.write {
|
||||||
|
definitions.clear()
|
||||||
|
definitions.addAll(newDefinitions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -19,9 +19,9 @@ package org.jetbrains.kotlin.cli.common.script
|
|||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
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.script.KotlinScriptDefinitionProvider
|
|
||||||
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
|
|
||||||
import org.jetbrains.kotlin.script.ScriptContentLoader
|
import org.jetbrains.kotlin.script.ScriptContentLoader
|
||||||
|
import org.jetbrains.kotlin.script.ScriptDefinitionProvider
|
||||||
|
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
|
||||||
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
|
||||||
@@ -30,7 +30,7 @@ import kotlin.script.experimental.dependencies.ScriptDependencies
|
|||||||
|
|
||||||
class CliScriptDependenciesProvider(
|
class CliScriptDependenciesProvider(
|
||||||
project: Project,
|
project: Project,
|
||||||
private val scriptDefinitionProvider: KotlinScriptDefinitionProvider
|
private val scriptDefinitionProvider: ScriptDefinitionProvider
|
||||||
) : ScriptDependenciesProvider {
|
) : ScriptDependenciesProvider {
|
||||||
|
|
||||||
private val cacheLock = ReentrantReadWriteLock()
|
private val cacheLock = ReentrantReadWriteLock()
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ import org.jetbrains.kotlin.javac.JavacWrapper
|
|||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider
|
import org.jetbrains.kotlin.script.ScriptDefinitionProvider
|
||||||
import org.jetbrains.kotlin.script.StandardScriptDefinition
|
import org.jetbrains.kotlin.script.StandardScriptDefinition
|
||||||
import org.jetbrains.kotlin.util.PerformanceCounter
|
import org.jetbrains.kotlin.util.PerformanceCounter
|
||||||
import org.jetbrains.kotlin.utils.KotlinPaths
|
import org.jetbrains.kotlin.utils.KotlinPaths
|
||||||
@@ -166,7 +166,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
val environment = createEnvironmentWithScriptingSupport(rootDisposable, configuration, arguments, messageCollector)
|
val environment = createEnvironmentWithScriptingSupport(rootDisposable, configuration, arguments, messageCollector)
|
||||||
?: return COMPILATION_ERROR
|
?: return COMPILATION_ERROR
|
||||||
|
|
||||||
val scriptDefinitionProvider = KotlinScriptDefinitionProvider.getInstance(environment.project)!!
|
val scriptDefinitionProvider = ScriptDefinitionProvider.getInstance(environment.project)!!
|
||||||
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 =
|
||||||
@@ -460,7 +460,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
for (template in scriptTemplates) {
|
for (template in scriptTemplates) {
|
||||||
try {
|
try {
|
||||||
val cls = classloader.loadClass(template)
|
val cls = classloader.loadClass(template)
|
||||||
val def = KotlinScriptDefinitionFromAnnotatedTemplate(cls.kotlin, null, null, scriptResolverEnv)
|
val def = KotlinScriptDefinitionFromAnnotatedTemplate(cls.kotlin, scriptResolverEnv)
|
||||||
configuration.add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, def)
|
configuration.add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, def)
|
||||||
messageCollector.report(
|
messageCollector.report(
|
||||||
INFO,
|
INFO,
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import com.intellij.ide.plugins.PluginManagerCore
|
|||||||
import com.intellij.lang.MetaLanguage
|
import com.intellij.lang.MetaLanguage
|
||||||
import com.intellij.lang.java.JavaParserDefinition
|
import com.intellij.lang.java.JavaParserDefinition
|
||||||
import com.intellij.openapi.Disposable
|
import com.intellij.openapi.Disposable
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
|
||||||
import com.intellij.openapi.application.TransactionGuard
|
import com.intellij.openapi.application.TransactionGuard
|
||||||
import com.intellij.openapi.application.TransactionGuardImpl
|
import com.intellij.openapi.application.TransactionGuardImpl
|
||||||
import com.intellij.openapi.components.ServiceManager
|
import com.intellij.openapi.components.ServiceManager
|
||||||
@@ -39,7 +38,6 @@ import com.intellij.openapi.fileTypes.FileTypeExtensionPoint
|
|||||||
import com.intellij.openapi.fileTypes.PlainTextFileType
|
import com.intellij.openapi.fileTypes.PlainTextFileType
|
||||||
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.io.FileUtil
|
|
||||||
import com.intellij.openapi.util.io.FileUtilRt
|
import com.intellij.openapi.util.io.FileUtilRt
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import com.intellij.openapi.vfs.*
|
import com.intellij.openapi.vfs.*
|
||||||
@@ -71,6 +69,7 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
|||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
|
import org.jetbrains.kotlin.cli.common.script.CliScriptDefinitionProvider
|
||||||
import org.jetbrains.kotlin.cli.common.script.CliScriptDependenciesProvider
|
import org.jetbrains.kotlin.cli.common.script.CliScriptDependenciesProvider
|
||||||
import org.jetbrains.kotlin.cli.common.script.CliScriptReportSink
|
import org.jetbrains.kotlin.cli.common.script.CliScriptReportSink
|
||||||
import org.jetbrains.kotlin.cli.common.toBooleanLenient
|
import org.jetbrains.kotlin.cli.common.toBooleanLenient
|
||||||
@@ -104,7 +103,7 @@ import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtens
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
|
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.CliDeclarationProviderFactoryService
|
import org.jetbrains.kotlin.resolve.lazy.declarations.CliDeclarationProviderFactoryService
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider
|
import org.jetbrains.kotlin.script.ScriptDefinitionProvider
|
||||||
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
|
||||||
import org.jetbrains.kotlin.script.ScriptReportSink
|
import org.jetbrains.kotlin.script.ScriptReportSink
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
@@ -191,7 +190,8 @@ class KotlinCoreEnvironment private constructor(
|
|||||||
})
|
})
|
||||||
sourceFiles.sortBy { it.virtualFile.path }
|
sourceFiles.sortBy { it.virtualFile.path }
|
||||||
|
|
||||||
KotlinScriptDefinitionProvider.getInstance(project)?.let { scriptDefinitionProvider ->
|
val scriptDefinitionProvider = ScriptDefinitionProvider.getInstance(project) as? CliScriptDefinitionProvider
|
||||||
|
if (scriptDefinitionProvider != null) {
|
||||||
scriptDefinitionProvider.setScriptDefinitions(
|
scriptDefinitionProvider.setScriptDefinitions(
|
||||||
configuration.getList(JVMConfigurationKeys.SCRIPT_DEFINITIONS))
|
configuration.getList(JVMConfigurationKeys.SCRIPT_DEFINITIONS))
|
||||||
|
|
||||||
@@ -554,9 +554,9 @@ class KotlinCoreEnvironment private constructor(
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun registerProjectServices(projectEnvironment: JavaCoreProjectEnvironment, messageCollector: MessageCollector?) {
|
fun registerProjectServices(projectEnvironment: JavaCoreProjectEnvironment, messageCollector: MessageCollector?) {
|
||||||
with (projectEnvironment.project) {
|
with (projectEnvironment.project) {
|
||||||
val kotlinScriptDefinitionProvider = KotlinScriptDefinitionProvider()
|
val scriptDefinitionProvider = CliScriptDefinitionProvider()
|
||||||
registerService(KotlinScriptDefinitionProvider::class.java, kotlinScriptDefinitionProvider)
|
registerService(ScriptDefinitionProvider::class.java, scriptDefinitionProvider)
|
||||||
registerService(ScriptDependenciesProvider::class.java, CliScriptDependenciesProvider(projectEnvironment.project, kotlinScriptDefinitionProvider))
|
registerService(ScriptDependenciesProvider::class.java, CliScriptDependenciesProvider(projectEnvironment.project, scriptDefinitionProvider))
|
||||||
registerService(KotlinJavaPsiFacade::class.java, KotlinJavaPsiFacade(this))
|
registerService(KotlinJavaPsiFacade::class.java, KotlinJavaPsiFacade(this))
|
||||||
registerService(KtLightClassForFacade.FacadeStubCache::class.java, KtLightClassForFacade.FacadeStubCache(this))
|
registerService(KtLightClassForFacade.FacadeStubCache::class.java, KtLightClassForFacade.FacadeStubCache(this))
|
||||||
if (messageCollector != null) {
|
if (messageCollector != null) {
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ open class KotlinJvmReplService(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
val cls = classloader.loadClass(templateClassName)
|
val cls = classloader.loadClass(templateClassName)
|
||||||
val def = KotlinScriptDefinitionFromAnnotatedTemplate(cls.kotlin, null, null, emptyMap())
|
val def = KotlinScriptDefinitionFromAnnotatedTemplate(cls.kotlin, emptyMap())
|
||||||
messageCollector.report(INFO, "New script definition $templateClassName: files pattern = \"${def.scriptFilePattern}\", " +
|
messageCollector.report(INFO, "New script definition $templateClassName: files pattern = \"${def.scriptFilePattern}\", " +
|
||||||
"resolver = ${def.dependencyResolver.javaClass.name}")
|
"resolver = ${def.dependencyResolver.javaClass.name}")
|
||||||
return def
|
return def
|
||||||
|
|||||||
+1
-5
@@ -35,21 +35,17 @@ import kotlin.script.templates.AcceptedAnnotations
|
|||||||
|
|
||||||
open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
||||||
template: KClass<out Any>,
|
template: KClass<out Any>,
|
||||||
providedResolver: DependenciesResolver? = null,
|
|
||||||
providedScriptFilePattern: String? = null,
|
|
||||||
val environment: Map<String, Any?>? = null,
|
val environment: Map<String, Any?>? = null,
|
||||||
val templateClasspath: List<File> = emptyList()
|
val templateClasspath: List<File> = emptyList()
|
||||||
) : KotlinScriptDefinition(template) {
|
) : KotlinScriptDefinition(template) {
|
||||||
|
|
||||||
val scriptFilePattern by lazy {
|
val scriptFilePattern by lazy {
|
||||||
providedScriptFilePattern
|
takeUnlessError { template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateDefinition>()?.scriptFilePattern }
|
||||||
?: takeUnlessError { template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateDefinition>()?.scriptFilePattern }
|
|
||||||
?: takeUnlessError { template.annotations.firstIsInstanceOrNull<org.jetbrains.kotlin.script.ScriptTemplateDefinition>()?.scriptFilePattern }
|
?: takeUnlessError { template.annotations.firstIsInstanceOrNull<org.jetbrains.kotlin.script.ScriptTemplateDefinition>()?.scriptFilePattern }
|
||||||
?: DEFAULT_SCRIPT_FILE_PATTERN
|
?: DEFAULT_SCRIPT_FILE_PATTERN
|
||||||
}
|
}
|
||||||
|
|
||||||
override val dependencyResolver: DependenciesResolver by lazy {
|
override val dependencyResolver: DependenciesResolver by lazy {
|
||||||
providedResolver ?:
|
|
||||||
resolverFromAnnotation(template) ?:
|
resolverFromAnnotation(template) ?:
|
||||||
resolverFromLegacyAnnotation(template) ?:
|
resolverFromLegacyAnnotation(template) ?:
|
||||||
DependenciesResolver.NoDependencies
|
DependenciesResolver.NoDependencies
|
||||||
|
|||||||
-95
@@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2017 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.script
|
|
||||||
|
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
|
||||||
import com.intellij.openapi.extensions.ExtensionPointName
|
|
||||||
import com.intellij.openapi.extensions.Extensions
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import java.io.File
|
|
||||||
import java.net.URLClassLoader
|
|
||||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
|
||||||
|
|
||||||
interface ScriptTemplatesProvider {
|
|
||||||
|
|
||||||
// for resolving ambiguities
|
|
||||||
val id: String
|
|
||||||
|
|
||||||
@Deprecated("Parameter isn't used for resolving priorities anymore. " +
|
|
||||||
"com.intellij.openapi.extensions.LoadingOrder constants can be used to order providers when registered from Intellij plugin.",
|
|
||||||
ReplaceWith("0"))
|
|
||||||
val version: Int get() = 0
|
|
||||||
|
|
||||||
val isValid: Boolean
|
|
||||||
|
|
||||||
val templateClassNames: Iterable<String>
|
|
||||||
|
|
||||||
val resolver: DependenciesResolver? get() = null
|
|
||||||
|
|
||||||
val filePattern: String? get() = null
|
|
||||||
|
|
||||||
val templateClasspath: List<File>
|
|
||||||
|
|
||||||
// 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).
|
|
||||||
* Script template dependencies naturally become (part of) dependencies of the script which is not always desired for resolver dependencies.
|
|
||||||
* i.e. gradle resolver may depend on some jars that 'built.gradle.kts' files should not depend on.
|
|
||||||
*/
|
|
||||||
val additionalResolverClasspath: List<File> get() = emptyList()
|
|
||||||
|
|
||||||
val environment: Map<String, Any?>?
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val EP_NAME: ExtensionPointName<ScriptTemplatesProvider> =
|
|
||||||
ExtensionPointName.create<ScriptTemplatesProvider>("org.jetbrains.kotlin.scriptTemplatesProvider")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun makeScriptDefsFromTemplatesProviderExtensions(project: Project,
|
|
||||||
errorsHandler: ((ScriptTemplatesProvider, Throwable) -> Unit)
|
|
||||||
): List<KotlinScriptDefinition> =
|
|
||||||
makeScriptDefsFromTemplatesProviders(Extensions.getArea(project).getExtensionPoint(ScriptTemplatesProvider.EP_NAME).extensions.asIterable(),
|
|
||||||
errorsHandler)
|
|
||||||
|
|
||||||
fun makeScriptDefsFromTemplatesProviders(providers: Iterable<ScriptTemplatesProvider>,
|
|
||||||
errorsHandler: ((ScriptTemplatesProvider, Throwable) -> Unit) = { _, ex -> throw ex }
|
|
||||||
): List<KotlinScriptDefinition> = providers.flatMap { provider ->
|
|
||||||
try {
|
|
||||||
val loader = createClassLoader(provider)
|
|
||||||
provider.templateClassNames.map {
|
|
||||||
KotlinScriptDefinitionFromAnnotatedTemplate(
|
|
||||||
loader.loadClass(it).kotlin, provider.resolver,
|
|
||||||
provider.filePattern, provider.environment, provider.templateClasspath
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (ex: Throwable) {
|
|
||||||
LOG.info("Templates provider ${provider.id} is invalid: ${ex.message}")
|
|
||||||
errorsHandler(provider, ex)
|
|
||||||
emptyList<KotlinScriptDefinition>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createClassLoader(provider: ScriptTemplatesProvider): ClassLoader {
|
|
||||||
val classpath = provider.templateClasspath + provider.additionalResolverClasspath
|
|
||||||
LOG.info("[kts] loading script definitions ${provider.templateClassNames} using cp: ${classpath.joinToString(File.pathSeparator)}")
|
|
||||||
val baseLoader = ScriptTemplatesProvider::class.java.classLoader
|
|
||||||
return if (classpath.isEmpty()) baseLoader else URLClassLoader(classpath.map { it.toURI().toURL() }.toTypedArray(), baseLoader)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val LOG = Logger.getInstance("ScriptTemplatesProviders")
|
|
||||||
@@ -23,14 +23,14 @@ import com.intellij.openapi.project.Project;
|
|||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider;
|
import org.jetbrains.kotlin.script.ScriptDefinitionProvider;
|
||||||
|
|
||||||
public class KotlinParser implements PsiParser {
|
public class KotlinParser implements PsiParser {
|
||||||
|
|
||||||
private final KotlinScriptDefinitionProvider scriptDefinitionProvider;
|
private final ScriptDefinitionProvider scriptDefinitionProvider;
|
||||||
|
|
||||||
public KotlinParser(Project project) {
|
public KotlinParser(Project project) {
|
||||||
scriptDefinitionProvider = KotlinScriptDefinitionProvider.getInstance(project);
|
scriptDefinitionProvider = ScriptDefinitionProvider.Companion.getInstance(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+7
-51
@@ -17,67 +17,23 @@
|
|||||||
package org.jetbrains.kotlin.script
|
package org.jetbrains.kotlin.script
|
||||||
|
|
||||||
import com.intellij.openapi.components.ServiceManager
|
import com.intellij.openapi.components.ServiceManager
|
||||||
import com.intellij.openapi.fileTypes.LanguageFileType
|
|
||||||
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 kotlin.concurrent.read
|
|
||||||
import kotlin.concurrent.write
|
|
||||||
|
|
||||||
class KotlinScriptDefinitionProvider {
|
|
||||||
|
|
||||||
private val definitions: MutableList<KotlinScriptDefinition> = arrayListOf(StandardScriptDefinition)
|
|
||||||
private val definitionsLock = java.util.concurrent.locks.ReentrantReadWriteLock()
|
|
||||||
|
|
||||||
fun setScriptDefinitions(newDefinitions: List<KotlinScriptDefinition>): Boolean {
|
|
||||||
var changed = false
|
|
||||||
definitionsLock.read {
|
|
||||||
if (newDefinitions != definitions) {
|
|
||||||
definitionsLock.write {
|
|
||||||
definitions.clear()
|
|
||||||
definitions.addAll(newDefinitions)
|
|
||||||
}
|
|
||||||
changed = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return changed
|
|
||||||
}
|
|
||||||
|
|
||||||
|
interface ScriptDefinitionProvider {
|
||||||
|
fun findScriptDefinition(fileName: String): KotlinScriptDefinition?
|
||||||
|
fun isScript(fileName: String): Boolean
|
||||||
fun findScriptDefinition(file: VirtualFile): KotlinScriptDefinition? = findScriptDefinition(file.name)
|
fun findScriptDefinition(file: VirtualFile): KotlinScriptDefinition? = findScriptDefinition(file.name)
|
||||||
|
|
||||||
fun findScriptDefinition(fileName: String): KotlinScriptDefinition? = definitionsLock.read {
|
|
||||||
definitions.firstOrNull { it.isScript(fileName) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isScript(fileName: String): Boolean = definitionsLock.read {
|
|
||||||
definitions.any { it.isScript(fileName) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addScriptDefinition(scriptDefinition: KotlinScriptDefinition) {
|
|
||||||
definitionsLock.write {
|
|
||||||
definitions.add(0, scriptDefinition)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeScriptDefinition(scriptDefinition: KotlinScriptDefinition) {
|
|
||||||
definitionsLock.write {
|
|
||||||
definitions.remove(scriptDefinition)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getAllKnownFileTypes(): Iterable<LanguageFileType> = definitionsLock.read {
|
|
||||||
definitions.map { it.fileType }.distinct()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
fun getInstance(project: Project): ScriptDefinitionProvider =
|
||||||
fun getInstance(project: Project): KotlinScriptDefinitionProvider? =
|
ServiceManager.getService(project, ScriptDefinitionProvider::class.java)
|
||||||
ServiceManager.getService(project, KotlinScriptDefinitionProvider::class.java)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getScriptDefinition(file: VirtualFile, project: Project): KotlinScriptDefinition? =
|
fun getScriptDefinition(file: VirtualFile, project: Project): KotlinScriptDefinition? =
|
||||||
KotlinScriptDefinitionProvider.getInstance(project)?.findScriptDefinition(file)
|
ScriptDefinitionProvider.getInstance(project).findScriptDefinition(file)
|
||||||
|
|
||||||
fun getScriptDefinition(psiFile: PsiFile): KotlinScriptDefinition? =
|
fun getScriptDefinition(psiFile: PsiFile): KotlinScriptDefinition? =
|
||||||
KotlinScriptDefinitionProvider.getInstance(psiFile.project)?.findScriptDefinition(psiFile.name)
|
ScriptDefinitionProvider.getInstance(psiFile.project).findScriptDefinition(psiFile.name)
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.kotlin.checkers.CheckerTestUtil;
|
import org.jetbrains.kotlin.checkers.CheckerTestUtil;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.resolve.AnalyzingUtils;
|
import org.jetbrains.kotlin.resolve.AnalyzingUtils;
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider;
|
|
||||||
import org.jetbrains.kotlin.script.StandardScriptDefinition;
|
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -133,10 +131,6 @@ public class CodegenTestFiles {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KotlinScriptDefinitionProvider scriptDefinitionProvider = KotlinScriptDefinitionProvider.getInstance(project);
|
|
||||||
assert scriptDefinitionProvider != null;
|
|
||||||
scriptDefinitionProvider.addScriptDefinition(StandardScriptDefinition.INSTANCE);
|
|
||||||
|
|
||||||
return new CodegenTestFiles(Collections.singletonList(file), expectedValues, scriptParameterValues);
|
return new CodegenTestFiles(Collections.singletonList(file), expectedValues, scriptParameterValues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ internal class TestRepl(
|
|||||||
private fun makeScriptDefinition(templateClasspath: List<File>, templateClassName: String): KotlinScriptDefinition {
|
private fun makeScriptDefinition(templateClasspath: List<File>, templateClassName: String): KotlinScriptDefinition {
|
||||||
val classloader = URLClassLoader(templateClasspath.map { it.toURI().toURL() }.toTypedArray(), this::class.java.classLoader)
|
val classloader = URLClassLoader(templateClasspath.map { it.toURI().toURL() }.toTypedArray(), this::class.java.classLoader)
|
||||||
val cls = classloader.loadClass(templateClassName)
|
val cls = classloader.loadClass(templateClassName)
|
||||||
return KotlinScriptDefinitionFromAnnotatedTemplate(cls.kotlin, null, null, emptyMap())
|
return KotlinScriptDefinitionFromAnnotatedTemplate(cls.kotlin, emptyMap())
|
||||||
}
|
}
|
||||||
|
|
||||||
private val scriptDef = makeScriptDefinition(templateClasspath, templateClassName)
|
private val scriptDef = makeScriptDefinition(templateClasspath, templateClassName)
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
||||||
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
|
||||||
@@ -26,16 +25,18 @@ import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
|
|||||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.addKotlinSourceRoots
|
import org.jetbrains.kotlin.config.addKotlinSourceRoots
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
import org.jetbrains.kotlin.scripts.ScriptWithIntParam
|
import org.jetbrains.kotlin.scripts.TestKotlinScriptDependenciesResolver
|
||||||
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.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.script.templates.ScriptTemplateDefinition
|
||||||
|
|
||||||
class ScriptGenTest : CodegenTestCase() {
|
class ScriptGenTest : CodegenTestCase() {
|
||||||
companion object {
|
companion object {
|
||||||
private val FIB_SCRIPT_DEFINITION = KotlinScriptDefinitionFromAnnotatedTemplate(ScriptWithIntParam::class, providedScriptFilePattern = ".*\\.lang\\.kt")
|
private val FIB_SCRIPT_DEFINITION = KotlinScriptDefinitionFromAnnotatedTemplate(ScriptWithIntParam::class)
|
||||||
private val NO_PARAM_SCRIPT_DEFINITION = KotlinScriptDefinitionFromAnnotatedTemplate(Any::class, providedScriptFilePattern = ".*\\.kts")
|
private val NO_PARAM_SCRIPT_DEFINITION = KotlinScriptDefinitionFromAnnotatedTemplate(Any::class)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
@@ -124,3 +125,8 @@ class ScriptGenTest : CodegenTestCase() {
|
|||||||
loadFiles(*sourcePaths.toTypedArray())
|
loadFiles(*sourcePaths.toTypedArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ScriptTemplateDefinition(
|
||||||
|
scriptFilePattern =".*\\.lang\\.kt",
|
||||||
|
resolver = TestKotlinScriptDependenciesResolver::class)
|
||||||
|
abstract class ScriptWithIntParam(val num: Int)
|
||||||
@@ -28,8 +28,9 @@ import com.intellij.psi.util.PsiTreeUtil;
|
|||||||
import com.intellij.util.PathUtil;
|
import com.intellij.util.PathUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.KtNodeTypes;
|
import org.jetbrains.kotlin.KtNodeTypes;
|
||||||
|
import org.jetbrains.kotlin.cli.common.script.CliScriptDefinitionProvider;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider;
|
import org.jetbrains.kotlin.script.ScriptDefinitionProvider;
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
import org.jetbrains.kotlin.test.testFramework.KtParsingTestCase;
|
import org.jetbrains.kotlin.test.testFramework.KtParsingTestCase;
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ public abstract class AbstractParsingTest extends KtParsingTestCase {
|
|||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
getProject().registerService(KotlinScriptDefinitionProvider.class);
|
getProject().registerService(ScriptDefinitionProvider.class, CliScriptDefinitionProvider.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ class ScriptTemplateTest : KtUsefulTestCase() {
|
|||||||
includeKotlinRuntime: Boolean = true
|
includeKotlinRuntime: Boolean = true
|
||||||
): Class<*>? =
|
): Class<*>? =
|
||||||
compileScriptImpl("compiler/testData/script/" + scriptPath, KotlinScriptDefinitionFromAnnotatedTemplate(
|
compileScriptImpl("compiler/testData/script/" + scriptPath, KotlinScriptDefinitionFromAnnotatedTemplate(
|
||||||
scriptTemplate, null, null, environment
|
scriptTemplate, environment
|
||||||
), runIsolated, messageCollector, includeKotlinRuntime)
|
), runIsolated, messageCollector, includeKotlinRuntime)
|
||||||
|
|
||||||
private fun compileScriptImpl(
|
private fun compileScriptImpl(
|
||||||
|
|||||||
@@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.core.script
|
||||||
|
|
||||||
|
import com.intellij.openapi.components.service
|
||||||
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
|
import com.intellij.openapi.extensions.ExtensionPointName
|
||||||
|
import com.intellij.openapi.extensions.Extensions
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.projectRoots.JavaSdk
|
||||||
|
import com.intellij.openapi.projectRoots.ProjectJdkTable
|
||||||
|
import com.intellij.openapi.projectRoots.ex.PathUtilEx
|
||||||
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
|
import org.jetbrains.kotlin.script.ScriptDefinitionProvider
|
||||||
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.flattenTo
|
||||||
|
import java.io.File
|
||||||
|
import java.net.URLClassLoader
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
|
import kotlin.concurrent.read
|
||||||
|
import kotlin.concurrent.write
|
||||||
|
import kotlin.script.dependencies.Environment
|
||||||
|
import kotlin.script.dependencies.ScriptContents
|
||||||
|
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||||
|
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||||
|
import kotlin.script.experimental.dependencies.asSuccess
|
||||||
|
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
||||||
|
|
||||||
|
class ScriptDefinitionsManager(private val project: Project): ScriptDefinitionProvider {
|
||||||
|
private val lock = ReentrantReadWriteLock()
|
||||||
|
private var definitionsByContributor = mutableMapOf<ScriptDefinitionContributor, List<KotlinScriptDefinition>>()
|
||||||
|
private var definitions: List<KotlinScriptDefinition> = emptyList()
|
||||||
|
|
||||||
|
fun reloadDefinitionsBy(contributor: ScriptDefinitionContributor) = lock.write {
|
||||||
|
currentDefinitions() //force definitions to be computed
|
||||||
|
|
||||||
|
if (contributor !in definitionsByContributor) error("Unknown contributor: ${contributor.id}")
|
||||||
|
|
||||||
|
definitionsByContributor[contributor] = contributor.safeGetDefinitions()
|
||||||
|
updateDefinitions()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun currentDefinitions(): List<KotlinScriptDefinition> {
|
||||||
|
val hasDefinitions = definitions.isNotEmpty()
|
||||||
|
when {
|
||||||
|
hasDefinitions -> return definitions
|
||||||
|
else -> {
|
||||||
|
reloadScriptDefinitions()
|
||||||
|
return definitions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findScriptDefinition(fileName: String): KotlinScriptDefinition? = lock.read {
|
||||||
|
currentDefinitions().firstOrNull { it.isScript(fileName) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isScript(fileName: String) = lock.read {
|
||||||
|
currentDefinitions().any { it.isScript(fileName) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getContributors(): List<ScriptDefinitionContributor> =
|
||||||
|
Extensions.getArea(project).getExtensionPoint(ScriptDefinitionContributor.EP_NAME).extensions.toList()
|
||||||
|
|
||||||
|
fun reloadScriptDefinitions() = lock.write {
|
||||||
|
definitionsByContributor = getContributors().associateByTo(mutableMapOf(), { it }, { it.safeGetDefinitions() })
|
||||||
|
updateDefinitions()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateDefinitions() {
|
||||||
|
definitions = definitionsByContributor.values.flattenTo(mutableListOf())
|
||||||
|
// TODO: clear by script type/definition
|
||||||
|
project.service<ScriptDependenciesUpdater>().clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ScriptDefinitionContributor.safeGetDefinitions(): List<KotlinScriptDefinition> {
|
||||||
|
return try {
|
||||||
|
getDefinitions()
|
||||||
|
}
|
||||||
|
catch (t: Throwable) {
|
||||||
|
// TODO: review exception handling
|
||||||
|
// possibly log, see KT-19276
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getInstance(project: Project): ScriptDefinitionsManager = project.service<ScriptDefinitionProvider>() as ScriptDefinitionsManager
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val LOG = Logger.getInstance("ScriptTemplatesProviders")
|
||||||
|
|
||||||
|
fun loadDefinitionsFromTemplates(
|
||||||
|
templateClassNames: List<String>,
|
||||||
|
templateClasspath: List<File>,
|
||||||
|
environment: Environment = emptyMap(),
|
||||||
|
// 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).
|
||||||
|
* Script template dependencies naturally become (part of) dependencies of the script which is not always desired for resolver dependencies.
|
||||||
|
* i.e. gradle resolver may depend on some jars that 'built.gradle.kts' files should not depend on.
|
||||||
|
*/
|
||||||
|
additionalResolverClasspath: List<File> = emptyList()
|
||||||
|
): List<KotlinScriptDefinitionFromAnnotatedTemplate> = try {
|
||||||
|
val classpath = templateClasspath + additionalResolverClasspath
|
||||||
|
LOG.info("[kts] loading script definitions $templateClassNames using cp: ${classpath.joinToString(File.pathSeparator)}")
|
||||||
|
val baseLoader = ScriptDefinitionContributor::class.java.classLoader
|
||||||
|
val loader = if (classpath.isEmpty()) baseLoader else URLClassLoader(classpath.map { it.toURI().toURL() }.toTypedArray(), baseLoader)
|
||||||
|
|
||||||
|
templateClassNames.map {
|
||||||
|
KotlinScriptDefinitionFromAnnotatedTemplate(
|
||||||
|
loader.loadClass(it).kotlin,
|
||||||
|
environment,
|
||||||
|
templateClasspath
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ex: Throwable) {
|
||||||
|
// TODO: review exception handling
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ScriptDefinitionContributor {
|
||||||
|
val id: String
|
||||||
|
|
||||||
|
fun getDefinitions(): List<KotlinScriptDefinition>
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val EP_NAME: ExtensionPointName<ScriptDefinitionContributor> =
|
||||||
|
ExtensionPointName.create<ScriptDefinitionContributor>("org.jetbrains.kotlin.scriptDefinitionContributor")
|
||||||
|
|
||||||
|
inline fun <reified T> find(project: Project) =
|
||||||
|
Extensions.getArea(project).getExtensionPoint(ScriptDefinitionContributor.EP_NAME).extensions.filterIsInstance<T>().firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class StandardScriptDefinitionContributor(private val project: Project) : ScriptDefinitionContributor {
|
||||||
|
override fun getDefinitions() = listOf(StandardIdeScriptDefinition(project))
|
||||||
|
|
||||||
|
override val id: String = "StandardKotlinScript"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class StandardIdeScriptDefinition(project: Project) : KotlinScriptDefinition(ScriptTemplateWithArgs::class) {
|
||||||
|
override val dependencyResolver = BundledKotlinScriptDependenciesResolver(project)
|
||||||
|
}
|
||||||
|
|
||||||
|
class BundledKotlinScriptDependenciesResolver(private val project: Project) : DependenciesResolver {
|
||||||
|
override fun resolve(
|
||||||
|
scriptContents: ScriptContents,
|
||||||
|
environment: Environment
|
||||||
|
): DependenciesResolver.ResolveResult {
|
||||||
|
val javaHome = getScriptSDK(project)
|
||||||
|
val dependencies = ScriptDependencies(
|
||||||
|
javaHome = javaHome?.let(::File),
|
||||||
|
classpath = with(PathUtil.kotlinPathsForIdeaPlugin) {
|
||||||
|
listOf(
|
||||||
|
reflectPath,
|
||||||
|
stdlibPath,
|
||||||
|
scriptRuntimePath
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return dependencies.asSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getScriptSDK(project: Project): String? {
|
||||||
|
val jdk = ProjectJdkTable.getInstance().allJdks.firstOrNull { sdk -> sdk.sdkType is JavaSdk } ?: PathUtilEx.getAnyJdk(project)
|
||||||
|
return jdk?.homePath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+17
-16
@@ -17,7 +17,6 @@
|
|||||||
package org.jetbrains.kotlin.idea.core.script
|
package org.jetbrains.kotlin.idea.core.script
|
||||||
|
|
||||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
|
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
|
||||||
import com.intellij.openapi.extensions.Extensions
|
import com.intellij.openapi.extensions.Extensions
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
@@ -27,6 +26,7 @@ import com.intellij.psi.search.NonClasspathDirectoriesScope
|
|||||||
import com.intellij.util.containers.SLRUMap
|
import com.intellij.util.containers.SLRUMap
|
||||||
import kotlinx.coroutines.experimental.launch
|
import kotlinx.coroutines.experimental.launch
|
||||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
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
|
||||||
@@ -37,11 +37,11 @@ import kotlin.reflect.KProperty0
|
|||||||
import kotlin.reflect.jvm.isAccessible
|
import kotlin.reflect.jvm.isAccessible
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||||
|
|
||||||
private const val MAX_SCRIPTS_CACHED = 15
|
private const val MAX_SCRIPTS_CACHED = 10
|
||||||
|
|
||||||
class ScriptDependenciesCache(private val project: Project) {
|
class ScriptDependenciesCache(private val project: Project) {
|
||||||
private val cacheLock = ReentrantReadWriteLock()
|
private val cacheLock = ReentrantReadWriteLock()
|
||||||
private val cache = SLRUMap<VirtualFile, ScriptDependencies>(0, MAX_SCRIPTS_CACHED)
|
private val cache = SLRUMap<VirtualFile, ScriptDependencies>(MAX_SCRIPTS_CACHED, MAX_SCRIPTS_CACHED)
|
||||||
|
|
||||||
operator fun get(virtualFile: VirtualFile): ScriptDependencies? = cacheLock.read { cache[virtualFile] }
|
operator fun get(virtualFile: VirtualFile): ScriptDependencies? = cacheLock.read { cache[virtualFile] }
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ class ScriptDependenciesCache(private val project: Project) {
|
|||||||
NonClasspathDirectoriesScope(allLibrarySources)
|
NonClasspathDirectoriesScope(allLibrarySources)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onChange(file: VirtualFile?) {
|
private fun onChange(files: List<VirtualFile>) {
|
||||||
this::allScriptsClasspath.clearValue()
|
this::allScriptsClasspath.clearValue()
|
||||||
this::allScriptsClasspathScope.clearValue()
|
this::allScriptsClasspathScope.clearValue()
|
||||||
this::allLibrarySources.clearValue()
|
this::allLibrarySources.clearValue()
|
||||||
@@ -74,22 +74,18 @@ class ScriptDependenciesCache(private val project: Project) {
|
|||||||
.single()
|
.single()
|
||||||
|
|
||||||
kotlinScriptDependenciesClassFinder.clearCache()
|
kotlinScriptDependenciesClassFinder.clearCache()
|
||||||
updateHighlighting(file)
|
updateHighlighting(files)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateHighlighting(file: VirtualFile?) {
|
private fun updateHighlighting(files: List<VirtualFile>) {
|
||||||
ScriptDependenciesModificationTracker.getInstance(project).incModificationCount()
|
ScriptDependenciesModificationTracker.getInstance(project).incModificationCount()
|
||||||
|
|
||||||
launch(EDT(project)) {
|
launch(EDT(project)) {
|
||||||
if (file != null) {
|
files.forEach {
|
||||||
file.let { PsiManager.getInstance(project).findFile(it) }?.let { psiFile ->
|
PsiManager.getInstance(project).findFile(it)?.let { psiFile ->
|
||||||
DaemonCodeAnalyzer.getInstance(project).restart(psiFile)
|
DaemonCodeAnalyzer.getInstance(project).restart(psiFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
assert(ApplicationManager.getApplication().isUnitTestMode)
|
|
||||||
DaemonCodeAnalyzer.getInstance(project).restart()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,8 +95,13 @@ class ScriptDependenciesCache(private val project: Project) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
cacheLock.write(cache::clear)
|
val keys = cacheLock.read {
|
||||||
onChange(null)
|
val keys = mutableListOf<VirtualFile>()
|
||||||
|
cache.iterateKeys { keys.addIfNotNull(it) }
|
||||||
|
cacheLock.write(cache::clear)
|
||||||
|
keys
|
||||||
|
}
|
||||||
|
onChange(keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun save(virtualFile: VirtualFile, new: ScriptDependencies): Boolean {
|
fun save(virtualFile: VirtualFile, new: ScriptDependencies): Boolean {
|
||||||
@@ -111,7 +112,7 @@ class ScriptDependenciesCache(private val project: Project) {
|
|||||||
}
|
}
|
||||||
val changed = new != old
|
val changed = new != old
|
||||||
if (changed) {
|
if (changed) {
|
||||||
onChange(virtualFile)
|
onChange(listOf(virtualFile))
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed
|
return changed
|
||||||
@@ -122,7 +123,7 @@ class ScriptDependenciesCache(private val project: Project) {
|
|||||||
cache.remove(virtualFile) != null
|
cache.remove(virtualFile) != null
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
onChange(virtualFile)
|
onChange(listOf(virtualFile))
|
||||||
}
|
}
|
||||||
return changed
|
return changed
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-24
@@ -23,9 +23,8 @@ import com.intellij.openapi.vfs.StandardFileSystems
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.util.io.URLUtil
|
import com.intellij.util.io.URLUtil
|
||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider
|
import org.jetbrains.kotlin.script.ScriptDefinitionProvider
|
||||||
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
|
||||||
import org.jetbrains.kotlin.script.makeScriptDefsFromTemplatesProviderExtensions
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||||
|
|
||||||
@@ -41,25 +40,12 @@ class IdeScriptDependenciesProvider(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ScriptDependenciesManager internal constructor(
|
class ScriptDependenciesManager internal constructor(
|
||||||
private val project: Project,
|
|
||||||
private val scriptDefinitionProvider: KotlinScriptDefinitionProvider,
|
|
||||||
private val cacheUpdater: ScriptDependenciesUpdater,
|
private val cacheUpdater: ScriptDependenciesUpdater,
|
||||||
private val cache: ScriptDependenciesCache
|
private val cache: ScriptDependenciesCache
|
||||||
) {
|
) {
|
||||||
init {
|
|
||||||
reloadScriptDefinitions()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getScriptClasspath(file: VirtualFile): List<VirtualFile> = toVfsRoots(cacheUpdater.getCurrentDependencies(file).classpath)
|
fun getScriptClasspath(file: VirtualFile): List<VirtualFile> = toVfsRoots(cacheUpdater.getCurrentDependencies(file).classpath)
|
||||||
fun getScriptDependencies(file: VirtualFile): ScriptDependencies = cacheUpdater.getCurrentDependencies(file)
|
fun getScriptDependencies(file: VirtualFile): ScriptDependencies = cacheUpdater.getCurrentDependencies(file)
|
||||||
|
|
||||||
private fun reloadScriptDefinitions() {
|
|
||||||
val def = makeScriptDefsFromTemplatesProviderExtensions(
|
|
||||||
project, { ep, ex -> /* do nothing, logging these exception creates too much noise*/}
|
|
||||||
)
|
|
||||||
scriptDefinitionProvider.setScriptDefinitions(def)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getAllScriptsClasspathScope() = cache.allScriptsClasspathScope
|
fun getAllScriptsClasspathScope() = cache.allScriptsClasspathScope
|
||||||
fun getAllLibrarySourcesScope() = cache.allLibrarySourcesScope
|
fun getAllLibrarySourcesScope() = cache.allLibrarySourcesScope
|
||||||
fun getAllLibrarySources() = cache.allLibrarySources
|
fun getAllLibrarySources() = cache.allLibrarySources
|
||||||
@@ -90,18 +76,10 @@ class ScriptDependenciesManager internal constructor(
|
|||||||
@TestOnly
|
@TestOnly
|
||||||
fun updateScriptDependenciesSynchronously(virtualFile: VirtualFile, project: Project) {
|
fun updateScriptDependenciesSynchronously(virtualFile: VirtualFile, project: Project) {
|
||||||
with(getInstance(project)) {
|
with(getInstance(project)) {
|
||||||
val scriptDefinition = KotlinScriptDefinitionProvider.getInstance(project)!!.findScriptDefinition(virtualFile)!!
|
val scriptDefinition = ScriptDefinitionProvider.getInstance(project).findScriptDefinition(virtualFile)!!
|
||||||
cacheUpdater.updateSync(virtualFile, scriptDefinition)
|
cacheUpdater.updateSync(virtualFile, scriptDefinition)
|
||||||
cacheUpdater.notifyRootsChanged()
|
cacheUpdater.notifyRootsChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestOnly
|
|
||||||
fun reloadScriptDefinitions(project: Project) {
|
|
||||||
with(getInstance(project)) {
|
|
||||||
reloadScriptDefinitions()
|
|
||||||
cacheUpdater.clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -47,10 +47,10 @@ import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
|
|||||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||||
|
|
||||||
internal class ScriptDependenciesUpdater(
|
class ScriptDependenciesUpdater(
|
||||||
private val project: Project,
|
private val project: Project,
|
||||||
private val cache: ScriptDependenciesCache,
|
private val cache: ScriptDependenciesCache,
|
||||||
private val scriptDefinitionProvider: KotlinScriptDefinitionProvider
|
private val scriptDefinitionProvider: ScriptDefinitionProvider
|
||||||
) {
|
) {
|
||||||
private val requests = ConcurrentHashMap<String, ModStampedRequest>()
|
private val requests = ConcurrentHashMap<String, ModStampedRequest>()
|
||||||
private val contentLoader = ScriptContentLoader(project)
|
private val contentLoader = ScriptContentLoader(project)
|
||||||
|
|||||||
+4
-10
@@ -21,28 +21,22 @@ import com.intellij.openapi.vfs.VirtualFile
|
|||||||
import com.intellij.psi.ResolveScopeProvider
|
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.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
import org.jetbrains.kotlin.script.getScriptDefinition
|
import org.jetbrains.kotlin.script.getScriptDefinition
|
||||||
|
|
||||||
class KotlinScriptResolveScopeProvider : ResolveScopeProvider() {
|
class KotlinScriptResolveScopeProvider : ResolveScopeProvider() {
|
||||||
companion object {
|
|
||||||
val USE_NULL_RESOLVE_SCOPE = "USE_NULL_RESOLVE_SCOPE"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getResolveScope(file: VirtualFile, project: Project): GlobalSearchScope? {
|
override fun getResolveScope(file: VirtualFile, project: Project): GlobalSearchScope? {
|
||||||
val scriptDefinition = getScriptDefinition(file, project)
|
val scriptDefinition = getScriptDefinition(file, project)
|
||||||
// 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.template == Any::class -> null
|
||||||
|
scriptDefinition is StandardIdeScriptDefinition -> null
|
||||||
scriptDefinition is KotlinScriptDefinitionFromAnnotatedTemplate -> // TODO: should include the file itself
|
scriptDefinition is KotlinScriptDefinitionFromAnnotatedTemplate -> // TODO: should include the file itself
|
||||||
if (scriptDefinition.environment?.containsKey(USE_NULL_RESOLVE_SCOPE) ?: false) {
|
ScriptDependenciesManager.getInstance(project).getAllScriptsClasspathScope()
|
||||||
null
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ScriptDependenciesManager.getInstance(project).getAllScriptsClasspathScope()
|
|
||||||
}
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+50
-37
@@ -24,23 +24,51 @@ import com.intellij.openapi.vfs.VirtualFile
|
|||||||
import org.gradle.tooling.ProjectConnection
|
import org.gradle.tooling.ProjectConnection
|
||||||
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.script.ScriptTemplatesProvider
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper
|
import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper
|
||||||
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings
|
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings
|
||||||
|
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.script.dependencies.Environment
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||||
|
|
||||||
abstract class AbstractGradleScriptTemplatesProvider(
|
abstract class AbstractGradleScriptTemplatesProvider(
|
||||||
project: Project, override val id: String, private val templateClass: String, private val dependencySelector: Regex
|
private val project: Project,
|
||||||
): ScriptTemplatesProvider {
|
override val id: String,
|
||||||
|
private val templateClass: String,
|
||||||
|
private val dependencySelector: Regex
|
||||||
|
): ScriptDefinitionContributor {
|
||||||
|
|
||||||
private val gradleExeSettings: GradleExecutionSettings? by lazy {
|
override fun getDefinitions(): List<KotlinScriptDefinition> {
|
||||||
try {
|
val gradleExeSettings = getExeSettings() ?: return emptyList()
|
||||||
ExternalSystemApiUtil.getExecutionSettings<GradleExecutionSettings>(
|
|
||||||
|
val gradleHome = gradleExeSettings.gradleHome ?: error("Unable to get Gradle home directory")
|
||||||
|
|
||||||
|
val gradleLibDir = File(gradleHome, "lib").let {
|
||||||
|
it.takeIf { it.exists() && it.isDirectory } ?: error("Invalid Gradle libraries directory $it")
|
||||||
|
}
|
||||||
|
val templateClasspath = gradleLibDir.listFiles { it ->
|
||||||
|
/* an inference problem without explicit 'it', TODO: remove when fixed */
|
||||||
|
dependencySelector.matches(it.name)
|
||||||
|
}.takeIf { it.isNotEmpty() }?.asList() ?: error("Missing jars in gradle directory")
|
||||||
|
|
||||||
|
return loadDefinitionsFromTemplates(
|
||||||
|
listOf(templateClass),
|
||||||
|
templateClasspath,
|
||||||
|
createEnvironment(gradleExeSettings),
|
||||||
|
additionalResolverClasspath(gradleLibDir)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun additionalResolverClasspath(gradleLibDir: File): List<File> = emptyList()
|
||||||
|
|
||||||
|
private fun getExeSettings(): GradleExecutionSettings? {
|
||||||
|
return try {
|
||||||
|
ExternalSystemApiUtil.getExecutionSettings(
|
||||||
project,
|
project,
|
||||||
com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.toCanonicalPath(project.basePath!!),
|
ExternalSystemApiUtil.toCanonicalPath(project.basePath!!),
|
||||||
org.jetbrains.plugins.gradle.util.GradleConstants.SYSTEM_ID)
|
GradleConstants.SYSTEM_ID)
|
||||||
}
|
}
|
||||||
catch (e: Throwable) {
|
catch (e: Throwable) {
|
||||||
// TODO: consider displaying the warning to the user
|
// TODO: consider displaying the warning to the user
|
||||||
@@ -49,44 +77,26 @@ abstract class AbstractGradleScriptTemplatesProvider(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val gradleJvmOptions: List<String> by lazy {
|
private fun createEnvironment(gradleExeSettings: GradleExecutionSettings): Environment {
|
||||||
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 } }
|
||||||
.filterNot(String::isBlank)
|
.filterNot(String::isBlank)
|
||||||
.distinct()
|
.distinct()
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
}
|
|
||||||
|
|
||||||
internal val gradleLibDir: File by lazy {
|
|
||||||
val gradleHome = gradleExeSettings?.gradleHome ?: error("Unable to get Gradle home directory")
|
|
||||||
|
|
||||||
File(gradleHome, "lib").let {
|
return mapOf(
|
||||||
it.takeIf { it.exists() && it.isDirectory } ?: error("Invalid Gradle libraries directory $it")
|
"gradleHome" to gradleExeSettings.gradleHome?.let(::File),
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val isValid: Boolean get() = true
|
|
||||||
|
|
||||||
override val templateClassNames get() = listOf(templateClass)
|
|
||||||
|
|
||||||
override val templateClasspath: List<File> get() {
|
|
||||||
return gradleLibDir.listFiles { it ->
|
|
||||||
/* an inference problem without explicit 'it', TODO: remove when fixed */
|
|
||||||
dependencySelector.matches(it.name)
|
|
||||||
}.takeIf { it.isNotEmpty() }?.asList() ?: error("Missing jars in gradle directory")
|
|
||||||
}
|
|
||||||
|
|
||||||
override val environment: Map<String, Any?>? by lazy {
|
|
||||||
mapOf(
|
|
||||||
"gradleHome" to gradleExeSettings?.gradleHome?.let(::File),
|
|
||||||
"projectRoot" to (project.basePath ?: project.baseDir.canonicalPath)?.let(::File),
|
"projectRoot" to (project.basePath ?: project.baseDir.canonicalPath)?.let(::File),
|
||||||
"gradleWithConnection" to { action: (ProjectConnection) -> Unit ->
|
"gradleWithConnection" to { action: (ProjectConnection) -> Unit ->
|
||||||
GradleExecutionHelper().execute(project.basePath!!, null) { action(it) } },
|
GradleExecutionHelper().execute(project.basePath!!, null) { action(it) }
|
||||||
"gradleJavaHome" to gradleExeSettings?.javaHome,
|
},
|
||||||
|
"gradleJavaHome" to gradleExeSettings.javaHome,
|
||||||
"gradleJvmOptions" to gradleJvmOptions,
|
"gradleJvmOptions" to gradleJvmOptions,
|
||||||
"getScriptSectionTokens" to ::topLevelSectionCodeTextTokens
|
"getScriptSectionTokens" to ::topLevelSectionCodeTextTokens
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,11 +107,14 @@ abstract class AbstractGradleKotlinDSLTemplateProvider(project: Project, private
|
|||||||
templateClass,
|
templateClass,
|
||||||
Regex("^gradle-(?:kotlin-dsl|core).*\\.jar\$")
|
Regex("^gradle-(?:kotlin-dsl|core).*\\.jar\$")
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// TODO_R: check this against kotlin-dsl branch that uses daemon
|
// TODO_R: check this against kotlin-dsl branch that uses daemon
|
||||||
override val additionalResolverClasspath: List<File> get() =
|
override fun additionalResolverClasspath(gradleLibDir: File): List<File> {
|
||||||
// additionally need compiler jar to load gradle resolver
|
// additionally need compiler jar to load gradle resolver
|
||||||
gradleLibDir.listFiles { file -> file.name.startsWith("kotlin-compiler-embeddable") || file.name.startsWith("kotlin-stdlib") }
|
return gradleLibDir.listFiles { file -> file.name.startsWith("kotlin-compiler-embeddable") || file.name.startsWith("kotlin-stdlib") }
|
||||||
.firstOrNull()?.let(::listOf).orEmpty()
|
.firstOrNull()?.let(::listOf).orEmpty()
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GradleSettingsKotlinDSLTemplateProvider(project: Project)
|
class GradleSettingsKotlinDSLTemplateProvider(project: Project)
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import com.intellij.psi.PsiFileFactory
|
|||||||
import com.intellij.psi.PsiManager
|
import com.intellij.psi.PsiManager
|
||||||
import com.intellij.psi.impl.PsiFileFactoryImpl
|
import com.intellij.psi.impl.PsiFileFactoryImpl
|
||||||
import com.intellij.testFramework.LightVirtualFile
|
import com.intellij.testFramework.LightVirtualFile
|
||||||
|
import com.intellij.util.containers.ContainerUtil
|
||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
import org.jetbrains.kotlin.console.actions.BuildAndRestartConsoleAction
|
import org.jetbrains.kotlin.console.actions.BuildAndRestartConsoleAction
|
||||||
import org.jetbrains.kotlin.console.actions.KtExecuteCommandAction
|
import org.jetbrains.kotlin.console.actions.KtExecuteCommandAction
|
||||||
@@ -54,7 +55,12 @@ import org.jetbrains.kotlin.console.gutter.ConsoleIndicatorRenderer
|
|||||||
import org.jetbrains.kotlin.console.gutter.IconWithTooltip
|
import org.jetbrains.kotlin.console.gutter.IconWithTooltip
|
||||||
import org.jetbrains.kotlin.console.gutter.ReplIcons
|
import org.jetbrains.kotlin.console.gutter.ReplIcons
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.*
|
import org.jetbrains.kotlin.idea.caches.resolve.NotUnderContentRootModuleInfo
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.productionSourceInfo
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.testSourceInfo
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor
|
||||||
|
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
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -66,7 +72,6 @@ import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
|
|||||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor
|
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.repl.ReplState
|
import org.jetbrains.kotlin.resolve.repl.ReplState
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider
|
|
||||||
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
|
||||||
@@ -89,7 +94,9 @@ class KotlinConsoleRunner(
|
|||||||
|
|
||||||
override fun finishConsole() {
|
override fun finishConsole() {
|
||||||
KotlinConsoleKeeper.getInstance(project).removeConsole(consoleView.virtualFile)
|
KotlinConsoleKeeper.getInstance(project).removeConsole(consoleView.virtualFile)
|
||||||
KotlinScriptDefinitionProvider.getInstance(project)!!.removeScriptDefinition(consoleScriptDefinition)
|
val consoleContributor = ScriptDefinitionContributor.find<ConsoleScriptDefinitionContributor>(project)!!
|
||||||
|
consoleContributor.unregisterDefinition(consoleScriptDefinition)
|
||||||
|
ScriptDefinitionsManager.getInstance(project).reloadDefinitionsBy(consoleContributor)
|
||||||
|
|
||||||
if (ApplicationManager.getApplication().isUnitTestMode) {
|
if (ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
consoleTerminated.countDown()
|
consoleTerminated.countDown()
|
||||||
@@ -151,7 +158,10 @@ class KotlinConsoleRunner(
|
|||||||
val executeAction = KtExecuteCommandAction(consoleView.virtualFile)
|
val executeAction = KtExecuteCommandAction(consoleView.virtualFile)
|
||||||
executeAction.registerCustomShortcutSet(CommonShortcuts.CTRL_ENTER, consoleView.consoleEditor.component)
|
executeAction.registerCustomShortcutSet(CommonShortcuts.CTRL_ENTER, consoleView.consoleEditor.component)
|
||||||
|
|
||||||
KotlinScriptDefinitionProvider.getInstance(project)!!.addScriptDefinition(consoleScriptDefinition)
|
val consoleContributor = ScriptDefinitionContributor.find<ConsoleScriptDefinitionContributor>(project)!!
|
||||||
|
consoleContributor.registerDefinition(consoleScriptDefinition)
|
||||||
|
ScriptDefinitionsManager.getInstance(project).reloadDefinitionsBy(consoleContributor)
|
||||||
|
|
||||||
enableCompletion(consoleView)
|
enableCompletion(consoleView)
|
||||||
|
|
||||||
return consoleView
|
return consoleView
|
||||||
@@ -285,4 +295,22 @@ class KotlinConsoleRunner(
|
|||||||
private fun configureFileDependencies(psiFile: KtFile) {
|
private fun configureFileDependencies(psiFile: KtFile) {
|
||||||
psiFile.moduleInfo = module.testSourceInfo() ?: module.productionSourceInfo() ?: NotUnderContentRootModuleInfo
|
psiFile.moduleInfo = module.testSourceInfo() ?: module.productionSourceInfo() ?: NotUnderContentRootModuleInfo
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConsoleScriptDefinitionContributor: ScriptDefinitionContributor {
|
||||||
|
private val definitions = ContainerUtil.newConcurrentSet<KotlinScriptDefinition>()
|
||||||
|
|
||||||
|
override val id: String = "IDEA Console"
|
||||||
|
|
||||||
|
override fun getDefinitions(): List<KotlinScriptDefinition> {
|
||||||
|
return definitions.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun registerDefinition(definition: KotlinScriptDefinition) {
|
||||||
|
definitions.add(definition)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unregisterDefinition(definition: KotlinScriptDefinition) {
|
||||||
|
definitions.remove(definition)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -30,8 +30,8 @@
|
|||||||
<extensionPoint name="storageComponentContainerContributor"
|
<extensionPoint name="storageComponentContainerContributor"
|
||||||
interface="org.jetbrains.kotlin.extensions.StorageComponentContainerContributor"
|
interface="org.jetbrains.kotlin.extensions.StorageComponentContainerContributor"
|
||||||
area="IDEA_PROJECT"/>
|
area="IDEA_PROJECT"/>
|
||||||
<extensionPoint name="scriptTemplatesProvider"
|
<extensionPoint name="scriptDefinitionContributor"
|
||||||
interface="org.jetbrains.kotlin.script.ScriptTemplatesProvider"
|
interface="org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor"
|
||||||
area="IDEA_PROJECT"/>
|
area="IDEA_PROJECT"/>
|
||||||
<extensionPoint name="facetConfigurationExtension"
|
<extensionPoint name="facetConfigurationExtension"
|
||||||
interface="org.jetbrains.kotlin.idea.facet.KotlinFacetConfigurationExtension"/>
|
interface="org.jetbrains.kotlin.idea.facet.KotlinFacetConfigurationExtension"/>
|
||||||
|
|||||||
@@ -25,13 +25,16 @@
|
|||||||
<!-- diagnosticSuppressor decelerated in common.xml -->
|
<!-- diagnosticSuppressor decelerated in common.xml -->
|
||||||
<diagnosticSuppressor implementation="org.jetbrains.kotlin.idea.debugger.DiagnosticSuppressorForDebugger"/>
|
<diagnosticSuppressor implementation="org.jetbrains.kotlin.idea.debugger.DiagnosticSuppressorForDebugger"/>
|
||||||
|
|
||||||
<scriptTemplatesProvider
|
<scriptDefinitionContributor
|
||||||
id="ScriptTemplatesFromCompilerSettingsProvider"
|
id="ScriptTemplatesFromCompilerSettingsProvider"
|
||||||
implementation="org.jetbrains.kotlin.idea.script.ScriptTemplatesFromCompilerSettingsProvider"/>
|
implementation="org.jetbrains.kotlin.idea.script.ScriptTemplatesFromCompilerSettingsProvider"/>
|
||||||
|
|
||||||
<scriptTemplatesProvider id="StandardKotlinScriptTemplateProvider"
|
<scriptDefinitionContributor id="StandardScriptDefinitionContributor"
|
||||||
order="last"
|
order="last"
|
||||||
implementation="org.jetbrains.kotlin.idea.script.StandardKotlinScriptTemplateProvider"/>
|
implementation="org.jetbrains.kotlin.idea.core.script.StandardScriptDefinitionContributor"/>
|
||||||
|
|
||||||
|
<scriptDefinitionContributor id="ConsoleScriptDefinitionContributor"
|
||||||
|
implementation="org.jetbrains.kotlin.console.ConsoleScriptDefinitionContributor"/>
|
||||||
|
|
||||||
<idePlatformSupport implementation="org.jetbrains.kotlin.caches.resolve.JvmPlatformSupport"/>
|
<idePlatformSupport implementation="org.jetbrains.kotlin.caches.resolve.JvmPlatformSupport"/>
|
||||||
<idePlatformSupport implementation="org.jetbrains.kotlin.caches.resolve.JsPlatformSupport"/>
|
<idePlatformSupport implementation="org.jetbrains.kotlin.caches.resolve.JsPlatformSupport"/>
|
||||||
|
|||||||
@@ -280,8 +280,8 @@
|
|||||||
<projectService serviceInterface="org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer"
|
<projectService serviceInterface="org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer"
|
||||||
serviceImplementation="org.jetbrains.kotlin.resolve.DummyCodeAnalyzerInitializer"/>
|
serviceImplementation="org.jetbrains.kotlin.resolve.DummyCodeAnalyzerInitializer"/>
|
||||||
|
|
||||||
<projectService serviceInterface="org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider"
|
<projectService serviceInterface="org.jetbrains.kotlin.script.ScriptDefinitionProvider"
|
||||||
serviceImplementation="org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider"/>
|
serviceImplementation="org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager"/>
|
||||||
|
|
||||||
<projectService serviceInterface="org.jetbrains.kotlin.script.ScriptDependenciesProvider"
|
<projectService serviceInterface="org.jetbrains.kotlin.script.ScriptDependenciesProvider"
|
||||||
serviceImplementation="org.jetbrains.kotlin.idea.core.script.IdeScriptDependenciesProvider"/>
|
serviceImplementation="org.jetbrains.kotlin.idea.core.script.IdeScriptDependenciesProvider"/>
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2016 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.script
|
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.projectRoots.JavaSdk
|
|
||||||
import com.intellij.openapi.projectRoots.ProjectJdkTable
|
|
||||||
import com.intellij.openapi.projectRoots.ex.PathUtilEx
|
|
||||||
import org.jetbrains.kotlin.idea.core.script.dependencies.KotlinScriptResolveScopeProvider
|
|
||||||
import org.jetbrains.kotlin.script.ScriptTemplatesProvider
|
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
|
||||||
import java.io.File
|
|
||||||
import kotlin.script.dependencies.*
|
|
||||||
import kotlin.script.experimental.dependencies.*
|
|
||||||
import kotlin.script.experimental.dependencies.DependenciesResolver.ResolveResult
|
|
||||||
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
|
||||||
|
|
||||||
class StandardKotlinScriptTemplateProvider(val project: Project) : ScriptTemplatesProvider {
|
|
||||||
override val id: String = "StandardKotlinScriptTemplateProvider"
|
|
||||||
override val isValid: Boolean = true
|
|
||||||
|
|
||||||
override val templateClassNames: Iterable<String> get() = listOf(ScriptTemplateWithArgs::class.qualifiedName!!)
|
|
||||||
override val templateClasspath get() = emptyList<File>()
|
|
||||||
|
|
||||||
override val environment: Map<String, Any?>? get() {
|
|
||||||
return mapOf(
|
|
||||||
KotlinScriptResolveScopeProvider.USE_NULL_RESOLVE_SCOPE to true,
|
|
||||||
"sdk" to getScriptSDK(project)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val resolver: DependenciesResolver = BundledKotlinScriptDependenciesResolver()
|
|
||||||
|
|
||||||
private fun getScriptSDK(project: Project): String? {
|
|
||||||
val jdk = PathUtilEx.getAnyJdk(project) ?:
|
|
||||||
ProjectJdkTable.getInstance().allJdks.firstOrNull { sdk -> sdk.sdkType is JavaSdk }
|
|
||||||
|
|
||||||
return jdk?.homePath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class BundledKotlinScriptDependenciesResolver : DependenciesResolver {
|
|
||||||
override fun resolve(
|
|
||||||
scriptContents: ScriptContents,
|
|
||||||
environment: Environment
|
|
||||||
): ResolveResult {
|
|
||||||
val javaHome = environment.get("sdk") as String?
|
|
||||||
val dependencies = ScriptDependencies(
|
|
||||||
javaHome = javaHome?.let(::File),
|
|
||||||
classpath = with(PathUtil.kotlinPathsForIdeaPlugin) {
|
|
||||||
listOf(
|
|
||||||
reflectPath,
|
|
||||||
stdlibPath,
|
|
||||||
scriptRuntimePath
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return dependencies.asSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,20 +18,23 @@ package org.jetbrains.kotlin.idea.script
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettings
|
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettings
|
||||||
import org.jetbrains.kotlin.script.ScriptTemplatesProvider
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.loadDefinitionsFromTemplates
|
||||||
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class ScriptTemplatesFromCompilerSettingsProvider(project: Project): ScriptTemplatesProvider
|
class ScriptTemplatesFromCompilerSettingsProvider(private val project: Project) : ScriptDefinitionContributor {
|
||||||
{
|
override fun getDefinitions(): List<KotlinScriptDefinition> {
|
||||||
private val kotlinSettings = KotlinCompilerSettings.getInstance(project).settings
|
val kotlinSettings = KotlinCompilerSettings.getInstance(project).settings
|
||||||
|
return loadDefinitionsFromTemplates(
|
||||||
|
templateClassNames = kotlinSettings.scriptTemplates.split(',', ' '),
|
||||||
|
templateClasspath = kotlinSettings.scriptTemplatesClasspath.split(File.pathSeparator).map(::File),
|
||||||
|
environment = mapOf(
|
||||||
|
"projectRoot" to (project.basePath ?: project.baseDir.canonicalPath)?.let(::File))
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override val id: String = "KotlinCompilerScriptTemplatesSettings"
|
override val id: String = "KotlinCompilerScriptTemplatesSettings"
|
||||||
override val isValid: Boolean = kotlinSettings.scriptTemplates.isNotBlank()
|
|
||||||
|
|
||||||
override val templateClassNames: Iterable<String> get() = kotlinSettings.scriptTemplates.split(',', ' ')
|
|
||||||
override val templateClasspath get() = kotlinSettings.scriptTemplatesClasspath.split(File.pathSeparator).map(::File)
|
|
||||||
override val environment: Map<String, Any?>? by lazy { mapOf(
|
|
||||||
"projectRoot" to (project.basePath ?: project.baseDir.canonicalPath)?.let(::File))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ import com.intellij.openapi.vfs.VirtualFile
|
|||||||
import com.intellij.testFramework.PlatformTestUtil
|
import com.intellij.testFramework.PlatformTestUtil
|
||||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
||||||
import org.jetbrains.kotlin.idea.KotlinDaemonAnalyzerTestCase
|
import org.jetbrains.kotlin.idea.KotlinDaemonAnalyzerTestCase
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager.Companion.updateScriptDependenciesSynchronously
|
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager.Companion.updateScriptDependenciesSynchronously
|
||||||
import org.jetbrains.kotlin.idea.navigation.GotoCheck
|
import org.jetbrains.kotlin.idea.navigation.GotoCheck
|
||||||
import org.jetbrains.kotlin.script.ScriptTemplatesProvider
|
|
||||||
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.kotlin.test.MockLibraryUtil
|
import org.jetbrains.kotlin.test.MockLibraryUtil
|
||||||
@@ -39,12 +39,6 @@ import org.junit.Assert
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
import kotlin.script.dependencies.Environment
|
import kotlin.script.dependencies.Environment
|
||||||
import kotlin.script.dependencies.ScriptContents
|
|
||||||
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
|
|
||||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
|
||||||
import kotlin.script.experimental.dependencies.asSuccess
|
|
||||||
import kotlin.script.templates.ScriptTemplateDefinition
|
|
||||||
|
|
||||||
|
|
||||||
abstract class AbstractScriptConfigurationHighlightingTest : AbstractScriptConfigurationTest() {
|
abstract class AbstractScriptConfigurationHighlightingTest : AbstractScriptConfigurationTest() {
|
||||||
@@ -182,44 +176,10 @@ abstract class AbstractScriptConfigurationTest : KotlinDaemonAnalyzerTestCase()
|
|||||||
|
|
||||||
PlatformTestUtil.registerExtension(
|
PlatformTestUtil.registerExtension(
|
||||||
Extensions.getArea(project),
|
Extensions.getArea(project),
|
||||||
ScriptTemplatesProvider.EP_NAME,
|
ScriptDefinitionContributor.EP_NAME,
|
||||||
provider,
|
provider,
|
||||||
testRootDisposable
|
testRootDisposable
|
||||||
)
|
)
|
||||||
ScriptDependenciesManager.reloadScriptDefinitions(project)
|
ScriptDefinitionsManager.getInstance(project).reloadScriptDefinitions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CustomScriptTemplateProvider(
|
|
||||||
override val environment: Map<String, Any?>
|
|
||||||
) : ScriptTemplatesProvider {
|
|
||||||
override val id = "Test"
|
|
||||||
override val isValid = true
|
|
||||||
override val templateClassNames = listOf("custom.scriptDefinition.Template")
|
|
||||||
override val templateClasspath = listOfNotNull(environment["template-classes"] as? File)
|
|
||||||
}
|
|
||||||
|
|
||||||
class FromTextTemplateProvider(
|
|
||||||
override val environment: Map<String, Any?>
|
|
||||||
) : ScriptTemplatesProvider {
|
|
||||||
override val id = "Test"
|
|
||||||
override val isValid = true
|
|
||||||
override val templateClassNames = listOf("org.jetbrains.kotlin.idea.script.Template")
|
|
||||||
override val templateClasspath get() = emptyList<File>()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class FromTextDependenciesResolver : AsyncDependenciesResolver {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
suspend override fun resolveAsync(scriptContents: ScriptContents, environment: Environment): DependenciesResolver.ResolveResult {
|
|
||||||
return ScriptDependencies(
|
|
||||||
classpath = (environment["classpath"] as? List<File>).orEmpty(),
|
|
||||||
imports = (environment["imports"] as? List<String>).orEmpty(),
|
|
||||||
sources = (environment["sources"] as? List<File>).orEmpty()
|
|
||||||
).asSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
@ScriptTemplateDefinition(FromTextDependenciesResolver::class, scriptFilePattern = "script.kts")
|
|
||||||
class Template
|
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.script
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.loadDefinitionsFromTemplates
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.script.dependencies.Environment
|
||||||
|
import kotlin.script.dependencies.ScriptContents
|
||||||
|
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
|
||||||
|
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||||
|
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||||
|
import kotlin.script.experimental.dependencies.asSuccess
|
||||||
|
import kotlin.script.templates.ScriptTemplateDefinition
|
||||||
|
|
||||||
|
|
||||||
|
class CustomScriptTemplateProvider(
|
||||||
|
val environment: Environment
|
||||||
|
) : ScriptDefinitionContributor {
|
||||||
|
override val id = "Test"
|
||||||
|
|
||||||
|
override fun getDefinitions() = loadDefinitionsFromTemplates(
|
||||||
|
templateClassNames = listOf("custom.scriptDefinition.Template"),
|
||||||
|
templateClasspath = listOfNotNull(environment["template-classes"] as? File),
|
||||||
|
environment = environment
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class FromTextTemplateProvider(
|
||||||
|
val environment: Map<String, Any?>
|
||||||
|
) : ScriptDefinitionContributor {
|
||||||
|
override val id = "Test"
|
||||||
|
override fun getDefinitions() = loadDefinitionsFromTemplates(
|
||||||
|
templateClassNames = listOf("org.jetbrains.kotlin.idea.script.Template"),
|
||||||
|
templateClasspath = emptyList(),
|
||||||
|
environment = environment
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FromTextDependenciesResolver : AsyncDependenciesResolver {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
suspend override fun resolveAsync(scriptContents: ScriptContents, environment: Environment): DependenciesResolver.ResolveResult {
|
||||||
|
return ScriptDependencies(
|
||||||
|
classpath = (environment["classpath"] as? List<File>).orEmpty(),
|
||||||
|
imports = (environment["imports"] as? List<String>).orEmpty(),
|
||||||
|
sources = (environment["sources"] as? List<File>).orEmpty()
|
||||||
|
).asSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
@ScriptTemplateDefinition(FromTextDependenciesResolver::class, scriptFilePattern = "script.kts")
|
||||||
|
class Template
|
||||||
+1
-2
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.cli.common.repl.*
|
|||||||
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
|
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
|
||||||
import org.jetbrains.kotlin.cli.jvm.repl.GenericReplCompiler
|
import org.jetbrains.kotlin.cli.jvm.repl.GenericReplCompiler
|
||||||
import org.jetbrains.kotlin.config.*
|
import org.jetbrains.kotlin.config.*
|
||||||
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
|
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
@@ -64,7 +63,7 @@ class KotlinJsr223JvmLocalScriptEngine(
|
|||||||
private fun makeScriptDefinition(templateClasspath: List<File>, templateClassName: String): KotlinScriptDefinition {
|
private fun makeScriptDefinition(templateClasspath: List<File>, templateClassName: String): KotlinScriptDefinition {
|
||||||
val classloader = URLClassLoader(templateClasspath.map { it.toURI().toURL() }.toTypedArray(), this.javaClass.classLoader)
|
val classloader = URLClassLoader(templateClasspath.map { it.toURI().toURL() }.toTypedArray(), this.javaClass.classLoader)
|
||||||
val cls = classloader.loadClass(templateClassName)
|
val cls = classloader.loadClass(templateClassName)
|
||||||
return KotlinScriptDefinitionFromAnnotatedTemplate(cls.kotlin, null, null, emptyMap())
|
return KotlinScriptDefinitionFromAnnotatedTemplate(cls.kotlin, emptyMap())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun makeCompilerConfiguration() = CompilerConfiguration().apply {
|
private fun makeCompilerConfiguration() = CompilerConfiguration().apply {
|
||||||
|
|||||||
+1
-1
@@ -115,7 +115,7 @@ done
|
|||||||
suppressOutput: Boolean = false
|
suppressOutput: Boolean = false
|
||||||
): Class<*>? =
|
): Class<*>? =
|
||||||
compileScriptImpl("src/test/resources/scripts/" + scriptFileName,
|
compileScriptImpl("src/test/resources/scripts/" + scriptFileName,
|
||||||
KotlinScriptDefinitionFromAnnotatedTemplate(scriptTemplate, null, null, environment), suppressOutput)
|
KotlinScriptDefinitionFromAnnotatedTemplate(scriptTemplate, environment), suppressOutput)
|
||||||
|
|
||||||
private fun compileScriptImpl(
|
private fun compileScriptImpl(
|
||||||
scriptPath: String,
|
scriptPath: String,
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ 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, null, null, emptyMap())
|
val def = KotlinScriptDefinitionFromAnnotatedTemplate(ScriptForSamWithReceivers::class, emptyMap())
|
||||||
configuration.add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, def)
|
configuration.add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, def)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
|||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.addKotlinSourceRoot
|
import org.jetbrains.kotlin.config.addKotlinSourceRoot
|
||||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
|
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider
|
|
||||||
import org.jetbrains.kotlin.script.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
|
||||||
import org.jetbrains.kotlin.test.TestJdkKind
|
import org.jetbrains.kotlin.test.TestJdkKind
|
||||||
@@ -51,8 +49,6 @@ abstract class AbstractKotlinUastTest : AbstractUastTest() {
|
|||||||
|
|
||||||
initializeKotlinEnvironment()
|
initializeKotlinEnvironment()
|
||||||
|
|
||||||
KotlinScriptDefinitionProvider.getInstance(project)?.addScriptDefinition(StandardScriptDefinition)
|
|
||||||
|
|
||||||
val trace = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
|
val trace = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
|
||||||
|
|
||||||
val environment = kotlinCoreEnvironment!!
|
val environment = kotlinCoreEnvironment!!
|
||||||
|
|||||||
Reference in New Issue
Block a user