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 110619ad131..3a73ed2878c 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 @@ -19,13 +19,21 @@ package org.jetbrains.kotlin.resolve.lazy.descriptors import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptorVisitor import org.jetbrains.kotlin.descriptors.ScriptDescriptor +import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies +import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.lazy.LazyClassContext import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.lazy.data.KtScriptInfo import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider +import org.jetbrains.kotlin.resolve.scopes.LexicalScope +import org.jetbrains.kotlin.resolve.scopes.LexicalScopeImpl +import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind import org.jetbrains.kotlin.resolve.source.toSourceElement import org.jetbrains.kotlin.script.KotlinScriptDefinition import org.jetbrains.kotlin.script.ScriptHelper @@ -33,9 +41,10 @@ import org.jetbrains.kotlin.script.ScriptPriorities import org.jetbrains.kotlin.script.getScriptDefinition import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.utils.ifEmpty +import kotlin.reflect.KClass class LazyScriptDescriptor( - resolveSession: ResolveSession, + val resolveSession: ResolveSession, containingDeclaration: DeclarationDescriptor, name: Name, internal val scriptInfo: KtScriptInfo @@ -82,4 +91,30 @@ class LazyScriptDescriptor( override fun computeSupertypes() = listOf(ScriptHelper.getInstance().getKotlinType(this, scriptDefinition.template)).ifEmpty { listOf(builtIns.anyType) } + + private val scriptOuterScope: () -> LexicalScope = resolveSession.storageManager.createLazyValue { + val receivers = scriptDefinition.implicitReceivers + var outerScope = super.getOuterScope() + for (receiver in receivers.asReversed()) { + val receiverClassId = receiver.classifier?.let { it as? KClass<*> }?.java?.classId + val receiverClassDescriptor = receiverClassId?.let { module.findClassAcrossModuleDependencies(it) } + if (receiverClassDescriptor == null) { + resolveSession.trace.report(Errors.MISSING_DEPENDENCY_CLASS.on(scriptInfo.script, receiverClassId?.asSingleFqName() ?: FqName(receiver.toString()))) + break + } + outerScope = LexicalScopeImpl( + outerScope, + receiverClassDescriptor, + true, + receiverClassDescriptor.thisAsReceiverParameter, + LexicalScopeKind.CLASS_MEMBER_SCOPE + ) + } + outerScope + } + + override fun getOuterScope(): LexicalScope = scriptOuterScope() } + +private val Class<*>.classId: ClassId + get() = enclosingClass?.classId?.createNestedClassId(Name.identifier(simpleName)) ?: ClassId.topLevel(FqName(name)) diff --git a/compiler/psi/src/org/jetbrains/kotlin/script/KotlinScriptDefinition.kt b/compiler/psi/src/org/jetbrains/kotlin/script/KotlinScriptDefinition.kt index 1476efa3425..f5f84ab3ced 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/script/KotlinScriptDefinition.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/script/KotlinScriptDefinition.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.name.NameUtils import org.jetbrains.kotlin.parsing.KotlinParserDefinition import org.jetbrains.kotlin.psi.KtScript import kotlin.reflect.KClass +import kotlin.reflect.KType import kotlin.script.experimental.dependencies.DependenciesResolver import kotlin.script.experimental.location.ScriptExpectedLocation import kotlin.script.templates.standard.ScriptTemplateWithArgs @@ -53,6 +54,8 @@ open class KotlinScriptDefinition(val template: KClass) : UserDataHolde open val scriptExpectedLocations: List = listOf(ScriptExpectedLocation.SourcesOnly, ScriptExpectedLocation.TestsOnly) + + open val implicitReceivers: List get() = emptyList() } object StandardScriptDefinition : KotlinScriptDefinition(ScriptTemplateWithArgs::class) diff --git a/plugins/scripting/scripting-cli/src/org/jetbrains/kotlin/scripting/compiler/plugin/KotlinScriptDefinitionAdapterFromNewAPI.kt b/plugins/scripting/scripting-cli/src/org/jetbrains/kotlin/scripting/compiler/plugin/KotlinScriptDefinitionAdapterFromNewAPI.kt index cf031617536..b2be4901852 100644 --- a/plugins/scripting/scripting-cli/src/org/jetbrains/kotlin/scripting/compiler/plugin/KotlinScriptDefinitionAdapterFromNewAPI.kt +++ b/plugins/scripting/scripting-cli/src/org/jetbrains/kotlin/scripting/compiler/plugin/KotlinScriptDefinitionAdapterFromNewAPI.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.name.NameUtils import org.jetbrains.kotlin.psi.KtScript import org.jetbrains.kotlin.script.KotlinScriptDefinition import kotlin.reflect.KClass +import kotlin.reflect.KType import kotlin.script.experimental.api.ScriptCompileConfigurationParams import kotlin.script.experimental.api.ScriptDefinition import kotlin.script.experimental.api.resultOrNull @@ -47,6 +48,13 @@ class KotlinScriptDefinitionAdapterFromNewAPI(val scriptDefinition: ScriptDefini }.resultOrNull()?.getOrNull(ScriptCompileConfigurationParams.updateConfigurationOnAnnotations)?.toList() ?: emptyList() } + + override val implicitReceivers: List by lazy { + runBlocking { + scriptDefinition.configurator.baseConfiguration(null) + }.resultOrNull()?.getOrNull(ScriptCompileConfigurationParams.scriptSignature)?.providedDeclarations?.implicitReceivers + ?: emptyList() + } }