Minor, extract fakeDescriptorsForReferences.kt

This commit is contained in:
Alexander Udalov
2017-06-01 17:10:44 +03:00
parent 9e98c11114
commit 66ea288be7
3 changed files with 46 additions and 26 deletions
@@ -229,9 +229,10 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
@Override
protected void generateKotlinMetadataAnnotation() {
FunctionDescriptor frontendFunDescriptor = CodegenUtilKt.unwrapFrontendVersion(funDescriptor);
FunctionDescriptor freeLambdaDescriptor = createFreeLambdaDescriptor(frontendFunDescriptor);
Method method = v.getSerializationBindings().get(METHOD_FOR_FUNCTION, frontendFunDescriptor);
assert method != null : "No method for " + frontendFunDescriptor;
FunctionDescriptor freeLambdaDescriptor = FakeDescriptorsForReferencesKt.createFreeFakeLambdaDescriptor(frontendFunDescriptor);
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, freeLambdaDescriptor, method);
DescriptorSerializer serializer =
@@ -245,30 +246,6 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
});
}
/**
* Given a function descriptor, creates another function descriptor with type parameters copied from outer context(s).
* This is needed because once we're serializing this to a proto, there's no place to store information about external type parameters.
*/
@NotNull
public static FunctionDescriptor createFreeLambdaDescriptor(@NotNull FunctionDescriptor descriptor) {
FunctionDescriptor.CopyBuilder<? extends FunctionDescriptor> builder = descriptor.newCopyBuilder();
List<TypeParameterDescriptor> typeParameters = new ArrayList<>(0);
builder.setTypeParameters(typeParameters);
DeclarationDescriptor container = descriptor.getContainingDeclaration();
while (container != null) {
if (container instanceof ClassDescriptor) {
typeParameters.addAll(((ClassDescriptor) container).getDeclaredTypeParameters());
}
else if (container instanceof CallableDescriptor && !(container instanceof ConstructorDescriptor)) {
typeParameters.addAll(((CallableDescriptor) container).getTypeParameters());
}
container = container.getContainingDeclaration();
}
return typeParameters.isEmpty() ? descriptor : builder.build();
}
@Override
protected void done() {
writeOuterClassAndEnclosingMethod();
@@ -479,7 +479,7 @@ class CoroutineCodegenForNamedFunction private constructor(
override fun generateKotlinMetadataAnnotation() {
writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0) { av ->
val serializer = DescriptorSerializer.createForLambda(JvmSerializerExtension(v.serializationBindings, state))
val functionProto = serializer.functionProto(createFreeLambdaDescriptor(suspendFunctionJvmView)).build()
val functionProto = serializer.functionProto(createFreeFakeLambdaDescriptor(suspendFunctionJvmView)).build()
AsmUtil.writeAnnotationData(av, serializer, functionProto)
}
}
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2017 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.codegen
import org.jetbrains.kotlin.descriptors.*
import java.util.ArrayList
/**
* Given a function descriptor, creates another function descriptor with type parameters copied from outer context(s).
* This is needed because once we're serializing this to a proto, there's no place to store information about external type parameters.
*/
fun createFreeFakeLambdaDescriptor(descriptor: FunctionDescriptor): FunctionDescriptor {
val builder = descriptor.newCopyBuilder()
val typeParameters = ArrayList<TypeParameterDescriptor>(0)
builder.setTypeParameters(typeParameters)
var container: DeclarationDescriptor? = descriptor.containingDeclaration
while (container != null) {
if (container is ClassDescriptor) {
typeParameters.addAll(container.declaredTypeParameters)
}
else if (container is CallableDescriptor && container !is ConstructorDescriptor) {
typeParameters.addAll(container.typeParameters)
}
container = container.containingDeclaration
}
return if (typeParameters.isEmpty()) descriptor else builder.build()!!
}