From fe69185cd4c5e77537df5edec7485444893739b2 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Tue, 20 Sep 2016 23:34:14 +0200 Subject: [PATCH] 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 --- .../kotlin/codegen/ScriptCodegen.java | 14 +- .../jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt | 4 +- .../kotlin/cli/jvm/repl/GenericRepl.kt | 8 +- .../kotlin/cli/jvm/repl/ReplInterpreter.kt | 4 +- .../kotlin/daemon/KotlinRemoteReplService.kt | 4 +- .../org/jetbrains/kotlin/psi/KtScript.java | 5 +- .../descriptors/LazyScriptClassMemberScope.kt | 1 + .../lazy/descriptors/LazyScriptDescriptor.kt | 13 +- .../kotlin/script/KotlinScriptDefinition.kt | 83 +-------- ...inScriptDefinitionFromAnnotatedTemplate.kt | 154 ++++++++++++++++ .../script/KotlinScriptDefinitionProvider.kt | 6 + .../KotlinScriptExternalImportsProvider.kt | 24 +-- .../kotlin/script/getScriptDefinition.kt | 30 --- ...Template.kt => scriptAnnotatedTemplate.kt} | 0 .../script/scriptDefinitionFromTemplate.kt | 172 ------------------ .../scriptTemplateProviderExtensionPoint.kt | 8 +- .../jetbrains/kotlin/script/scriptTypeUtil.kt | 76 ++++++++ .../jetbrains/kotlin/codegen/ScriptGenTest.kt | 7 +- .../kotlin/scripts/ScriptTemplateTest.kt | 2 +- .../kotlin/descriptors/ScriptDescriptor.java | 7 - .../kotlin/resolve/DescriptorUtils.kt | 14 -- .../KotlinScriptResolveScopeProvider.kt | 4 +- .../kotlin/console/KotlinConsoleRunner.kt | 4 +- .../kotlin/script/util/ScriptUtilIT.kt | 4 +- 24 files changed, 290 insertions(+), 358 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionFromAnnotatedTemplate.kt delete mode 100644 compiler/frontend/src/org/jetbrains/kotlin/script/getScriptDefinition.kt rename compiler/frontend/src/org/jetbrains/kotlin/script/{scriptTemplate.kt => scriptAnnotatedTemplate.kt} (100%) delete mode 100644 compiler/frontend/src/org/jetbrains/kotlin/script/scriptDefinitionFromTemplate.kt create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/script/scriptTypeUtil.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java index 4ff153a469d..a00e37ba4a4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java @@ -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 { iv.invokespecial("java/lang/Object", "", "()V", false); } else { - List> superclassParamsMap = scriptDescriptor.getScriptParametersToPassToSuperclass(); - ConstructorDescriptor ctorDesc = DescriptorUtilsKt.getConstructorByParamsMap(superclass, superclassParamsMap); + // TODO: check if it is correct way to find a promary constructor + Collection ctorDescriptors = superclass.getConstructors(); + assert ctorDescriptors.size() == 1; + ConstructorDescriptor ctorDesc = ctorDescriptors.iterator().next(); assert ctorDesc != null; iv.load(0, classType); List valueParameters = scriptDescriptor.getUnsubstitutedPrimaryConstructor().getValueParameters(); - for (Pair 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; } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt index f561cb8958c..8d608dadee1 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt @@ -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() { 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, diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericRepl.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericRepl.kt index b71381fa0e7..b89cad5ee4b 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericRepl.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericRepl.kt @@ -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(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 = emptyList() - } - protected var lineState: LineState? = null fun createDiagnosticHolder() = ReplTerminalDiagnosticMessageHolder() diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.kt index cdd43c8e371..73aa65656ca 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.kt @@ -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" } diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/KotlinRemoteReplService.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/KotlinRemoteReplService.kt index b1e617314cc..7a122b55b01 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/KotlinRemoteReplService.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/KotlinRemoteReplService.kt @@ -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}", diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtScript.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtScript.java index cc3060741e9..16159437b6c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtScript.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtScript.java @@ -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 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(); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyScriptClassMemberScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyScriptClassMemberScope.kt index 5f1d791394c..7ad3ef52d1e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyScriptClassMemberScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyScriptClassMemberScope.kt @@ -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, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyScriptDescriptor.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyScriptDescriptor.kt index 1b704d5e8e6..15db4a7e5ea 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyScriptDescriptor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyScriptDescriptor.kt @@ -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> { - 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) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinition.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinition.kt index 9b5e5a9e852..2f1981f46d4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinition.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinition.kt @@ -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) { - val template: KClass + 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 isScript(file: TF): Boolean = + open fun isScript(file: TF): Boolean = getFileName(file).endsWith(KotlinParserDefinition.STD_SCRIPT_EXT) - // TODO: replace these 3 functions with template property - fun getScriptParameters(scriptDescriptor: ScriptDescriptor): List - fun getScriptSupertypes(scriptDescriptor: ScriptDescriptor): List = emptyList() - fun getScriptParametersToPassToSuperclass(scriptDescriptor: ScriptDescriptor): List = emptyList() - - fun getScriptName(script: KtScript): Name = + open fun getScriptName(script: KtScript): Name = ScriptNameUtil.fileNameWithExtensionStripped(script, KotlinParserDefinition.STD_SCRIPT_EXT) - fun getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? = null + open fun getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? = null } interface KotlinScriptExternalDependencies { @@ -70,54 +50,5 @@ interface KotlinScriptExternalDependencies { val scripts: Iterable get() = emptyList() } -class KotlinScriptExternalDependenciesUnion(val dependencies: Iterable) : KotlinScriptExternalDependencies { - override val javaHome: String? get() = dependencies.firstOrNull { it.javaHome != null }?.javaHome - override val classpath: Iterable get() = dependencies.flatMap { it.classpath } - override val imports: Iterable get() = dependencies.flatMap { it.imports } - override val sources: Iterable get() = dependencies.flatMap { it.sources } - override val scripts: Iterable 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): 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) -} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionFromAnnotatedTemplate.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionFromAnnotatedTemplate.kt new file mode 100644 index 00000000000..185749cdd50 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionFromAnnotatedTemplate.kt @@ -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, + providedResolver: ScriptDependenciesResolver? = null, + providedScriptFilePattern: String? = null, + val environment: Map? = null +) : KotlinScriptDefinition(template) { + + val scriptFilePattern by lazy { + providedScriptFilePattern ?: template.annotations.firstIsInstanceOrNull()?.scriptFilePattern ?: DEFAULT_SCRIPT_FILE_PATTERN + } + + val resolver: ScriptDependenciesResolver? by lazy { + val defAnn by lazy { template.annotations.firstIsInstanceOrNull() } + 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> by lazy { + val resolveMethod = ScriptDependenciesResolver::resolve + val resolverMethodAnnotations = + resolver::class.memberFunctions.find { + it.name == resolveMethod.name && + sameSignature(it, resolveMethod) + } + ?.annotations + ?.filterIsInstance() + 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 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 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) } + } + .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 getAnnotationEntries(file: TF, project: Project): Iterable = 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 { + val psiFile: PsiFile = PsiManager.getInstance(project).findFile(file) + ?: throw IllegalArgumentException("Unable to load PSI from ${file.canonicalPath}") + return getAnnotationEntriesFromPsiFile(psiFile) + } + + class BasicScriptContents(myFile: TF, getAnnotations: () -> Iterable) : ScriptContents { + override val file: File? by lazy { getFile(myFile) } + override val annotations: Iterable 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) + } +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionProvider.kt index d20c2e4b664..7d9402c07a4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionProvider.kt @@ -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) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptExternalImportsProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptExternalImportsProvider.kt index d21946a1f35..e90b81c2344 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptExternalImportsProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptExternalImportsProvider.kt @@ -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.isSamePathListAs(other: Iterable): Boolean = !(first.hasNext() || second.hasNext()) } +fun getScriptExternalDependencies(file: VirtualFile, project: Project): KotlinScriptExternalDependencies? = + KotlinScriptExternalImportsProvider.getInstance(project)?.getExternalImports(file) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/getScriptDefinition.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/getScriptDefinition.kt deleted file mode 100644 index 93526199ec1..00000000000 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/getScriptDefinition.kt +++ /dev/null @@ -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) \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTemplate.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/scriptAnnotatedTemplate.kt similarity index 100% rename from compiler/frontend/src/org/jetbrains/kotlin/script/scriptTemplate.kt rename to compiler/frontend/src/org/jetbrains/kotlin/script/scriptAnnotatedTemplate.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/scriptDefinitionFromTemplate.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/scriptDefinitionFromTemplate.kt deleted file mode 100644 index aea796fcfff..00000000000 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/scriptDefinitionFromTemplate.kt +++ /dev/null @@ -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, - val resolver: ScriptDependenciesResolver? = null, - val scriptFilePattern: String? = null, - val environment: Map? = null -) : KotlinScriptDefinition { - - // TODO: remove this and simplify definitionAnnotation as soon as deprecated annotations will be removed - internal class ScriptTemplateDefinitionData(val resolverClass: KClass, - makeResolver: () -> ScriptDependenciesResolver?, - val scriptFilePattern: String?) { - - val resolver: ScriptDependenciesResolver? by lazy(makeResolver) - - val acceptedAnnotations: List> by lazy { - val resolveMethod = ScriptDependenciesResolver::resolve - val resolverMethodAnnotations = - resolverClass.memberFunctions.find { - it.name == resolveMethod.name && - sameSignature(it, resolveMethod) - } - ?.annotations - ?.filterIsInstance() - 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() - 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 = - template.primaryConstructor!!.parameters.map { ScriptParameter(Name.identifier(it.name!!), getKotlinTypeByKType(scriptDescriptor, it.type)) } - - override fun getScriptSupertypes(scriptDescriptor: ScriptDescriptor): List = - listOf(getKotlinTypeByFqName(scriptDescriptor, template.qualifiedName!!)) - - override fun getScriptParametersToPassToSuperclass(scriptDescriptor: ScriptDescriptor): List = - getScriptParameters(scriptDescriptor).map { it.name } - - override fun 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 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) } - } - .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 getAnnotationEntries(file: TF, project: Project): Iterable = 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 { - val psiFile: PsiFile = PsiManager.getInstance(project).findFile(file) - ?: throw IllegalArgumentException("Unable to load PSI from ${file.canonicalPath}") - return getAnnotationEntriesFromPsiFile(psiFile) - } - - class BasicScriptContents(myFile: TF, getAnnotations: () -> Iterable) : ScriptContents { - override val file: File? by lazy { getFile(myFile) } - override val annotations: Iterable 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) - } -} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTemplateProviderExtensionPoint.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTemplateProviderExtensionPoint.kt index 663d82292ad..2aaf6a9e71b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTemplateProviderExtensionPoint.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTemplateProviderExtensionPoint.kt @@ -48,13 +48,13 @@ interface ScriptTemplatesProvider { fun makeScriptDefsFromTemplatesProviderExtensions(project: Project, errorsHandler: ((ScriptTemplatesProvider, Exception) -> Unit) = { ep, ex -> throw ex } -): List = +): List = makeScriptDefsFromTemplatesProviders(Extensions.getArea(project).getExtensionPoint(ScriptTemplatesProvider.EP_NAME).extensions.asIterable(), errorsHandler) fun makeScriptDefsFromTemplatesProviders(providers: Iterable, errorsHandler: ((ScriptTemplatesProvider, Exception) -> Unit) = { ep, ex -> throw ex } -): List { +): List { val idToVersion = hashMapOf() return providers.filter { it.isValid }.sortedByDescending { it.version }.flatMap { provider -> try { @@ -65,12 +65,12 @@ fun makeScriptDefsFromTemplatesProviders(providers: Iterable() + emptyList() } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTypeUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTypeUtil.kt new file mode 100644 index 00000000000..0a22a9536b8 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTypeUtil.kt @@ -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 = + template.primaryConstructor?.parameters + ?.map { ScriptParameter(Name.identifier(it.name!!), getKotlinTypeByKType(scriptDescriptor, it.type)) } + ?: emptyList() + +fun getKotlinType(scriptDescriptor: ScriptDescriptor, kClass: KClass): 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) +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ScriptGenTest.kt b/compiler/tests/org/jetbrains/kotlin/codegen/ScriptGenTest.kt index 5a8adc307e7..62b5f0bd369 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ScriptGenTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ScriptGenTest.kt @@ -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() { diff --git a/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTemplateTest.kt b/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTemplateTest.kt index fafa846ff7a..ab680feeb2f 100644 --- a/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTemplateTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTemplateTest.kt @@ -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, diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ScriptDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ScriptDescriptor.java index 1a914717df9..50b67113134 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ScriptDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ScriptDescriptor.java @@ -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> getScriptParametersToPassToSuperclass(); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt index d4e88233769..1b01651377e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt @@ -255,20 +255,6 @@ fun D.overriddenTreeUniqueAsSequence(useOriginal: Boole return doBuildOverriddenTreeAsSequence() } -fun ClassDescriptor.getConstructorByParams(params: List): 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>): ConstructorDescriptor? = - classDescriptor.getConstructorByParams(params.map { it.second }) - - fun CallableDescriptor.varargParameterPosition() = valueParameters.indexOfFirst { it.varargElementType != null } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/KotlinScriptResolveScopeProvider.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/KotlinScriptResolveScopeProvider.kt index d9ecd6fce7c..a7e86659f03 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/KotlinScriptResolveScopeProvider.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/KotlinScriptResolveScopeProvider.kt @@ -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 } diff --git a/idea/idea-repl/src/org/jetbrains/kotlin/console/KotlinConsoleRunner.kt b/idea/idea-repl/src/org/jetbrains/kotlin/console/KotlinConsoleRunner.kt index 41c26abc91d..7b42006c354 100644 --- a/idea/idea-repl/src/org/jetbrains/kotlin/console/KotlinConsoleRunner.kt +++ b/idea/idea-repl/src/org/jetbrains/kotlin/console/KotlinConsoleRunner.kt @@ -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 isScript(file: TF): Boolean { val vf = when (file) { diff --git a/libraries/tools/kotlin-script-util/src/test/kotlin/org/jetbrains/kotlin/script/util/ScriptUtilIT.kt b/libraries/tools/kotlin-script-util/src/test/kotlin/org/jetbrains/kotlin/script/util/ScriptUtilIT.kt index 188b455d5b2..f43265dbc60 100644 --- a/libraries/tools/kotlin-script-util/src/test/kotlin/org/jetbrains/kotlin/script/util/ScriptUtilIT.kt +++ b/libraries/tools/kotlin-script-util/src/test/kotlin/org/jetbrains/kotlin/script/util/ScriptUtilIT.kt @@ -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? = 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,