Introduce fictitious numbered Function class descriptors

This commit is contained in:
Alexander Udalov
2015-04-16 17:58:18 +03:00
parent 27ed098467
commit 4141e0a8df
32 changed files with 807 additions and 70 deletions
@@ -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) {
@@ -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)
@@ -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)
}
}
@@ -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")
}
}
@@ -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
)
}
}
}