Introduce fictitious numbered Function class descriptors
This commit is contained in:
@@ -21,6 +21,7 @@ import kotlin.*;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.functions.BuiltInFictitiousFunctionClassFactory;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
@@ -116,6 +117,7 @@ public class KotlinBuiltIns {
|
||||
PackageFragmentProvider packageFragmentProvider = BuiltinsPackage.createBuiltInPackageFragmentProvider(
|
||||
storageManager, builtInsModule,
|
||||
setOf(BUILT_INS_PACKAGE_FQ_NAME, BuiltinsPackage.getKOTLIN_REFLECT_FQ_NAME()),
|
||||
new BuiltInFictitiousFunctionClassFactory(storageManager, builtInsModule),
|
||||
new Function1<String, InputStream>() {
|
||||
@Override
|
||||
public InputStream invoke(String path) {
|
||||
|
||||
+4
-5
@@ -20,10 +20,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentProviderImpl
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
|
||||
import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeCapabilitiesDeserializer
|
||||
import org.jetbrains.kotlin.serialization.deserialization.LocalClassResolverImpl
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ResourceLoadingClassDataFinder
|
||||
import org.jetbrains.kotlin.serialization.deserialization.*
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import java.io.InputStream
|
||||
|
||||
@@ -31,6 +28,7 @@ public fun createBuiltInPackageFragmentProvider(
|
||||
storageManager: StorageManager,
|
||||
module: ModuleDescriptor,
|
||||
packageFqNames: Set<FqName>,
|
||||
classDescriptorFactory: ClassDescriptorFactory,
|
||||
loadResource: (String) -> InputStream?
|
||||
): PackageFragmentProvider {
|
||||
val packageFragments = packageFqNames.map { fqName ->
|
||||
@@ -47,7 +45,8 @@ public fun createBuiltInPackageFragmentProvider(
|
||||
BuiltInsAnnotationAndConstantLoader(module),
|
||||
provider,
|
||||
localClassResolver,
|
||||
FlexibleTypeCapabilitiesDeserializer.ThrowException
|
||||
FlexibleTypeCapabilitiesDeserializer.ThrowException,
|
||||
classDescriptorFactory
|
||||
)
|
||||
|
||||
localClassResolver.setDeserializationComponents(components)
|
||||
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.builtins.functions
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KOTLIN_REFLECT_FQ_NAME
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor.Kind
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor.Kinds
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
/**
|
||||
* Produces descriptors representing the fictitious classes for function types, such as kotlin.Function1 or kotlin.reflect.KMemberFunction0.
|
||||
*/
|
||||
public class BuiltInFictitiousFunctionClassFactory(
|
||||
private val storageManager: StorageManager,
|
||||
private val module: ModuleDescriptor
|
||||
) : ClassDescriptorFactory {
|
||||
|
||||
private data class KindWithArity(val kind: Kind, val arity: Int)
|
||||
|
||||
private fun parseClassName(className: String, allowedKinds: Set<Kind>): KindWithArity? {
|
||||
for (kind in allowedKinds) {
|
||||
val prefix = kind.classNamePrefix
|
||||
if (!className.startsWith(prefix)) continue
|
||||
|
||||
val arity = try {
|
||||
className.substring(prefix.length()).toInt()
|
||||
}
|
||||
catch (e: NumberFormatException) { continue }
|
||||
|
||||
// TODO: validate arity, should be <= 255 for functions, <= 254 for members/extensions
|
||||
return KindWithArity(kind, arity)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
override fun createClass(classId: ClassId): ClassDescriptor? {
|
||||
if (classId.isLocal() || classId.isNestedClass()) return null
|
||||
|
||||
val className = classId.getRelativeClassName().asString()
|
||||
if ("Function" !in className) return null // An optimization
|
||||
|
||||
val packageFqName = classId.getPackageFqName()
|
||||
|
||||
val allowedKinds = when (packageFqName) {
|
||||
BUILT_INS_PACKAGE_FQ_NAME -> Kinds.Functions
|
||||
KOTLIN_REFLECT_FQ_NAME -> Kinds.KFunctions
|
||||
else -> return null
|
||||
}
|
||||
|
||||
val kindWithArity = parseClassName(className, allowedKinds) ?: return null
|
||||
val (kind, arity) = kindWithArity // KT-5100
|
||||
|
||||
val containingPackageFragment = module.getPackage(packageFqName)!!.getFragments().single()
|
||||
|
||||
return FunctionClassDescriptor(storageManager, containingPackageFragment, kind, arity)
|
||||
}
|
||||
}
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.builtins.functions
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor.Kind
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.AbstractClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.StaticScopeForKotlinClass
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.utils.toReadOnlyList
|
||||
import java.util.ArrayList
|
||||
import java.util.EnumSet
|
||||
|
||||
/**
|
||||
* A [ClassDescriptor] representing the fictitious class for a function type, such as kotlin.Function1 or kotlin.reflect.KMemberFunction0.
|
||||
*
|
||||
* Classes which are represented by this descriptor include (with supertypes):
|
||||
*
|
||||
* Function1 : Function
|
||||
* KFunction1 : Function1, KFunction
|
||||
* KMemberFunction1 : Function2, KMemberFunction
|
||||
* KExtensionFunction1 : Function2, KExtensionFunction
|
||||
* (TODO) KMemberExtensionFunction1 : Function3, KMemberExtensionFunction
|
||||
*/
|
||||
public class FunctionClassDescriptor(
|
||||
private val storageManager: StorageManager,
|
||||
private val containingDeclaration: PackageFragmentDescriptor,
|
||||
val functionKind: Kind,
|
||||
val arity: Int
|
||||
) : AbstractClassDescriptor(storageManager, functionKind.numberedClassName(arity)) {
|
||||
|
||||
public enum class Kind(val classNamePrefix: String) {
|
||||
Function("Function"),
|
||||
KFunction("KFunction"),
|
||||
KMemberFunction("KMemberFunction"),
|
||||
KExtensionFunction("KExtensionFunction");
|
||||
// TODO: KMemberExtensionFunction
|
||||
|
||||
fun numberedClassName(arity: Int) = Name.identifier("$classNamePrefix$arity")
|
||||
val hasDispatchReceiver: Boolean get() = this == KMemberFunction
|
||||
val hasExtensionReceiver: Boolean get() = this == KExtensionFunction
|
||||
}
|
||||
|
||||
public object Kinds {
|
||||
val Functions = EnumSet.of(Kind.Function)
|
||||
val KFunctions = EnumSet.of(Kind.KFunction, Kind.KMemberFunction, Kind.KExtensionFunction)
|
||||
}
|
||||
|
||||
private val staticScope = StaticScopeForKotlinClass(this)
|
||||
private val typeConstructor = FunctionTypeConstructor()
|
||||
private val memberScope = FunctionClassScope(storageManager, this)
|
||||
|
||||
override fun getContainingDeclaration() = containingDeclaration
|
||||
|
||||
override fun getStaticScope() = staticScope
|
||||
|
||||
override fun getTypeConstructor(): TypeConstructor = typeConstructor
|
||||
|
||||
override fun getScopeForMemberLookup() = memberScope
|
||||
|
||||
override fun getCompanionObjectDescriptor() = null
|
||||
override fun getConstructors() = emptyList<ConstructorDescriptor>()
|
||||
override fun getKind() = ClassKind.INTERFACE
|
||||
override fun getModality() = Modality.ABSTRACT
|
||||
override fun getUnsubstitutedPrimaryConstructor() = null
|
||||
override fun getVisibility() = Visibilities.PUBLIC
|
||||
override fun isCompanionObject() = false
|
||||
override fun isInner() = false
|
||||
override fun getAnnotations() = Annotations.EMPTY
|
||||
override fun getSource() = SourceElement.NO_SOURCE
|
||||
|
||||
private inner class FunctionTypeConstructor : AbstractClassTypeConstructor() {
|
||||
private val parameters = storageManager.createLazyValue {
|
||||
val result = ArrayList<TypeParameterDescriptor>()
|
||||
|
||||
fun typeParameter(variance: Variance, name: String) {
|
||||
result.add(TypeParameterDescriptorImpl.createWithDefaultBound(
|
||||
this@FunctionClassDescriptor, Annotations.EMPTY, false, variance, Name.identifier(name), result.size()
|
||||
))
|
||||
}
|
||||
|
||||
if (functionKind.hasDispatchReceiver) {
|
||||
typeParameter(Variance.IN_VARIANCE, "T")
|
||||
}
|
||||
if (functionKind.hasExtensionReceiver) {
|
||||
typeParameter(Variance.IN_VARIANCE, "E")
|
||||
}
|
||||
|
||||
(1..arity).map { i ->
|
||||
typeParameter(Variance.IN_VARIANCE, "P$i")
|
||||
}
|
||||
|
||||
typeParameter(Variance.OUT_VARIANCE, "R")
|
||||
|
||||
result.toReadOnlyList()
|
||||
}
|
||||
|
||||
private val supertypes = storageManager.createLazyValue {
|
||||
val result = ArrayList<JetType>(2)
|
||||
|
||||
fun add(packageFragment: PackageFragmentDescriptor, name: Name, annotations: Annotations) {
|
||||
val descriptor = packageFragment.getMemberScope().getClassifier(name) as? ClassDescriptor
|
||||
?: error("Class $name not found in $packageFragment")
|
||||
|
||||
// Substitute K type parameters of the super class with our last K type parameters
|
||||
val typeConstructor = descriptor.getTypeConstructor()
|
||||
val superParameters = typeConstructor.getParameters()
|
||||
val arguments = getParameters().takeLast(superParameters.size()).map { TypeProjectionImpl(it.getDefaultType()) }
|
||||
|
||||
result.add(JetTypeImpl(annotations, typeConstructor, false, arguments, descriptor.getMemberScope(arguments)))
|
||||
}
|
||||
|
||||
// Add unnumbered base class, e.g. KMemberFunction for KMemberFunction5, or Function for Function0
|
||||
add(containingDeclaration, Name.identifier(functionKind.classNamePrefix), Annotations.EMPTY)
|
||||
|
||||
// For K*Functions, add corresponding numbered Function class, e.g. Function2 for KMemberFunction1
|
||||
if (functionKind in Kinds.KFunctions) {
|
||||
var functionArity = arity
|
||||
if (functionKind.hasDispatchReceiver) functionArity++
|
||||
if (functionKind.hasExtensionReceiver) functionArity++
|
||||
|
||||
val module = containingDeclaration.getContainingDeclaration()
|
||||
val kotlinPackageFragment = module.getPackage(BUILT_INS_PACKAGE_FQ_NAME)!!.getFragments().single()
|
||||
add(kotlinPackageFragment, Kind.Function.numberedClassName(functionArity), Annotations.EMPTY)
|
||||
}
|
||||
|
||||
result.toReadOnlyList()
|
||||
}
|
||||
|
||||
override fun getParameters() = parameters()
|
||||
|
||||
override fun getSupertypes(): Collection<JetType> = supertypes()
|
||||
|
||||
override fun getDeclarationDescriptor() = this@FunctionClassDescriptor
|
||||
override fun isDenotable() = true
|
||||
override fun isFinal() = false
|
||||
override fun getAnnotations() = Annotations.EMPTY
|
||||
|
||||
override fun toString() = getDeclarationDescriptor().toString()
|
||||
}
|
||||
|
||||
override fun toString() = getName().asString()
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.builtins.functions
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScopeImpl
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import org.jetbrains.kotlin.utils.toReadOnlyList
|
||||
import java.util.ArrayList
|
||||
|
||||
class FunctionClassScope(
|
||||
private val storageManager: StorageManager,
|
||||
private val functionClass: FunctionClassDescriptor
|
||||
) : JetScopeImpl() {
|
||||
private val allFunctions = storageManager.createLazyValue {
|
||||
if (functionClass.functionKind == FunctionClassDescriptor.Kind.Function) {
|
||||
val invoke = FunctionInvokeDescriptor.create(functionClass)
|
||||
(listOf(invoke) + createFakeOverrides(invoke)).toReadOnlyList()
|
||||
}
|
||||
else {
|
||||
createFakeOverrides(null).toReadOnlyList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getContainingDeclaration() = functionClass
|
||||
|
||||
override fun getDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
|
||||
if (!kindFilter.acceptsKinds(DescriptorKindFilter.FUNCTIONS_MASK)) return listOf()
|
||||
return allFunctions()
|
||||
}
|
||||
|
||||
override fun getFunctions(name: Name): Collection<FunctionDescriptor> {
|
||||
return allFunctions().filter { it.getName() == name }
|
||||
}
|
||||
|
||||
private fun createFakeOverrides(invoke: FunctionDescriptor?): List<FunctionDescriptor> {
|
||||
val result = ArrayList<FunctionDescriptor>(3)
|
||||
val allSuperDescriptors = functionClass.getTypeConstructor().getSupertypes().flatMap { it.getMemberScope().getAllDescriptors() }
|
||||
for ((name, descriptors) in allSuperDescriptors.groupBy { it.getName() }) {
|
||||
@suppress("UNCHECKED_CAST")
|
||||
OverridingUtil.generateOverridesInFunctionGroup(
|
||||
name,
|
||||
/* membersFromSupertypes = */ descriptors as Collection<FunctionDescriptor>,
|
||||
/* membersFromCurrent = */ if (name == invoke?.getName()) listOf(invoke) else listOf(),
|
||||
functionClass,
|
||||
object : OverridingUtil.DescriptorSink {
|
||||
override fun addToScope(fakeOverride: CallableMemberDescriptor) {
|
||||
OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, null)
|
||||
result.add(fakeOverride as FunctionDescriptor)
|
||||
}
|
||||
|
||||
override fun conflict(fromSuper: CallableMemberDescriptor, fromCurrent: CallableMemberDescriptor) {
|
||||
error("Conflict in scope of ${getContainingDeclaration()}: $fromSuper vs $fromCurrent")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
override fun printScopeStructure(p: Printer) {
|
||||
p.println("Scope of function class $functionClass")
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.builtins.functions
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
// TODO: make parameter names synthetic / non-stable
|
||||
public class FunctionInvokeDescriptor private constructor(
|
||||
private val container: DeclarationDescriptor,
|
||||
private val original: FunctionInvokeDescriptor?,
|
||||
private val callableKind: CallableMemberDescriptor.Kind
|
||||
) : SimpleFunctionDescriptorImpl(
|
||||
container,
|
||||
original,
|
||||
Annotations.EMPTY,
|
||||
Name.identifier("invoke"),
|
||||
callableKind,
|
||||
SourceElement.NO_SOURCE
|
||||
) {
|
||||
override fun createSubstitutedCopy(
|
||||
newOwner: DeclarationDescriptor,
|
||||
original: FunctionDescriptor?,
|
||||
kind: CallableMemberDescriptor.Kind
|
||||
): FunctionInvokeDescriptor {
|
||||
return FunctionInvokeDescriptor(newOwner, original as FunctionInvokeDescriptor?, kind)
|
||||
}
|
||||
|
||||
companion object Factory {
|
||||
fun create(functionClass: FunctionClassDescriptor): FunctionInvokeDescriptor {
|
||||
val typeParameters = functionClass.getTypeConstructor().getParameters()
|
||||
|
||||
val result = FunctionInvokeDescriptor(functionClass, null, CallableMemberDescriptor.Kind.DECLARATION)
|
||||
result.initialize(
|
||||
null,
|
||||
functionClass.getThisAsReceiverParameter(),
|
||||
listOf(),
|
||||
typeParameters.takeWhile { it.getVariance() == Variance.IN_VARIANCE }
|
||||
.withIndex()
|
||||
.map { createValueParameter(result, it.index, it.value) },
|
||||
typeParameters.last().getDefaultType(),
|
||||
Modality.ABSTRACT,
|
||||
Visibilities.PUBLIC
|
||||
)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun createValueParameter(
|
||||
containingDeclaration: FunctionInvokeDescriptor,
|
||||
index: Int,
|
||||
typeParameter: TypeParameterDescriptor
|
||||
): ValueParameterDescriptor {
|
||||
val typeParameterName = typeParameter.getName().asString()
|
||||
val name = when (typeParameterName) {
|
||||
"T" -> "instance"
|
||||
"E" -> "receiver"
|
||||
else -> {
|
||||
// Type parameter "P1" -> value parameter "p1", "P2" -> "p2", etc.
|
||||
typeParameterName.toLowerCase()
|
||||
}
|
||||
}
|
||||
|
||||
return ValueParameterDescriptorImpl(
|
||||
containingDeclaration, null, index,
|
||||
Annotations.EMPTY,
|
||||
Name.identifier(name),
|
||||
typeParameter.getDefaultType(),
|
||||
/* declaresDefaultValue = */ false,
|
||||
/* varargElementType = */ null,
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user