Create proper constructor in script descriptor
allows to resolve calls to scripts in compiler (but not in the IDE yet) Some refactorings on the way
This commit is contained in:
@@ -75,9 +75,7 @@ class ScriptCodegen private constructor(
|
|||||||
|
|
||||||
val jvmSignature = typeMapper.mapScriptSignature(
|
val jvmSignature = typeMapper.mapScriptSignature(
|
||||||
scriptDescriptor,
|
scriptDescriptor,
|
||||||
scriptContext.earlierScripts,
|
scriptContext.earlierScripts
|
||||||
scriptDefinition.implicitReceivers,
|
|
||||||
scriptDefinition.environmentVariables
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (state.replSpecific.shouldGenerateScriptResultValue) {
|
if (state.replSpecific.shouldGenerateScriptResultValue) {
|
||||||
@@ -104,37 +102,6 @@ class ScriptCodegen private constructor(
|
|||||||
val superclass = scriptDescriptor.getSuperClassNotAny()
|
val superclass = scriptDescriptor.getSuperClassNotAny()
|
||||||
// TODO: throw if class is not found)
|
// TODO: throw if class is not found)
|
||||||
|
|
||||||
if (superclass == null) {
|
|
||||||
iv.load(0, classType)
|
|
||||||
iv.invokespecial("java/lang/Object", "<init>", "()V", false)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
val ctorDesc = superclass.unsubstitutedPrimaryConstructor
|
|
||||||
?: throw RuntimeException("Primary constructor not found for script template " + superclass.toString())
|
|
||||||
|
|
||||||
iv.load(0, classType)
|
|
||||||
|
|
||||||
fun Int.incrementIf(cond: Boolean): Int = if (cond) plus(1) else this
|
|
||||||
val valueParamStart = 1
|
|
||||||
.incrementIf(scriptContext.earlierScripts.isNotEmpty())
|
|
||||||
.incrementIf(scriptDefinition.implicitReceivers.isNotEmpty())
|
|
||||||
.incrementIf(scriptDefinition.environmentVariables.isNotEmpty())
|
|
||||||
|
|
||||||
val valueParameters = scriptDescriptor.unsubstitutedPrimaryConstructor.valueParameters
|
|
||||||
for (superclassParam in ctorDesc.valueParameters) {
|
|
||||||
val valueParam = valueParameters.first { it.name == superclassParam.name }
|
|
||||||
iv.load(valueParam!!.index + valueParamStart, typeMapper.mapType(valueParam.type))
|
|
||||||
}
|
|
||||||
|
|
||||||
val ctorMethod = typeMapper.mapToCallableMethod(ctorDesc, false)
|
|
||||||
val sig = ctorMethod.getAsmMethod().descriptor
|
|
||||||
|
|
||||||
iv.invokespecial(
|
|
||||||
typeMapper.mapSupertype(superclass.defaultType, null).internalName,
|
|
||||||
"<init>", sig, false)
|
|
||||||
}
|
|
||||||
iv.load(0, classType)
|
|
||||||
|
|
||||||
val frameMap = FrameMap()
|
val frameMap = FrameMap()
|
||||||
frameMap.enterTemp(OBJECT_TYPE)
|
frameMap.enterTemp(OBJECT_TYPE)
|
||||||
|
|
||||||
@@ -157,6 +124,37 @@ class ScriptCodegen private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (superclass == null) {
|
||||||
|
iv.load(0, classType)
|
||||||
|
iv.invokespecial("java/lang/Object", "<init>", "()V", false)
|
||||||
|
} else {
|
||||||
|
val ctorDesc = superclass.unsubstitutedPrimaryConstructor
|
||||||
|
?: throw RuntimeException("Primary constructor not found for script template " + superclass.toString())
|
||||||
|
|
||||||
|
iv.load(0, classType)
|
||||||
|
|
||||||
|
fun Int.incrementIf(cond: Boolean): Int = if (cond) plus(1) else this
|
||||||
|
val valueParamStart = 1
|
||||||
|
.incrementIf(scriptContext.earlierScripts.isNotEmpty())
|
||||||
|
|
||||||
|
val valueParameters = scriptDescriptor.unsubstitutedPrimaryConstructor.valueParameters
|
||||||
|
for (superclassParam in ctorDesc.valueParameters) {
|
||||||
|
val valueParam = valueParameters.first { it.name == superclassParam.name }
|
||||||
|
val paramType = typeMapper.mapType(valueParam.type)
|
||||||
|
iv.load(valueParam!!.index + valueParamStart, paramType)
|
||||||
|
frameMap.enterTemp(paramType)
|
||||||
|
}
|
||||||
|
|
||||||
|
val ctorMethod = typeMapper.mapToCallableMethod(ctorDesc, false)
|
||||||
|
val sig = ctorMethod.getAsmMethod().descriptor
|
||||||
|
|
||||||
|
iv.invokespecial(
|
||||||
|
typeMapper.mapSupertype(superclass.defaultType, null).internalName,
|
||||||
|
"<init>", sig, false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
iv.load(0, classType)
|
||||||
|
|
||||||
if (scriptDefinition.implicitReceivers.isNotEmpty()) {
|
if (scriptDefinition.implicitReceivers.isNotEmpty()) {
|
||||||
val receiversParamIndex = frameMap.enterTemp(AsmUtil.getArrayType(OBJECT_TYPE))
|
val receiversParamIndex = frameMap.enterTemp(AsmUtil.getArrayType(OBJECT_TYPE))
|
||||||
|
|
||||||
|
|||||||
@@ -1607,9 +1607,7 @@ public class KotlinTypeMapper {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public JvmMethodSignature mapScriptSignature(
|
public JvmMethodSignature mapScriptSignature(
|
||||||
@NotNull ScriptDescriptor script,
|
@NotNull ScriptDescriptor script,
|
||||||
@NotNull List<ScriptDescriptor> importedScripts,
|
@NotNull List<ScriptDescriptor> importedScripts
|
||||||
List<? extends KType> implicitReceivers,
|
|
||||||
List<? extends Pair<String, ? extends KType>> environmentVariables
|
|
||||||
) {
|
) {
|
||||||
JvmSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
|
JvmSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
|
||||||
|
|
||||||
@@ -1619,14 +1617,6 @@ public class KotlinTypeMapper {
|
|||||||
writeParameter(sw, DescriptorUtilsKt.getModule(script).getBuiltIns().getArray().getDefaultType(), null);
|
writeParameter(sw, DescriptorUtilsKt.getModule(script).getBuiltIns().getArray().getDefaultType(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (implicitReceivers.size() > 0) {
|
|
||||||
writeParameter(sw, DescriptorUtilsKt.getModule(script).getBuiltIns().getArray().getDefaultType(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (environmentVariables.size() > 0) {
|
|
||||||
writeParameter(sw, DescriptorUtilsKt.getModule(script).getBuiltIns().getMap().getDefaultType(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ValueParameterDescriptor valueParameter : script.getUnsubstitutedPrimaryConstructor().getValueParameters()) {
|
for (ValueParameterDescriptor valueParameter : script.getUnsubstitutedPrimaryConstructor().getValueParameters()) {
|
||||||
writeParameter(sw, valueParameter.getType(), /* callableDescriptor = */ null);
|
writeParameter(sw, valueParameter.getType(), /* callableDescriptor = */ null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.script
|
package org.jetbrains.kotlin.script
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.NotFoundClasses
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.findNonGenericClassAcrossDependencies
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.classId
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
@@ -33,19 +31,27 @@ import kotlin.reflect.KVariance
|
|||||||
import kotlin.reflect.full.primaryConstructor
|
import kotlin.reflect.full.primaryConstructor
|
||||||
|
|
||||||
fun KotlinScriptDefinition.getScriptParameters(scriptDescriptor: ScriptDescriptor): List<ScriptParameter> =
|
fun KotlinScriptDefinition.getScriptParameters(scriptDescriptor: ScriptDescriptor): List<ScriptParameter> =
|
||||||
template.primaryConstructor?.parameters
|
template.primaryConstructor?.parameters
|
||||||
?.map { ScriptParameter(Name.identifier(it.name!!), getKotlinTypeByKType(scriptDescriptor, it.type)) }
|
?.map { ScriptParameter(Name.identifier(it.name!!), getKotlinTypeByKType(scriptDescriptor, it.type)) }
|
||||||
?: emptyList()
|
?: emptyList()
|
||||||
|
|
||||||
fun getKotlinTypeByKClass(scriptDescriptor: ScriptDescriptor, kClass: KClass<out Any>): KotlinType =
|
fun getKotlinTypeByKClass(scriptDescriptor: ScriptDescriptor, kClass: KClass<out Any>): KotlinType =
|
||||||
getKotlinTypeByFqName(scriptDescriptor,
|
getClassDescriptorByKClassOrMock(scriptDescriptor, kClass).defaultType
|
||||||
kClass.qualifiedName ?: throw RuntimeException("Cannot get FQN from $kClass"))
|
|
||||||
|
|
||||||
private fun getKotlinTypeByFqName(scriptDescriptor: ScriptDescriptor, fqName: String): KotlinType =
|
fun getClassDescriptorByKClass(scriptDescriptor: ScriptDescriptor, kClass: KClass<out Any>): ClassDescriptor? =
|
||||||
scriptDescriptor.module.findNonGenericClassAcrossDependencies(
|
scriptDescriptor.module.findClassAcrossModuleDependencies(kClass.classId)
|
||||||
ClassId.topLevel(FqName(fqName)),
|
|
||||||
NotFoundClasses(LockBasedStorageManager.NO_LOCKS, scriptDescriptor.module)
|
fun getMockClassDescriptor(scriptDescriptor: ScriptDescriptor, kClass: KClass<out Any>): ClassDescriptor {
|
||||||
).defaultType
|
val classId = kClass.classId
|
||||||
|
val typeParametersCount = generateSequence(classId, ClassId::getOuterClassId).map { 0 }.toList()
|
||||||
|
return NotFoundClasses(LockBasedStorageManager.NO_LOCKS, scriptDescriptor.module).getClass(classId, typeParametersCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getClassDescriptorByKClassOrMock(scriptDescriptor: ScriptDescriptor, kClass: KClass<out Any>): ClassDescriptor =
|
||||||
|
scriptDescriptor.module.findNonGenericClassAcrossDependencies(
|
||||||
|
kClass.classId,
|
||||||
|
NotFoundClasses(LockBasedStorageManager.NO_LOCKS, scriptDescriptor.module)
|
||||||
|
)
|
||||||
|
|
||||||
// TODO: support star projections
|
// TODO: support star projections
|
||||||
// TODO: support annotations on types and type parameters
|
// TODO: support annotations on types and type parameters
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ public interface Errors {
|
|||||||
DiagnosticFactory2<PsiElement, String, String> API_NOT_AVAILABLE = DiagnosticFactory2.create(ERROR);
|
DiagnosticFactory2<PsiElement, String, String> API_NOT_AVAILABLE = DiagnosticFactory2.create(ERROR);
|
||||||
|
|
||||||
DiagnosticFactory1<PsiElement, FqName> MISSING_DEPENDENCY_CLASS = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, FqName> MISSING_DEPENDENCY_CLASS = DiagnosticFactory1.create(ERROR);
|
||||||
|
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_BASE_CLASS = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_RECEIVER_CLASS = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_RECEIVER_CLASS = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_ENVIRONMENT_PROPERTY_CLASS = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_ENVIRONMENT_PROPERTY_CLASS = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory1<PsiElement, String> PRE_RELEASE_CLASS = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, String> PRE_RELEASE_CLASS = DiagnosticFactory1.create(ERROR);
|
||||||
|
|||||||
+1
@@ -357,6 +357,7 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(API_NOT_AVAILABLE, "This declaration is only available since Kotlin {0} and cannot be used with the specified API version {1}", STRING, STRING);
|
MAP.put(API_NOT_AVAILABLE, "This declaration is only available since Kotlin {0} and cannot be used with the specified API version {1}", STRING, STRING);
|
||||||
|
|
||||||
MAP.put(MISSING_DEPENDENCY_CLASS, "Cannot access class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
|
MAP.put(MISSING_DEPENDENCY_CLASS, "Cannot access class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
|
||||||
|
MAP.put(MISSING_SCRIPT_BASE_CLASS, "Cannot access script base class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
|
||||||
MAP.put(MISSING_SCRIPT_RECEIVER_CLASS, "Cannot access implicit script receiver class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
|
MAP.put(MISSING_SCRIPT_RECEIVER_CLASS, "Cannot access implicit script receiver class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
|
||||||
MAP.put(MISSING_SCRIPT_ENVIRONMENT_PROPERTY_CLASS, "Cannot access script environment property class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
|
MAP.put(MISSING_SCRIPT_ENVIRONMENT_PROPERTY_CLASS, "Cannot access script environment property class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
|
||||||
MAP.put(PRE_RELEASE_CLASS, "{0} is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler", TO_STRING);
|
MAP.put(PRE_RELEASE_CLASS, "{0} is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler", TO_STRING);
|
||||||
|
|||||||
+59
-24
@@ -22,9 +22,11 @@ import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
|
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
|
||||||
import org.jetbrains.kotlin.script.ScriptHelper
|
import org.jetbrains.kotlin.types.*
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||||
|
|
||||||
class LazyScriptClassMemberScope(
|
class LazyScriptClassMemberScope(
|
||||||
resolveSession: ResolveSession,
|
resolveSession: ResolveSession,
|
||||||
@@ -33,34 +35,67 @@ class LazyScriptClassMemberScope(
|
|||||||
trace: BindingTrace
|
trace: BindingTrace
|
||||||
) : LazyClassMemberScope(resolveSession, declarationProvider, scriptDescriptor, trace) {
|
) : LazyClassMemberScope(resolveSession, declarationProvider, scriptDescriptor, trace) {
|
||||||
|
|
||||||
override fun resolvePrimaryConstructor(): ClassConstructorDescriptor? {
|
private val scriptPrimaryConstructor: () -> ClassConstructorDescriptorImpl? = resolveSession.storageManager.createNullableLazyValue {
|
||||||
val constructor = ClassConstructorDescriptorImpl.create(
|
val baseClass = scriptDescriptor.baseClassDescriptor()
|
||||||
scriptDescriptor,
|
val baseConstructorDescriptor = baseClass?.unsubstitutedPrimaryConstructor
|
||||||
Annotations.EMPTY,
|
if (baseConstructorDescriptor != null) {
|
||||||
true,
|
val builtIns = scriptDescriptor.builtIns
|
||||||
SourceElement.NO_SOURCE
|
val implicitReceiversParamType =
|
||||||
)
|
if (scriptDescriptor.scriptDefinition().implicitReceivers.isEmpty()) null
|
||||||
constructor.initialize(
|
else {
|
||||||
createScriptParameters(constructor),
|
"implicitReceivers" to builtIns.array.substitute(builtIns.anyType)!!
|
||||||
Visibilities.PUBLIC
|
}
|
||||||
)
|
val environmentVarsParamType =
|
||||||
setDeferredReturnType(constructor)
|
if (scriptDescriptor.scriptDefinition().environmentVariables.isEmpty()) null
|
||||||
return constructor
|
else {
|
||||||
|
"environmentVariables" to builtIns.map.substitute(builtIns.stringType, builtIns.nullableAnyType)!!
|
||||||
|
}
|
||||||
|
val annotations = baseConstructorDescriptor.annotations
|
||||||
|
val constructorDescriptor = ClassConstructorDescriptorImpl.create(
|
||||||
|
scriptDescriptor, annotations, baseConstructorDescriptor.isPrimary, scriptDescriptor.source
|
||||||
|
)
|
||||||
|
var paramsIndexBase = baseConstructorDescriptor.valueParameters.let { if (it.isEmpty()) 0 else it.last().index + 1 }
|
||||||
|
val syntheticParameters =
|
||||||
|
listOf(implicitReceiversParamType, environmentVarsParamType).mapNotNull { param: Pair<String, KotlinType>? ->
|
||||||
|
if (param == null) null
|
||||||
|
else 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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createScriptParameters(constructor: ClassConstructorDescriptorImpl): List<ValueParameterDescriptor> {
|
override fun resolvePrimaryConstructor(): ClassConstructorDescriptor? {
|
||||||
return ScriptHelper.getInstance().getScriptParameters(scriptDescriptor.scriptDefinition, scriptDescriptor)
|
val constructor = scriptPrimaryConstructor()
|
||||||
.mapIndexed { index, (name, type) ->
|
?: ClassConstructorDescriptorImpl.create(
|
||||||
ValueParameterDescriptorImpl(
|
scriptDescriptor,
|
||||||
constructor, null, index, Annotations.EMPTY, name, type,
|
Annotations.EMPTY,
|
||||||
/* declaresDefaultValue = */ false,
|
true,
|
||||||
/* isCrossinline = */ false,
|
SourceElement.NO_SOURCE
|
||||||
/* isNoinline = */ false,
|
).initialize(
|
||||||
null, SourceElement.NO_SOURCE
|
emptyList(),
|
||||||
|
Visibilities.PUBLIC
|
||||||
)
|
)
|
||||||
}
|
setDeferredReturnType(constructor)
|
||||||
|
return constructor
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createPropertiesFromPrimaryConstructorParameters(name: Name, result: MutableSet<PropertyDescriptor>) {
|
override fun createPropertiesFromPrimaryConstructorParameters(name: Name, result: MutableSet<PropertyDescriptor>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ClassDescriptor.substitute(vararg types: KotlinType): KotlinType? =
|
||||||
|
KotlinTypeFactory.simpleType(this.defaultType, arguments = types.map { it.asTypeProjection() })
|
||||||
|
|||||||
+29
-27
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
@@ -31,14 +30,15 @@ import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
|||||||
import org.jetbrains.kotlin.resolve.lazy.data.KtScriptInfo
|
import org.jetbrains.kotlin.resolve.lazy.data.KtScriptInfo
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
|
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
|
||||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.ScriptEnvironmentDescriptor
|
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.ScriptEnvironmentDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.scopes.*
|
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.classId
|
||||||
|
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.resolve.source.toSourceElement
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
import org.jetbrains.kotlin.script.ScriptHelper
|
|
||||||
import org.jetbrains.kotlin.script.ScriptPriorities
|
import org.jetbrains.kotlin.script.ScriptPriorities
|
||||||
import org.jetbrains.kotlin.script.getScriptDefinition
|
import org.jetbrains.kotlin.script.getScriptDefinition
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
import org.jetbrains.kotlin.utils.ifEmpty
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
|
|
||||||
@@ -66,11 +66,10 @@ class LazyScriptDescriptor(
|
|||||||
|
|
||||||
override fun getPriority() = priority
|
override fun getPriority() = priority
|
||||||
|
|
||||||
val scriptDefinition: KotlinScriptDefinition
|
val scriptDefinition: () -> KotlinScriptDefinition = resolveSession.storageManager.createLazyValue {
|
||||||
by lazy {
|
val file = scriptInfo.script.containingKtFile
|
||||||
val file = scriptInfo.script.containingKtFile
|
getScriptDefinition(file) ?: throw RuntimeException("file ${file.name} is not a script")
|
||||||
getScriptDefinition(file) ?: throw RuntimeException("file ${file.name} is not a script")
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun substitute(substitutor: TypeSubstitutor) = this
|
override fun substitute(substitutor: TypeSubstitutor) = this
|
||||||
|
|
||||||
@@ -88,28 +87,39 @@ class LazyScriptDescriptor(
|
|||||||
|
|
||||||
override fun getUnsubstitutedPrimaryConstructor() = super.getUnsubstitutedPrimaryConstructor()!!
|
override fun getUnsubstitutedPrimaryConstructor() = super.getUnsubstitutedPrimaryConstructor()!!
|
||||||
|
|
||||||
override fun computeSupertypes() =
|
internal val baseClassDescriptor: () -> ClassDescriptor? = resolveSession.storageManager.createNullableLazyValue {
|
||||||
listOf(ScriptHelper.getInstance().getKotlinType(this, scriptDefinition.template)).ifEmpty { listOf(builtIns.anyType) }
|
findTypeDescriptor(scriptDefinition().template, Errors.MISSING_SCRIPT_BASE_CLASS)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun computeSupertypes() = listOf(baseClassDescriptor()?.defaultType ?: builtIns.anyType)
|
||||||
|
|
||||||
private val scriptImplicitReceivers: () -> List<ClassDescriptor> = resolveSession.storageManager.createLazyValue {
|
private val scriptImplicitReceivers: () -> List<ClassDescriptor> = resolveSession.storageManager.createLazyValue {
|
||||||
scriptDefinition.implicitReceivers.mapNotNull { receiver ->
|
scriptDefinition().implicitReceivers.mapNotNull { receiver ->
|
||||||
findTypeDescriptor(receiver, Errors.MISSING_SCRIPT_RECEIVER_CLASS)
|
findTypeDescriptor(receiver, Errors.MISSING_SCRIPT_RECEIVER_CLASS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun findTypeDescriptor(type: KType, errorDiagnostic: DiagnosticFactory1<PsiElement, String>): ClassDescriptor? {
|
internal fun findTypeDescriptor(kClass: KClass<*>, errorDiagnostic: DiagnosticFactory1<PsiElement, String>): ClassDescriptor? =
|
||||||
val receiverClassId = type.classId
|
findTypeDescriptor(kClass.classId, kClass.toString(), errorDiagnostic)
|
||||||
return receiverClassId?.let {
|
|
||||||
module.findClassAcrossModuleDependencies(it)
|
internal fun findTypeDescriptor(type: KType, errorDiagnostic: DiagnosticFactory1<PsiElement, String>): ClassDescriptor? =
|
||||||
} ?: also {
|
findTypeDescriptor(type.classId, type.toString(), errorDiagnostic)
|
||||||
|
|
||||||
|
internal fun findTypeDescriptor(
|
||||||
|
classId: ClassId?, typeName: String,
|
||||||
|
errorDiagnostic: DiagnosticFactory1<PsiElement, String>
|
||||||
|
): ClassDescriptor? {
|
||||||
|
val typeDescriptor = classId?.let { module.findClassAcrossModuleDependencies(it) }
|
||||||
|
if (typeDescriptor == null) {
|
||||||
// TODO: use PositioningStrategies to highlight some specific place in case of error, instead of treating the whole file as invalid
|
// TODO: use PositioningStrategies to highlight some specific place in case of error, instead of treating the whole file as invalid
|
||||||
resolveSession.trace.report(
|
resolveSession.trace.report(
|
||||||
errorDiagnostic.on(
|
errorDiagnostic.on(
|
||||||
scriptInfo.script,
|
scriptInfo.script,
|
||||||
receiverClassId?.asSingleFqName()?.toString() ?: type.toString()
|
classId?.asSingleFqName()?.toString() ?: typeName
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
return typeDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getImplicitReceivers(): List<ClassDescriptor> = scriptImplicitReceivers()
|
override fun getImplicitReceivers(): List<ClassDescriptor> = scriptImplicitReceivers()
|
||||||
@@ -123,7 +133,7 @@ class LazyScriptDescriptor(
|
|||||||
private val scriptOuterScope: () -> LexicalScope = resolveSession.storageManager.createLazyValue {
|
private val scriptOuterScope: () -> LexicalScope = resolveSession.storageManager.createLazyValue {
|
||||||
var outerScope = super.getOuterScope()
|
var outerScope = super.getOuterScope()
|
||||||
val outerScopeReceivers = implicitReceivers.let {
|
val outerScopeReceivers = implicitReceivers.let {
|
||||||
if (scriptDefinition.environmentVariables.isEmpty()) {
|
if (scriptDefinition().environmentVariables.isEmpty()) {
|
||||||
it
|
it
|
||||||
} else {
|
} else {
|
||||||
it + ScriptEnvironmentDescriptor(this)
|
it + ScriptEnvironmentDescriptor(this)
|
||||||
@@ -143,11 +153,3 @@ class LazyScriptDescriptor(
|
|||||||
|
|
||||||
override fun getOuterScope(): LexicalScope = scriptOuterScope()
|
override fun getOuterScope(): LexicalScope = scriptOuterScope()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val KClass<*>.classId: ClassId
|
|
||||||
get() = this.java.enclosingClass?.kotlin?.classId?.createNestedClassId(Name.identifier(simpleName!!))
|
|
||||||
?: ClassId.topLevel(FqName(qualifiedName!!))
|
|
||||||
|
|
||||||
private val KType.classId: ClassId?
|
|
||||||
get() = classifier?.let { it as? KClass<*> }?.classId
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ class ScriptEnvironmentDescriptor(script: LazyScriptDescriptor) :
|
|||||||
override fun getUnsubstitutedMemberScope(): MemberScope = memberScope()
|
override fun getUnsubstitutedMemberScope(): MemberScope = memberScope()
|
||||||
|
|
||||||
val properties: () -> List<ScriptEnvironmentPropertyDescriptor> = script.resolveSession.storageManager.createLazyValue {
|
val properties: () -> List<ScriptEnvironmentPropertyDescriptor> = script.resolveSession.storageManager.createLazyValue {
|
||||||
script.scriptDefinition.environmentVariables.mapNotNull { (name, type) ->
|
script.scriptDefinition().environmentVariables.mapNotNull { (name, type) ->
|
||||||
script.findTypeDescriptor(type, Errors.MISSING_SCRIPT_ENVIRONMENT_PROPERTY_CLASS)?.let {
|
script.findTypeDescriptor(type, Errors.MISSING_SCRIPT_ENVIRONMENT_PROPERTY_CLASS)?.let {
|
||||||
name to it
|
name to it
|
||||||
}
|
}
|
||||||
|
|||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.resolve.lazy.descriptors.script
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
|
||||||
|
val KClass<*>.classId: ClassId
|
||||||
|
get() = this.java.enclosingClass?.kotlin?.classId?.createNestedClassId(Name.identifier(simpleName!!))
|
||||||
|
?: ClassId.topLevel(FqName(qualifiedName!!))
|
||||||
|
|
||||||
|
val KType.classId: ClassId?
|
||||||
|
get() = classifier?.let { it as? KClass<*> }?.classId
|
||||||
@@ -84,7 +84,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
|
|||||||
|
|
||||||
override fun getPresentableName() = KOTLIN_BUILDER_NAME
|
override fun getPresentableName() = KOTLIN_BUILDER_NAME
|
||||||
|
|
||||||
override fun getCompilableFileExtensions() = arrayListOf("kt")
|
override fun getCompilableFileExtensions() = arrayListOf("kt", "kts")
|
||||||
|
|
||||||
override fun buildStarted(context: CompileContext) {
|
override fun buildStarted(context: CompileContext) {
|
||||||
LOG.debug("==========================================")
|
LOG.debug("==========================================")
|
||||||
|
|||||||
Reference in New Issue
Block a user