Implement support for additional receivers for script in frontend

This commit is contained in:
Ilya Chernikov
2018-03-07 11:23:08 +01:00
parent e79d3dd035
commit 87de1dff03
3 changed files with 47 additions and 1 deletions
@@ -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))
@@ -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<out Any>) : UserDataHolde
open val scriptExpectedLocations: List<ScriptExpectedLocation> =
listOf(ScriptExpectedLocation.SourcesOnly, ScriptExpectedLocation.TestsOnly)
open val implicitReceivers: List<KType> get() = emptyList()
}
object StandardScriptDefinition : KotlinScriptDefinition(ScriptTemplateWithArgs::class)
@@ -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<KType> by lazy {
runBlocking {
scriptDefinition.configurator.baseConfiguration(null)
}.resultOrNull()?.getOrNull(ScriptCompileConfigurationParams.scriptSignature)?.providedDeclarations?.implicitReceivers
?: emptyList()
}
}