Refactor script definition and related parts:
- simplify script definition interface, convert it to class - create simple definitions right from base - refactor (rename and simplify) script definition with annotated template - simplify usages of script definition in many places
This commit is contained in:
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import kotlin.Pair;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
||||
@@ -24,18 +23,17 @@ import org.jetbrains.kotlin.codegen.context.MethodContext;
|
||||
import org.jetbrains.kotlin.codegen.context.ScriptContext;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -154,17 +152,19 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
iv.invokespecial("java/lang/Object", "<init>", "()V", false);
|
||||
}
|
||||
else {
|
||||
List<Pair<Name, KotlinType>> superclassParamsMap = scriptDescriptor.getScriptParametersToPassToSuperclass();
|
||||
ConstructorDescriptor ctorDesc = DescriptorUtilsKt.getConstructorByParamsMap(superclass, superclassParamsMap);
|
||||
// TODO: check if it is correct way to find a promary constructor
|
||||
Collection<ClassConstructorDescriptor> ctorDescriptors = superclass.getConstructors();
|
||||
assert ctorDescriptors.size() == 1;
|
||||
ConstructorDescriptor ctorDesc = ctorDescriptors.iterator().next();
|
||||
assert ctorDesc != null;
|
||||
|
||||
iv.load(0, classType);
|
||||
|
||||
List<ValueParameterDescriptor> valueParameters = scriptDescriptor.getUnsubstitutedPrimaryConstructor().getValueParameters();
|
||||
for (Pair<Name, KotlinType> superclassParam: superclassParamsMap) {
|
||||
for (ValueParameterDescriptor superclassParam: ctorDesc.getValueParameters()) {
|
||||
ValueParameterDescriptor valueParam = null;
|
||||
for (ValueParameterDescriptor vpd: valueParameters) {
|
||||
if (vpd.getName().equals(superclassParam.getFirst())) {
|
||||
if (vpd.getName().equals(superclassParam.getName())) {
|
||||
valueParam = vpd;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHand
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromTemplate
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||
import org.jetbrains.kotlin.script.StandardScriptDefinition
|
||||
import org.jetbrains.kotlin.util.PerformanceCounter
|
||||
import org.jetbrains.kotlin.utils.KotlinPaths
|
||||
@@ -400,7 +400,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
for (template in scriptTemplates) {
|
||||
try {
|
||||
val cls = classloader.loadClass(template)
|
||||
val def = KotlinScriptDefinitionFromTemplate(cls.kotlin, null, null, scriptResolverEnv)
|
||||
val def = KotlinScriptDefinitionFromAnnotatedTemplate(cls.kotlin, null, null, scriptResolverEnv)
|
||||
configuration.add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, def)
|
||||
messageCollector.report(
|
||||
CompilerMessageSeverity.INFO,
|
||||
|
||||
@@ -43,8 +43,6 @@ import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||
import org.jetbrains.kotlin.script.KotlinScriptExternalDependencies
|
||||
import org.jetbrains.kotlin.script.ScriptParameter
|
||||
import java.io.File
|
||||
|
||||
private val logger = Logger.getInstance(GenericRepl::class.java)
|
||||
|
||||
@@ -56,7 +54,7 @@ open class GenericReplChecker(
|
||||
) : ReplChecker {
|
||||
protected val environment = run {
|
||||
compilerConfiguration.apply {
|
||||
add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, DelegatingScriptDefWithNoParams(scriptDefinition))
|
||||
add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, scriptDefinition)
|
||||
put<MessageCollector>(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
||||
put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
|
||||
}
|
||||
@@ -71,10 +69,6 @@ open class GenericReplChecker(
|
||||
val psiFile: KtFile,
|
||||
val errorHolder: DiagnosticMessageHolder)
|
||||
|
||||
protected class DelegatingScriptDefWithNoParams(parent: KotlinScriptDefinition) : KotlinScriptDefinition by parent {
|
||||
override fun getScriptParameters(scriptDescriptor: ScriptDescriptor): List<ScriptParameter> = emptyList()
|
||||
}
|
||||
|
||||
protected var lineState: LineState? = null
|
||||
|
||||
fun createDiagnosticHolder() = ReplTerminalDiagnosticMessageHolder()
|
||||
|
||||
@@ -41,7 +41,7 @@ import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtScript
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromTemplate
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||
import java.io.PrintWriter
|
||||
import java.net.URLClassLoader
|
||||
|
||||
@@ -179,7 +179,7 @@ class ReplInterpreter(
|
||||
|
||||
companion object {
|
||||
private val SCRIPT_RESULT_FIELD_NAME = "\$\$result"
|
||||
private val REPL_LINE_AS_SCRIPT_DEFINITION = object : KotlinScriptDefinitionFromTemplate(Any::class) {
|
||||
private val REPL_LINE_AS_SCRIPT_DEFINITION = object : KotlinScriptDefinition(Any::class) {
|
||||
override val name = "Kotlin REPL"
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.daemon.common.RemoteInputStream
|
||||
import org.jetbrains.kotlin.daemon.common.RemoteOperationsTracer
|
||||
import org.jetbrains.kotlin.daemon.common.RemoteOutputStream
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromTemplate
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.BufferedOutputStream
|
||||
@@ -85,7 +85,7 @@ open class KotlinJvmReplService(
|
||||
|
||||
try {
|
||||
val cls = classloader.loadClass(templateClassName)
|
||||
val def = KotlinScriptDefinitionFromTemplate(cls.kotlin, null, null, emptyMap())
|
||||
val def = KotlinScriptDefinitionFromAnnotatedTemplate(cls.kotlin, null, null, emptyMap())
|
||||
messageCollector.report(
|
||||
CompilerMessageSeverity.INFO,
|
||||
"New script definition $templateClassName: files pattern = \"${def.scriptFilePattern}\", resolver = ${def.resolver?.javaClass?.name}",
|
||||
|
||||
@@ -22,9 +22,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinScriptStub;
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes;
|
||||
import org.jetbrains.kotlin.script.GetScriptDefinitionKt;
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition;
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider;
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProviderKt;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -37,7 +36,7 @@ public class KtScript extends KtNamedDeclarationStub<KotlinScriptStub> implement
|
||||
private KotlinScriptDefinition getKotlinScriptDefinition() {
|
||||
if (!kotlinScriptDefinitionInitialized) {
|
||||
KtFile ktFile = getContainingKtFile();
|
||||
kotlinScriptDefinitionField = GetScriptDefinitionKt.getScriptDefinition(ktFile);
|
||||
kotlinScriptDefinitionField = KotlinScriptDefinitionProviderKt.getScriptDefinition(ktFile);
|
||||
kotlinScriptDefinitionInitialized = true;
|
||||
assert kotlinScriptDefinitionField != null : "Should not parse a script without definition: " + ktFile.toString();
|
||||
}
|
||||
|
||||
+1
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
|
||||
import org.jetbrains.kotlin.script.getScriptParameters
|
||||
|
||||
class LazyScriptClassMemberScope(
|
||||
resolveSession: ResolveSession,
|
||||
|
||||
+2
-11
@@ -29,8 +29,8 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProv
|
||||
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||
import org.jetbrains.kotlin.script.ScriptPriorities
|
||||
import org.jetbrains.kotlin.script.getKotlinTypeByFqName
|
||||
import org.jetbrains.kotlin.script.getScriptDefinition
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.utils.ifEmpty
|
||||
|
||||
@@ -79,14 +79,5 @@ class LazyScriptDescriptor(
|
||||
|
||||
override fun getUnsubstitutedPrimaryConstructor() = super.getUnsubstitutedPrimaryConstructor()!!
|
||||
|
||||
override fun computeSupertypes() = scriptDefinition.getScriptSupertypes(this).ifEmpty { listOf(builtIns.anyType) }
|
||||
|
||||
override fun getScriptParametersToPassToSuperclass(): List<Pair<Name, KotlinType>> {
|
||||
val scriptParams = scriptDefinition.getScriptParameters(this)
|
||||
return scriptDefinition.getScriptParametersToPassToSuperclass(this).map { name ->
|
||||
Pair(name,
|
||||
scriptParams.find { it.name == name }?.type
|
||||
?: throw RuntimeException("Unknown script parameter '$name' is specified as a script base class parameter"))
|
||||
}
|
||||
}
|
||||
override fun computeSupertypes() = listOf(getKotlinTypeByFqName(this, scriptDefinition.template.qualifiedName!!)).ifEmpty { listOf(builtIns.anyType) }
|
||||
}
|
||||
|
||||
@@ -18,48 +18,28 @@ package org.jetbrains.kotlin.script
|
||||
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
||||
import org.jetbrains.kotlin.psi.KtScript
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NotFoundClasses
|
||||
import org.jetbrains.kotlin.serialization.deserialization.findNonGenericClassAcrossDependencies
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import java.io.File
|
||||
import java.lang.RuntimeException
|
||||
import java.lang.UnsupportedOperationException
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.KTypeProjection
|
||||
import kotlin.reflect.KVariance
|
||||
import kotlin.script.StandardScriptTemplate
|
||||
|
||||
interface KotlinScriptDefinition {
|
||||
val name: String get() = "Kotlin Script"
|
||||
open class KotlinScriptDefinition(val template: KClass<out Any>) {
|
||||
|
||||
val template: KClass<out Any>
|
||||
open val name: String = "Kotlin Script"
|
||||
|
||||
// TODO: consider creating separate type (subtype? for kotlin scripts)
|
||||
val fileType: LanguageFileType get() = KotlinFileType.INSTANCE
|
||||
open val fileType: LanguageFileType = KotlinFileType.INSTANCE
|
||||
|
||||
fun <TF> isScript(file: TF): Boolean =
|
||||
open fun <TF> isScript(file: TF): Boolean =
|
||||
getFileName(file).endsWith(KotlinParserDefinition.STD_SCRIPT_EXT)
|
||||
|
||||
// TODO: replace these 3 functions with template property
|
||||
fun getScriptParameters(scriptDescriptor: ScriptDescriptor): List<ScriptParameter>
|
||||
fun getScriptSupertypes(scriptDescriptor: ScriptDescriptor): List<KotlinType> = emptyList()
|
||||
fun getScriptParametersToPassToSuperclass(scriptDescriptor: ScriptDescriptor): List<Name> = emptyList()
|
||||
|
||||
fun getScriptName(script: KtScript): Name =
|
||||
open fun getScriptName(script: KtScript): Name =
|
||||
ScriptNameUtil.fileNameWithExtensionStripped(script, KotlinParserDefinition.STD_SCRIPT_EXT)
|
||||
|
||||
fun <TF> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? = null
|
||||
open fun <TF> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? = null
|
||||
}
|
||||
|
||||
interface KotlinScriptExternalDependencies {
|
||||
@@ -70,54 +50,5 @@ interface KotlinScriptExternalDependencies {
|
||||
val scripts: Iterable<File> get() = emptyList()
|
||||
}
|
||||
|
||||
class KotlinScriptExternalDependenciesUnion(val dependencies: Iterable<KotlinScriptExternalDependencies>) : KotlinScriptExternalDependencies {
|
||||
override val javaHome: String? get() = dependencies.firstOrNull { it.javaHome != null }?.javaHome
|
||||
override val classpath: Iterable<File> get() = dependencies.flatMap { it.classpath }
|
||||
override val imports: Iterable<String> get() = dependencies.flatMap { it.imports }
|
||||
override val sources: Iterable<File> get() = dependencies.flatMap { it.sources }
|
||||
override val scripts: Iterable<File> get() = dependencies.flatMap { it.scripts }
|
||||
}
|
||||
object StandardScriptDefinition : KotlinScriptDefinition(StandardScriptTemplate::class)
|
||||
|
||||
data class ScriptParameter(val name: Name, val type: KotlinType)
|
||||
|
||||
object StandardScriptDefinition : KotlinScriptDefinitionFromTemplate(StandardScriptTemplate::class)
|
||||
|
||||
fun getKotlinType(scriptDescriptor: ScriptDescriptor, kClass: KClass<out Any>): KotlinType =
|
||||
getKotlinTypeByFqName(scriptDescriptor,
|
||||
kClass.qualifiedName ?: throw RuntimeException("Cannot get FQN from $kClass"))
|
||||
|
||||
fun getKotlinTypeByFqName(scriptDescriptor: ScriptDescriptor, fqName: String): KotlinType =
|
||||
scriptDescriptor.module.findNonGenericClassAcrossDependencies(
|
||||
ClassId.topLevel(FqName(fqName)),
|
||||
NotFoundClasses(LockBasedStorageManager.NO_LOCKS, scriptDescriptor.module)
|
||||
).defaultType
|
||||
|
||||
// TODO: support star projections
|
||||
// TODO: support annotations on types and type parameters
|
||||
// TODO: support type parameters on types and type projections
|
||||
fun getKotlinTypeByKType(scriptDescriptor: ScriptDescriptor, kType: KType): KotlinType {
|
||||
val classifier = kType.classifier
|
||||
if (classifier !is KClass<*>)
|
||||
throw UnsupportedOperationException("Only classes are supported as parameters in script template: $classifier")
|
||||
|
||||
val type = getKotlinType(scriptDescriptor, classifier)
|
||||
val typeProjections = kType.arguments.map { getTypeProjection(scriptDescriptor, it) }
|
||||
val isNullable = kType.isMarkedNullable
|
||||
|
||||
return KotlinTypeFactory.simpleType(Annotations.EMPTY, type.constructor, typeProjections, isNullable)
|
||||
}
|
||||
|
||||
private fun getTypeProjection(scriptDescriptor: ScriptDescriptor, kTypeProjection: KTypeProjection): TypeProjection {
|
||||
val kType = kTypeProjection.type ?: throw UnsupportedOperationException("Star projections are not supported")
|
||||
|
||||
val type = getKotlinTypeByKType(scriptDescriptor, kType)
|
||||
|
||||
val variance = when (kTypeProjection.variance) {
|
||||
KVariance.IN -> Variance.IN_VARIANCE
|
||||
KVariance.OUT -> Variance.OUT_VARIANCE
|
||||
KVariance.INVARIANT -> Variance.INVARIANT
|
||||
null -> throw UnsupportedOperationException("Star projections are not supported")
|
||||
}
|
||||
|
||||
return TypeProjectionImpl(variance, type)
|
||||
}
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* 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.script
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtScript
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import java.io.File
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.memberFunctions
|
||||
import kotlin.reflect.primaryConstructor
|
||||
|
||||
open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
||||
template: KClass<out Any>,
|
||||
providedResolver: ScriptDependenciesResolver? = null,
|
||||
providedScriptFilePattern: String? = null,
|
||||
val environment: Map<String, Any?>? = null
|
||||
) : KotlinScriptDefinition(template) {
|
||||
|
||||
val scriptFilePattern by lazy {
|
||||
providedScriptFilePattern ?: template.annotations.firstIsInstanceOrNull<ScriptTemplateDefinition>()?.scriptFilePattern ?: DEFAULT_SCRIPT_FILE_PATTERN
|
||||
}
|
||||
|
||||
val resolver: ScriptDependenciesResolver? by lazy {
|
||||
val defAnn by lazy { template.annotations.firstIsInstanceOrNull<ScriptTemplateDefinition>() }
|
||||
when {
|
||||
providedResolver != null -> providedResolver
|
||||
// TODO: logScriptDefMessage missing or invalid constructor
|
||||
defAnn != null ->
|
||||
try {
|
||||
defAnn.resolver.primaryConstructor?.call() ?: null.apply {
|
||||
log.error("[kts] No default constructor found for ${defAnn.resolver.qualifiedName}")
|
||||
}
|
||||
}
|
||||
catch (ex: ClassCastException) {
|
||||
log.error("[kts] Script def error ${ex.message}")
|
||||
null
|
||||
}
|
||||
else -> BasicScriptDependenciesResolver()
|
||||
}
|
||||
}
|
||||
|
||||
private val acceptedAnnotations: List<KClass<out Annotation>> by lazy {
|
||||
val resolveMethod = ScriptDependenciesResolver::resolve
|
||||
val resolverMethodAnnotations =
|
||||
resolver::class.memberFunctions.find {
|
||||
it.name == resolveMethod.name &&
|
||||
sameSignature(it, resolveMethod)
|
||||
}
|
||||
?.annotations
|
||||
?.filterIsInstance<AcceptedAnnotations>()
|
||||
resolverMethodAnnotations?.flatMap {
|
||||
val v = it.supportedAnnotationClasses
|
||||
v.toList() // TODO: inline after KT-9453 is resolved (now it fails with "java.lang.Class cannot be cast to kotlin.reflect.KClass")
|
||||
}
|
||||
?: emptyList()
|
||||
}
|
||||
|
||||
override val name = template.simpleName!!
|
||||
|
||||
override fun <TF> isScript(file: TF): Boolean =
|
||||
scriptFilePattern.let { Regex(it).matches(getFileName(file)) }
|
||||
|
||||
// TODO: implement other strategy - e.g. try to extract something from match with ScriptFilePattern
|
||||
override fun getScriptName(script: KtScript): Name = ScriptNameUtil.fileNameWithExtensionStripped(script, KotlinParserDefinition.STD_SCRIPT_EXT)
|
||||
|
||||
override fun <TF> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? {
|
||||
|
||||
val script = BasicScriptContents(file, getAnnotations = {
|
||||
val classLoader = (template as Any).javaClass.classLoader
|
||||
getAnnotationEntries(file, project)
|
||||
.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 { KtAnnotationWrapper(psiAnn, classLoader.loadClass(it.qualifiedName).kotlin as KClass<out Annotation>) }
|
||||
}
|
||||
.map { it.getProxy(classLoader) }
|
||||
})
|
||||
try {
|
||||
val fileDeps = resolver?.resolve(script, environment, ::logScriptDefMessage, previousDependencies)
|
||||
// TODO: use it as a Future
|
||||
return fileDeps?.get()
|
||||
}
|
||||
catch (ex: ClassCastException) {
|
||||
logScriptDefMessage(ScriptDependenciesResolver.ReportSeverity.ERROR, ex.message ?: "Invalid script template: ${template.qualifiedName}", null)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun <TF> getAnnotationEntries(file: TF, project: Project): Iterable<KtAnnotationEntry> = when (file) {
|
||||
is PsiFile -> getAnnotationEntriesFromPsiFile(file)
|
||||
is VirtualFile -> getAnnotationEntriesFromVirtualFile(file, project)
|
||||
is File -> {
|
||||
val virtualFile = (StandardFileSystems.local().findFileByPath(file.canonicalPath)
|
||||
?: throw IllegalArgumentException("Unable to find file ${file.canonicalPath}"))
|
||||
getAnnotationEntriesFromVirtualFile(virtualFile, project)
|
||||
}
|
||||
else -> throw IllegalArgumentException("Unsupported file type $file")
|
||||
}
|
||||
|
||||
private fun getAnnotationEntriesFromPsiFile(file: PsiFile) =
|
||||
if (file is KtFile) file.annotationEntries
|
||||
else throw IllegalArgumentException("Unable to extract kotlin annotations from ${file.name} (${file.fileType})")
|
||||
|
||||
private fun getAnnotationEntriesFromVirtualFile(file: VirtualFile, project: Project): Iterable<KtAnnotationEntry> {
|
||||
val psiFile: PsiFile = PsiManager.getInstance(project).findFile(file)
|
||||
?: throw IllegalArgumentException("Unable to load PSI from ${file.canonicalPath}")
|
||||
return getAnnotationEntriesFromPsiFile(psiFile)
|
||||
}
|
||||
|
||||
class BasicScriptContents<out TF>(myFile: TF, getAnnotations: () -> Iterable<Annotation>) : ScriptContents {
|
||||
override val file: File? by lazy { getFile(myFile) }
|
||||
override val annotations: Iterable<Annotation> by lazy { getAnnotations() }
|
||||
override val text: CharSequence? by lazy { getFileContents(myFile) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
internal val log = Logger.getInstance(KotlinScriptDefinitionFromAnnotatedTemplate::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun logScriptDefMessage(reportSeverity: ScriptDependenciesResolver.ReportSeverity, s: String, position: ScriptContents.Position?): Unit {
|
||||
val msg = (position?.run { "[at $line:$col]" } ?: "") + s
|
||||
when (reportSeverity) {
|
||||
ScriptDependenciesResolver.ReportSeverity.ERROR -> KotlinScriptDefinitionFromAnnotatedTemplate.log.error(msg)
|
||||
ScriptDependenciesResolver.ReportSeverity.WARNING -> KotlinScriptDefinitionFromAnnotatedTemplate.log.warn(msg)
|
||||
ScriptDependenciesResolver.ReportSeverity.INFO -> KotlinScriptDefinitionFromAnnotatedTemplate.log.info(msg)
|
||||
ScriptDependenciesResolver.ReportSeverity.DEBUG -> KotlinScriptDefinitionFromAnnotatedTemplate.log.debug(msg)
|
||||
}
|
||||
}
|
||||
@@ -72,3 +72,9 @@ class KotlinScriptDefinitionProvider {
|
||||
ServiceManager.getService(project, KotlinScriptDefinitionProvider::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
fun getScriptDefinition(file: VirtualFile, project: Project): KotlinScriptDefinition? =
|
||||
KotlinScriptDefinitionProvider.getInstance(project).findScriptDefinition(file)
|
||||
|
||||
fun getScriptDefinition(psiFile: PsiFile): KotlinScriptDefinition? =
|
||||
KotlinScriptDefinitionProvider.getInstance(psiFile.project).findScriptDefinition(psiFile)
|
||||
|
||||
+13
-11
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.script
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import java.io.File
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import kotlin.concurrent.read
|
||||
@@ -40,19 +41,18 @@ class KotlinScriptExternalImportsProvider(val project: Project, private val scri
|
||||
val path = getFilePath(file)
|
||||
return cache[path]
|
||||
?: if (cacheOfNulls.contains(path)) null
|
||||
else scriptDefinitionProvider.findScriptDefinition(file)
|
||||
?.let { it.getDependenciesFor(file, project, null) }
|
||||
.apply {
|
||||
log.info("[kts] new cached deps for $path: ${this?.classpath?.joinToString(File.pathSeparator)}")
|
||||
cacheLock.write {
|
||||
if (this == null) {
|
||||
cacheOfNulls.add(path)
|
||||
}
|
||||
else {
|
||||
cache.put(path, this)
|
||||
else scriptDefinitionProvider.findScriptDefinition(file)?.getDependenciesFor(file, project, null)
|
||||
.apply {
|
||||
log.info("[kts] new cached deps for $path: ${this?.classpath?.joinToString(File.pathSeparator)}")
|
||||
cacheLock.write {
|
||||
if (this == null) {
|
||||
cacheOfNulls.add(path)
|
||||
}
|
||||
else {
|
||||
cache.put(path, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// optimized for initial caching, additional handling of possible duplicates to save a call to distinct
|
||||
@@ -162,3 +162,5 @@ internal fun Iterable<File>.isSamePathListAs(other: Iterable<File>): Boolean =
|
||||
!(first.hasNext() || second.hasNext())
|
||||
}
|
||||
|
||||
fun getScriptExternalDependencies(file: VirtualFile, project: Project): KotlinScriptExternalDependencies? =
|
||||
KotlinScriptExternalImportsProvider.getInstance(project)?.getExternalImports(file)
|
||||
|
||||
@@ -1,30 +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.script
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiFile
|
||||
|
||||
fun getScriptDefinition(file: VirtualFile, project: Project): KotlinScriptDefinition? =
|
||||
KotlinScriptDefinitionProvider.getInstance(project).findScriptDefinition(file)
|
||||
|
||||
fun getScriptDefinition(psiFile: PsiFile): KotlinScriptDefinition? =
|
||||
KotlinScriptDefinitionProvider.getInstance(psiFile.project).findScriptDefinition(psiFile)
|
||||
|
||||
fun getScriptExternalDependencies(file: VirtualFile, project: Project): KotlinScriptExternalDependencies? =
|
||||
KotlinScriptExternalImportsProvider.getInstance(project)?.getExternalImports(file)
|
||||
@@ -1,172 +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.script
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtScript
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import java.io.File
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.memberFunctions
|
||||
import kotlin.reflect.primaryConstructor
|
||||
|
||||
open class KotlinScriptDefinitionFromTemplate(final override val template: KClass<out Any>,
|
||||
val resolver: ScriptDependenciesResolver? = null,
|
||||
val scriptFilePattern: String? = null,
|
||||
val environment: Map<String, Any?>? = null
|
||||
) : KotlinScriptDefinition {
|
||||
|
||||
// TODO: remove this and simplify definitionAnnotation as soon as deprecated annotations will be removed
|
||||
internal class ScriptTemplateDefinitionData(val resolverClass: KClass<out ScriptDependenciesResolver>,
|
||||
makeResolver: () -> ScriptDependenciesResolver?,
|
||||
val scriptFilePattern: String?) {
|
||||
|
||||
val resolver: ScriptDependenciesResolver? by lazy(makeResolver)
|
||||
|
||||
val acceptedAnnotations: List<KClass<out Annotation>> by lazy {
|
||||
val resolveMethod = ScriptDependenciesResolver::resolve
|
||||
val resolverMethodAnnotations =
|
||||
resolverClass.memberFunctions.find {
|
||||
it.name == resolveMethod.name &&
|
||||
sameSignature(it, resolveMethod)
|
||||
}
|
||||
?.annotations
|
||||
?.filterIsInstance<AcceptedAnnotations>()
|
||||
resolverMethodAnnotations?.flatMap {
|
||||
val v = it.supportedAnnotationClasses
|
||||
v.toList() // TODO: inline after KT-9453 is resolved (now it fails with "java.lang.Class cannot be cast to kotlin.reflect.KClass")
|
||||
}
|
||||
?: emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private val definitionData by lazy {
|
||||
val defAnn = template.annotations.firstIsInstanceOrNull<ScriptTemplateDefinition>()
|
||||
val filePattern = scriptFilePattern ?: defAnn?.scriptFilePattern ?: DEFAULT_SCRIPT_FILE_PATTERN
|
||||
when {
|
||||
resolver != null -> ScriptTemplateDefinitionData(resolver.javaClass.kotlin, { resolver }, filePattern)
|
||||
// TODO: logScriptDefMessage missing or invalid constructor
|
||||
defAnn != null -> ScriptTemplateDefinitionData(defAnn.resolver,
|
||||
{
|
||||
try {
|
||||
defAnn.resolver.primaryConstructor?.call() ?: null.apply {
|
||||
log.error("[kts] No default constructor found for ${defAnn.resolver.qualifiedName}")
|
||||
}
|
||||
}
|
||||
catch (ex: ClassCastException) {
|
||||
log.error("[kts] Script def error ${ex.message}")
|
||||
null
|
||||
}
|
||||
},
|
||||
filePattern)
|
||||
else -> ScriptTemplateDefinitionData(BasicScriptDependenciesResolver::class, ::BasicScriptDependenciesResolver, filePattern)
|
||||
}
|
||||
}
|
||||
|
||||
override val name = template.simpleName!!
|
||||
|
||||
override fun getScriptParameters(scriptDescriptor: ScriptDescriptor): List<ScriptParameter> =
|
||||
template.primaryConstructor!!.parameters.map { ScriptParameter(Name.identifier(it.name!!), getKotlinTypeByKType(scriptDescriptor, it.type)) }
|
||||
|
||||
override fun getScriptSupertypes(scriptDescriptor: ScriptDescriptor): List<KotlinType> =
|
||||
listOf(getKotlinTypeByFqName(scriptDescriptor, template.qualifiedName!!))
|
||||
|
||||
override fun getScriptParametersToPassToSuperclass(scriptDescriptor: ScriptDescriptor): List<Name> =
|
||||
getScriptParameters(scriptDescriptor).map { it.name }
|
||||
|
||||
override fun <TF> isScript(file: TF): Boolean =
|
||||
definitionData.scriptFilePattern?.let { Regex(it).matches(getFileName(file)) } ?: false
|
||||
|
||||
// TODO: implement other strategy - e.g. try to extract something from match with ScriptFilePattern
|
||||
override fun getScriptName(script: KtScript): Name = ScriptNameUtil.fileNameWithExtensionStripped(script, KotlinParserDefinition.STD_SCRIPT_EXT)
|
||||
|
||||
override fun <TF> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? {
|
||||
|
||||
val script = BasicScriptContents(file, getAnnotations = {
|
||||
val classLoader = (template as Any).javaClass.classLoader
|
||||
getAnnotationEntries(file, project)
|
||||
.mapNotNull { psiAnn ->
|
||||
// TODO: consider advanced matching using semantic similar to actual resolving
|
||||
definitionData.acceptedAnnotations.find { ann ->
|
||||
psiAnn.typeName.let { it == ann.simpleName || it == ann.qualifiedName }
|
||||
}?.let { KtAnnotationWrapper(psiAnn, classLoader.loadClass(it.qualifiedName).kotlin as KClass<out Annotation>) }
|
||||
}
|
||||
.map { it.getProxy(classLoader) }
|
||||
})
|
||||
try {
|
||||
val fileDeps = definitionData.resolver?.resolve(script, environment, ::logScriptDefMessage, previousDependencies)
|
||||
// TODO: use it as a Future
|
||||
return fileDeps?.get()
|
||||
}
|
||||
catch (ex: ClassCastException) {
|
||||
logScriptDefMessage(ScriptDependenciesResolver.ReportSeverity.ERROR, ex.message ?: "Invalid script template: ${template.qualifiedName}", null)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun <TF> getAnnotationEntries(file: TF, project: Project): Iterable<KtAnnotationEntry> = when (file) {
|
||||
is PsiFile -> getAnnotationEntriesFromPsiFile(file)
|
||||
is VirtualFile -> getAnnotationEntriesFromVirtualFile(file, project)
|
||||
is File -> {
|
||||
val virtualFile = (StandardFileSystems.local().findFileByPath(file.canonicalPath)
|
||||
?: throw IllegalArgumentException("Unable to find file ${file.canonicalPath}"))
|
||||
getAnnotationEntriesFromVirtualFile(virtualFile, project)
|
||||
}
|
||||
else -> throw IllegalArgumentException("Unsupported file type $file")
|
||||
}
|
||||
|
||||
private fun getAnnotationEntriesFromPsiFile(file: PsiFile) =
|
||||
if (file is KtFile) file.annotationEntries
|
||||
else throw IllegalArgumentException("Unable to extract kotlin annotations from ${file.name} (${file.fileType})")
|
||||
|
||||
private fun getAnnotationEntriesFromVirtualFile(file: VirtualFile, project: Project): Iterable<KtAnnotationEntry> {
|
||||
val psiFile: PsiFile = PsiManager.getInstance(project).findFile(file)
|
||||
?: throw IllegalArgumentException("Unable to load PSI from ${file.canonicalPath}")
|
||||
return getAnnotationEntriesFromPsiFile(psiFile)
|
||||
}
|
||||
|
||||
class BasicScriptContents<out TF>(myFile: TF, getAnnotations: () -> Iterable<Annotation>) : ScriptContents {
|
||||
override val file: File? by lazy { getFile(myFile) }
|
||||
override val annotations: Iterable<Annotation> by lazy { getAnnotations() }
|
||||
override val text: CharSequence? by lazy { getFileContents(myFile) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
internal val log = Logger.getInstance(KotlinScriptDefinitionFromTemplate::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun logScriptDefMessage(reportSeverity: ScriptDependenciesResolver.ReportSeverity, s: String, position: ScriptContents.Position?): Unit {
|
||||
val msg = (position?.run { "[at $line:$col]" } ?: "") + s
|
||||
when (reportSeverity) {
|
||||
ScriptDependenciesResolver.ReportSeverity.ERROR -> KotlinScriptDefinitionFromTemplate.log.error(msg)
|
||||
ScriptDependenciesResolver.ReportSeverity.WARNING -> KotlinScriptDefinitionFromTemplate.log.warn(msg)
|
||||
ScriptDependenciesResolver.ReportSeverity.INFO -> KotlinScriptDefinitionFromTemplate.log.info(msg)
|
||||
ScriptDependenciesResolver.ReportSeverity.DEBUG -> KotlinScriptDefinitionFromTemplate.log.debug(msg)
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -48,13 +48,13 @@ interface ScriptTemplatesProvider {
|
||||
|
||||
fun makeScriptDefsFromTemplatesProviderExtensions(project: Project,
|
||||
errorsHandler: ((ScriptTemplatesProvider, Exception) -> Unit) = { ep, ex -> throw ex }
|
||||
): List<KotlinScriptDefinitionFromTemplate> =
|
||||
): List<KotlinScriptDefinitionFromAnnotatedTemplate> =
|
||||
makeScriptDefsFromTemplatesProviders(Extensions.getArea(project).getExtensionPoint(ScriptTemplatesProvider.EP_NAME).extensions.asIterable(),
|
||||
errorsHandler)
|
||||
|
||||
fun makeScriptDefsFromTemplatesProviders(providers: Iterable<ScriptTemplatesProvider>,
|
||||
errorsHandler: ((ScriptTemplatesProvider, Exception) -> Unit) = { ep, ex -> throw ex }
|
||||
): List<KotlinScriptDefinitionFromTemplate> {
|
||||
): List<KotlinScriptDefinitionFromAnnotatedTemplate> {
|
||||
val idToVersion = hashMapOf<String, Int>()
|
||||
return providers.filter { it.isValid }.sortedByDescending { it.version }.flatMap { provider ->
|
||||
try {
|
||||
@@ -65,12 +65,12 @@ fun makeScriptDefsFromTemplatesProviders(providers: Iterable<ScriptTemplatesProv
|
||||
provider.templateClassNames.map {
|
||||
val cl = loader.loadClass(it)
|
||||
idToVersion.put(provider.id, provider.version)
|
||||
KotlinScriptDefinitionFromTemplate(cl.kotlin, provider.resolver, provider.filePattern, provider.environment)
|
||||
KotlinScriptDefinitionFromAnnotatedTemplate(cl.kotlin, provider.resolver, provider.filePattern, provider.environment)
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
errorsHandler(provider, ex)
|
||||
emptyList<KotlinScriptDefinitionFromTemplate>()
|
||||
emptyList<KotlinScriptDefinitionFromAnnotatedTemplate>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.script
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NotFoundClasses
|
||||
import org.jetbrains.kotlin.serialization.deserialization.findNonGenericClassAcrossDependencies
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import kotlin.reflect.*
|
||||
|
||||
data class ScriptParameter(val name: Name, val type: KotlinType)
|
||||
|
||||
fun KotlinScriptDefinition.getScriptParameters(scriptDescriptor: ScriptDescriptor): List<ScriptParameter> =
|
||||
template.primaryConstructor?.parameters
|
||||
?.map { ScriptParameter(Name.identifier(it.name!!), getKotlinTypeByKType(scriptDescriptor, it.type)) }
|
||||
?: emptyList()
|
||||
|
||||
fun getKotlinType(scriptDescriptor: ScriptDescriptor, kClass: KClass<out Any>): KotlinType =
|
||||
getKotlinTypeByFqName(scriptDescriptor,
|
||||
kClass.qualifiedName ?: throw java.lang.RuntimeException("Cannot get FQN from $kClass"))
|
||||
|
||||
fun getKotlinTypeByFqName(scriptDescriptor: ScriptDescriptor, fqName: String): KotlinType =
|
||||
scriptDescriptor.module.findNonGenericClassAcrossDependencies(
|
||||
ClassId.topLevel(FqName(fqName)),
|
||||
NotFoundClasses(LockBasedStorageManager.NO_LOCKS, scriptDescriptor.module)
|
||||
).defaultType
|
||||
|
||||
// TODO: support star projections
|
||||
// TODO: support annotations on types and type parameters
|
||||
// TODO: support type parameters on types and type projections
|
||||
fun getKotlinTypeByKType(scriptDescriptor: ScriptDescriptor, kType: KType): KotlinType {
|
||||
val classifier = kType.classifier
|
||||
if (classifier !is KClass<*>)
|
||||
throw java.lang.UnsupportedOperationException("Only classes are supported as parameters in script template: $classifier")
|
||||
|
||||
val type = getKotlinType(scriptDescriptor, classifier)
|
||||
val typeProjections = kType.arguments.map { getTypeProjection(scriptDescriptor, it) }
|
||||
val isNullable = kType.isMarkedNullable
|
||||
|
||||
return KotlinTypeFactory.simpleType(Annotations.EMPTY, type.constructor, typeProjections, isNullable)
|
||||
}
|
||||
|
||||
private fun getTypeProjection(scriptDescriptor: ScriptDescriptor, kTypeProjection: KTypeProjection): TypeProjection {
|
||||
val kType = kTypeProjection.type ?: throw java.lang.UnsupportedOperationException("Star projections are not supported")
|
||||
|
||||
val type = getKotlinTypeByKType(scriptDescriptor, kType)
|
||||
|
||||
val variance = when (kTypeProjection.variance) {
|
||||
KVariance.IN -> Variance.IN_VARIANCE
|
||||
KVariance.OUT -> Variance.OUT_VARIANCE
|
||||
KVariance.INVARIANT -> Variance.INVARIANT
|
||||
null -> throw java.lang.UnsupportedOperationException("Star projections are not supported")
|
||||
}
|
||||
|
||||
return TypeProjectionImpl(variance, type)
|
||||
}
|
||||
@@ -23,7 +23,8 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.addKotlinSourceRoots
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromTemplate
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||
import org.jetbrains.kotlin.script.ScriptTemplateDefinition
|
||||
import org.jetbrains.kotlin.scripts.ScriptWithIntParam
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
@@ -32,8 +33,8 @@ import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
|
||||
class ScriptGenTest : CodegenTestCase() {
|
||||
companion object {
|
||||
private val FIB_SCRIPT_DEFINITION = KotlinScriptDefinitionFromTemplate(ScriptWithIntParam::class, scriptFilePattern = ".*\\.lang\\.kt")
|
||||
private val NO_PARAM_SCRIPT_DEFINITION = KotlinScriptDefinitionFromTemplate(Any::class, scriptFilePattern = ".*\\.kts")
|
||||
private val FIB_SCRIPT_DEFINITION = KotlinScriptDefinitionFromAnnotatedTemplate(ScriptWithIntParam::class, providedScriptFilePattern = ".*\\.lang\\.kt")
|
||||
private val NO_PARAM_SCRIPT_DEFINITION = KotlinScriptDefinitionFromAnnotatedTemplate(Any::class, providedScriptFilePattern = ".*\\.kts")
|
||||
}
|
||||
|
||||
override fun setUp() {
|
||||
|
||||
@@ -228,7 +228,7 @@ class ScriptTemplateTest {
|
||||
runIsolated: Boolean = true,
|
||||
suppressOutput: Boolean = false,
|
||||
includeKotlinRuntime: Boolean = true): Class<*>? =
|
||||
compileScriptImpl("compiler/testData/script/" + scriptPath, KotlinScriptDefinitionFromTemplate(scriptTemplate, null, null, environment), runIsolated, suppressOutput, includeKotlinRuntime)
|
||||
compileScriptImpl("compiler/testData/script/" + scriptPath, KotlinScriptDefinitionFromAnnotatedTemplate(scriptTemplate, null, null, environment), runIsolated, suppressOutput, includeKotlinRuntime)
|
||||
|
||||
private fun compileScriptImpl(
|
||||
scriptPath: String,
|
||||
|
||||
@@ -16,12 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors;
|
||||
|
||||
import kotlin.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ScriptDescriptor extends ClassDescriptor {
|
||||
int getPriority();
|
||||
@@ -29,6 +24,4 @@ public interface ScriptDescriptor extends ClassDescriptor {
|
||||
@NotNull
|
||||
@Override
|
||||
ClassConstructorDescriptor getUnsubstitutedPrimaryConstructor();
|
||||
|
||||
List<Pair<Name, KotlinType>> getScriptParametersToPassToSuperclass();
|
||||
}
|
||||
|
||||
@@ -255,20 +255,6 @@ fun <D : CallableDescriptor> D.overriddenTreeUniqueAsSequence(useOriginal: Boole
|
||||
return doBuildOverriddenTreeAsSequence()
|
||||
}
|
||||
|
||||
fun ClassDescriptor.getConstructorByParams(params: List<KotlinType>): ConstructorDescriptor? =
|
||||
getConstructors().firstOrNull {
|
||||
when {
|
||||
it.valueParameters.isEmpty() && params.isEmpty() -> true
|
||||
it.valueParameters.size != params.size -> false
|
||||
else -> it.valueParameters.zip(params) { ctorP, p -> ctorP.type == p }.all { it }
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: inline and remove as soon as all usage sies are converted to kotlin
|
||||
fun getConstructorByParamsMap(classDescriptor: ClassDescriptor, params: List<Pair<Name, KotlinType>>): ConstructorDescriptor? =
|
||||
classDescriptor.getConstructorByParams(params.map { it.second })
|
||||
|
||||
|
||||
fun CallableDescriptor.varargParameterPosition() =
|
||||
valueParameters.indexOfFirst { it.varargElementType != null }
|
||||
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.ResolveScopeProvider
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.idea.core.script.KotlinScriptConfigurationManager
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromTemplate
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||
import org.jetbrains.kotlin.script.StandardScriptDefinition
|
||||
import org.jetbrains.kotlin.script.getScriptDefinition
|
||||
import kotlin.script.StandardScriptTemplate
|
||||
@@ -34,7 +34,7 @@ class KotlinScriptResolveScopeProvider : ResolveScopeProvider() {
|
||||
scriptDefinition == null -> null
|
||||
// This is a workaround for completion in scripts and REPL to provide module dependencies
|
||||
scriptDefinition == StandardScriptDefinition || scriptDefinition.template == Any::class -> null
|
||||
scriptDefinition is KotlinScriptDefinitionFromTemplate -> // TODO: should include the file itself
|
||||
scriptDefinition is KotlinScriptDefinitionFromAnnotatedTemplate -> // TODO: should include the file itself
|
||||
KotlinScriptConfigurationManager.getInstance(project).getAllScriptsClasspathScope()
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ import org.jetbrains.kotlin.psi.moduleInfo
|
||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor
|
||||
import org.jetbrains.kotlin.resolve.repl.ReplState
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromTemplate
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider
|
||||
import java.awt.Color
|
||||
import java.awt.Font
|
||||
@@ -124,7 +124,7 @@ class KotlinConsoleRunner(
|
||||
val executor = CommandExecutor(this)
|
||||
var compilerHelper: ConsoleCompilerHelper by Delegates.notNull()
|
||||
|
||||
private val consoleScriptDefinition = object : KotlinScriptDefinitionFromTemplate(Any::class) {
|
||||
private val consoleScriptDefinition = object : KotlinScriptDefinition(Any::class) {
|
||||
override val name = "Kotlin REPL"
|
||||
override fun <TF> isScript(file: TF): Boolean {
|
||||
val vf = when (file) {
|
||||
|
||||
+2
-2
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.addKotlinSourceRoot
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromTemplate
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
@@ -99,7 +99,7 @@ done
|
||||
environment: Map<String, Any?>? = null,
|
||||
runIsolated: Boolean = true,
|
||||
suppressOutput: Boolean = false): Class<*>? =
|
||||
compileScriptImpl("src/test/resources/scripts/" + scriptFileName, KotlinScriptDefinitionFromTemplate(scriptTemplate, null, null, environment), runIsolated, suppressOutput)
|
||||
compileScriptImpl("src/test/resources/scripts/" + scriptFileName, KotlinScriptDefinitionFromAnnotatedTemplate(scriptTemplate, null, null, environment), runIsolated, suppressOutput)
|
||||
|
||||
private fun compileScriptImpl(
|
||||
scriptPath: String,
|
||||
|
||||
Reference in New Issue
Block a user