diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/WrappedDescriptors.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/WrappedDescriptors.kt index 40d28553d01..17d07f4982e 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/WrappedDescriptors.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/WrappedDescriptors.kt @@ -724,7 +724,7 @@ open class WrappedScriptDescriptor : ScriptDescriptor, WrappedDeclarationDescrip } override fun getDefaultFunctionTypeForSamInterface(): SimpleType? { - TODO("not implemented") + TODO("not yet implemented") } override fun isDefinitelyNotSamInterface(): Boolean { @@ -735,6 +735,18 @@ open class WrappedScriptDescriptor : ScriptDescriptor, WrappedDeclarationDescrip TODO("Not yet implemented") } + override fun getExplicitConstructorParameters(): MutableList { + TODO("Not yet implemented") + } + + override fun getImplicitReceiversParameters(): MutableList { + TODO("Not yet implemented") + } + + override fun getScriptProvidedPropertiesParameters(): MutableList { + TODO("Not yet implemented") + } + override fun getImplicitReceivers(): MutableList { TODO("Not yet implemented") } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ScriptDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ScriptDescriptor.java index bd1cbdca035..aedaf8722de 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ScriptDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ScriptDescriptor.java @@ -36,4 +36,13 @@ public interface ScriptDescriptor extends ClassDescriptor { @Nullable PropertyDescriptor getResultValue(); + + @NotNull + List getExplicitConstructorParameters(); + + @NotNull + List getImplicitReceiversParameters(); + + @NotNull + List getScriptProvidedPropertiesParameters(); } diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptClassMemberScope.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptClassMemberScope.kt index 61d942dd83c..fc9521cbb47 100644 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptClassMemberScope.kt +++ b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptClassMemberScope.kt @@ -5,18 +5,13 @@ package org.jetbrains.kotlin.scripting.resolve -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor 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.resolve.lazy.descriptors.LazyClassMemberScope -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.KotlinTypeFactory -import org.jetbrains.kotlin.types.typeUtil.asTypeProjection class LazyScriptClassMemberScope( resolveSession: ResolveSession, @@ -28,65 +23,17 @@ class LazyScriptClassMemberScope( private val _variableNames: MutableSet by lazy(LazyThreadSafetyMode.PUBLICATION) { super.getVariableNames().apply { + scriptDescriptor.scriptProvidedProperties.forEach { + add(it.name) + } scriptDescriptor.resultFieldName()?.let { add(it) } } } - private val scriptPrimaryConstructor: () -> ClassConstructorDescriptorImpl? = resolveSession.storageManager.createNullableLazyValue { - val baseClass = scriptDescriptor.baseClassDescriptor() - val baseConstructorDescriptor = baseClass?.unsubstitutedPrimaryConstructor - if (baseConstructorDescriptor != null) { - val implicitReceiversParamTypes = - scriptDescriptor.implicitReceivers.mapIndexed { idx, receiver -> - val name = - if (receiver is ScriptDescriptor) "$IMPORTED_SCRIPT_PARAM_NAME_PREFIX${receiver.name}" - else "$IMPLICIT_RECEIVER_PARAM_NAME_PREFIX$idx" - name to receiver.defaultType - } - val providedPropertiesParamTypes = - scriptDescriptor.scriptProvidedProperties.map { - it.name.identifier to it.type - } - val annotations = baseConstructorDescriptor.annotations - val constructorDescriptor = ClassConstructorDescriptorImpl.create( - scriptDescriptor, annotations, baseConstructorDescriptor.isPrimary, scriptDescriptor.source - ) - var paramsIndexBase = baseConstructorDescriptor.valueParameters.lastIndex + 1 - val syntheticParameters = - (implicitReceiversParamTypes + providedPropertiesParamTypes).map { param: Pair -> - ValueParameterDescriptorImpl( - constructorDescriptor, - null, - paramsIndexBase++, - Annotations.EMPTY, - Name.identifier(param.first), - param.second, - false, false, false, null, SourceElement.NO_SOURCE - ) - } - val parameters = baseConstructorDescriptor.valueParameters.map { it.copy(constructorDescriptor, it.name, it.index) } + - syntheticParameters - constructorDescriptor.initialize(parameters, baseConstructorDescriptor.visibility) - constructorDescriptor.returnType = scriptDescriptor.defaultType - constructorDescriptor - } else { - null - } - } - - override fun resolvePrimaryConstructor(): ClassConstructorDescriptor? { - val constructor = scriptPrimaryConstructor() - ?: ClassConstructorDescriptorImpl.create( - scriptDescriptor, - Annotations.EMPTY, - true, - SourceElement.NO_SOURCE - ).initialize( - emptyList(), - DescriptorVisibilities.PUBLIC - ) + override fun resolvePrimaryConstructor(): ClassConstructorDescriptor { + val constructor = scriptDescriptor.scriptPrimaryConstructorWithParams().constructor setDeferredReturnType(constructor) return constructor } @@ -100,6 +47,7 @@ class LazyScriptClassMemberScope( result.add(it) } } + scriptDescriptor.scriptProvidedProperties.forEach { if (it.name == name) result.add(it) } } override fun createPropertiesFromPrimaryConstructorParameters(name: Name, result: MutableSet) { @@ -111,5 +59,3 @@ class LazyScriptClassMemberScope( } } -private fun ClassDescriptor.substitute(vararg types: KotlinType): KotlinType? = - KotlinTypeFactory.simpleType(this.defaultType, arguments = types.map { it.asTypeProjection() }) diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptDescriptor.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptDescriptor.kt index 2427bf9e60b..a463288fea9 100644 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptDescriptor.kt +++ b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptDescriptor.kt @@ -7,11 +7,14 @@ package org.jetbrains.kotlin.scripting.resolve import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.openapi.vfs.VirtualFileManager +import com.intellij.openapi.vfs.VirtualFileSystem import com.intellij.psi.PsiElement import com.intellij.psi.PsiManager import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations +import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1 import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors.MISSING_IMPORTED_SCRIPT_FILE @@ -53,6 +56,7 @@ import kotlin.script.experimental.host.GetScriptingClass import kotlin.script.experimental.host.ScriptingHostConfiguration import kotlin.script.experimental.host.getScriptingClass import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration +import kotlin.script.experimental.jvm.util.toValidJvmIdentifier class LazyScriptDescriptor( @@ -179,11 +183,11 @@ class LazyScriptDescriptor( private inner class ImportedScriptDescriptorsFinder { - val localFS by lazy { + val localFS: VirtualFileSystem by lazy(LazyThreadSafetyMode.PUBLICATION) { val fileManager = VirtualFileManager.getInstance() fileManager.getFileSystem(StandardFileSystems.FILE_PROTOCOL) } - val psiManager by lazy { PsiManager.getInstance(scriptInfo.script.project) } + val psiManager by lazy(LazyThreadSafetyMode.PUBLICATION) { PsiManager.getInstance(scriptInfo.script.project) } operator fun invoke(importedScript: SourceCode): ScriptDescriptor? { // Note: is not an error now - if import references other valid source file, it is simply compiled along with script @@ -264,22 +268,93 @@ class LazyScriptDescriptor( override fun getImplicitReceivers(): List = scriptImplicitReceivers() - private val scriptProvidedProperties: () -> ScriptProvidedPropertiesDescriptor = resolveSession.storageManager.createLazyValue { - ScriptProvidedPropertiesDescriptor(this) + private val scriptProvidedProperties: () -> List = resolveSession.storageManager.createLazyValue { + scriptCompilationConfiguration()[ScriptCompilationConfiguration.providedProperties].orEmpty() + .mapNotNull { (name, type) -> + findTypeDescriptor(getScriptingClass(type), Errors.MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS) + ?.let { name.toValidJvmIdentifier() to it } + }.map { (name, classDescriptor) -> + ScriptProvidedPropertyDescriptor( + Name.identifier(name), + classDescriptor, + thisAsReceiverParameter, + true, + this + ) + } } - override fun getScriptProvidedProperties(): List = scriptProvidedProperties().properties() + override fun getScriptProvidedProperties(): List = scriptProvidedProperties() + + internal class ConstructorWithParams( + val constructor: ClassConstructorDescriptorImpl, + val explicitConstructorParameters: List, + val implicitReceiversParameters: List, + val scriptProvidedPropertiesParameters: List + ) + + internal val scriptPrimaryConstructorWithParams: () -> ConstructorWithParams = resolveSession.storageManager.createLazyValue { + val baseConstructorDescriptor = baseClassDescriptor()?.unsubstitutedPrimaryConstructor + val inheritedAnnotations = baseConstructorDescriptor?.annotations ?: Annotations.EMPTY + val baseExplicitParameters = baseConstructorDescriptor?.valueParameters ?: emptyList() + + val implicitReceiversParamTypes = + implicitReceivers.mapIndexed { idx, receiver -> + val receiverName = + if (receiver is ScriptDescriptor) "${LazyScriptClassMemberScope.IMPORTED_SCRIPT_PARAM_NAME_PREFIX}${receiver.name}" + else "${LazyScriptClassMemberScope.IMPLICIT_RECEIVER_PARAM_NAME_PREFIX}$idx" + receiverName to receiver.defaultType + } + + val providedPropertiesParamTypes = + scriptProvidedProperties().map { + it.name.identifier to it.type + } + val constructorDescriptor = ClassConstructorDescriptorImpl.create(this, inheritedAnnotations, true, source) + + var paramsIndexBase = baseExplicitParameters.lastIndex + 1 + + fun createValueParameter(param: Pair) = + ValueParameterDescriptorImpl( + constructorDescriptor, + null, + paramsIndexBase++, + Annotations.EMPTY, + Name.identifier(param.first), + param.second, + declaresDefaultValue = false, isCrossinline = false, isNoinline = false, varargElementType = null, + source = SourceElement.NO_SOURCE + ) + + val explicitParameters = baseExplicitParameters.map { it.copy(constructorDescriptor, it.name, it.index) } + val implicitReceiversParameters = implicitReceiversParamTypes.map(::createValueParameter) + val providedPropertiesParameters = providedPropertiesParamTypes.map(::createValueParameter) + + constructorDescriptor.initialize( + explicitParameters + implicitReceiversParameters + providedPropertiesParameters, DescriptorVisibilities.PUBLIC + ) + constructorDescriptor.returnType = defaultType() + + ConstructorWithParams( + constructorDescriptor, + explicitConstructorParameters = explicitParameters, + implicitReceiversParameters = implicitReceiversParameters, + scriptProvidedPropertiesParameters = providedPropertiesParameters + ) + } + + override fun getExplicitConstructorParameters(): List = + scriptPrimaryConstructorWithParams().explicitConstructorParameters + + override fun getImplicitReceiversParameters(): List = + scriptPrimaryConstructorWithParams().implicitReceiversParameters + + override fun getScriptProvidedPropertiesParameters(): List = + scriptPrimaryConstructorWithParams().scriptProvidedPropertiesParameters private val scriptOuterScope: () -> LexicalScope = resolveSession.storageManager.createLazyValue { var outerScope = super.getOuterScope() - val outerScopeReceivers = implicitReceivers.let { - if (scriptCompilationConfiguration()[ScriptCompilationConfiguration.providedProperties]?.isNotEmpty() == true) { - it + ScriptProvidedPropertiesDescriptor(this) - } else { - it - } - } - for (receiverClassDescriptor in outerScopeReceivers.asReversed()) { + for (receiverClassDescriptor in implicitReceivers.asReversed()) { outerScope = LexicalScopeImpl( outerScope, receiverClassDescriptor, diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/ScriptProvidedPropertiesDescriptor.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/ScriptProvidedPropertiesDescriptor.kt deleted file mode 100644 index 8f1d7167a93..00000000000 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/ScriptProvidedPropertiesDescriptor.kt +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.scripting.resolve - -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.impl.MutableClassDescriptor -import org.jetbrains.kotlin.diagnostics.Errors -import org.jetbrains.kotlin.incremental.components.LookupLocation -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter -import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl -import org.jetbrains.kotlin.storage.LockBasedStorageManager -import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner -import org.jetbrains.kotlin.utils.Printer -import kotlin.script.experimental.api.ScriptCompilationConfiguration -import kotlin.script.experimental.api.providedProperties -import kotlin.script.experimental.jvm.util.toValidJvmIdentifier - -class ScriptProvidedPropertiesDescriptor(script: LazyScriptDescriptor) : - MutableClassDescriptor( - script, - ClassKind.CLASS, false, false, - Name.special(""), - SourceElement.NO_SOURCE, - LockBasedStorageManager.NO_LOCKS - ) { - - init { - modality = Modality.FINAL - visibility = DescriptorVisibilities.PUBLIC - setTypeParameterDescriptors(emptyList()) - createTypeConstructor() - } - - private val memberScope: () -> ScriptProvidedPropertiesMemberScope = script.resolveSession.storageManager.createLazyValue { - ScriptProvidedPropertiesMemberScope( - script.name.identifier, - properties() - ) - } - - override fun getUnsubstitutedMemberScope(kotlinTypeRefiner: KotlinTypeRefiner): MemberScope = memberScope() - - val properties: () -> List = script.resolveSession.storageManager.createLazyValue { - script.scriptCompilationConfiguration()[ScriptCompilationConfiguration.providedProperties].orEmpty().mapNotNull { (name, type) -> - script.findTypeDescriptor(script.getScriptingClass(type), Errors.MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS) - ?.let { name.toValidJvmIdentifier() to it } - }.map { (name, classDescriptor) -> - ScriptProvidedPropertyDescriptor( - Name.identifier(name), - classDescriptor, - thisAsReceiverParameter, - true, - script - ) - } - } - - private class ScriptProvidedPropertiesMemberScope( - private val scriptId: String, - private val providedProperties: List - ) : MemberScopeImpl() { - override fun getContributedDescriptors( - kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean - ): Collection = - providedProperties - - override fun getContributedVariables(name: Name, location: LookupLocation): Collection = - providedProperties.filter { it.name == name } - - override fun printScopeStructure(p: Printer) { - p.println("Scope of script provided properties: $scriptId") - } - } -}