kt-1760 delegation to java iface:
- removed codegen's unnecessary lookup for a declaration - skipped class' only supertype (if any) methods when delegating
This commit is contained in:
committed by
Andrey Breslav
parent
78cb5381f7
commit
b84f068c33
@@ -779,7 +779,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
StackValue field = StackValue.field(fieldType, classname, delegateField, false);
|
StackValue field = StackValue.field(fieldType, classname, delegateField, false);
|
||||||
field.store(fieldType, iv);
|
field.store(fieldType, iv);
|
||||||
|
|
||||||
JetClass superClass = (JetClass) classDescriptorToDeclaration(bindingContext, superClassDescriptor);
|
|
||||||
final CodegenContext delegateContext = context.intoClass(superClassDescriptor,
|
final CodegenContext delegateContext = context.intoClass(superClassDescriptor,
|
||||||
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname,
|
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname,
|
||||||
delegateField, false),
|
delegateField, false),
|
||||||
@@ -788,7 +787,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
MapTypeMode.IMPL)
|
MapTypeMode.IMPL)
|
||||||
.getInternalName()),
|
.getInternalName()),
|
||||||
state);
|
state);
|
||||||
generateDelegates(superClass, delegateContext, field);
|
generateDelegates(superClassDescriptor, delegateContext, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void lookupConstructorExpressionsInClosureIfPresent(final ConstructorContext constructorContext) {
|
private void lookupConstructorExpressionsInClosureIfPresent(final ConstructorContext constructorContext) {
|
||||||
@@ -1208,18 +1207,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void generateDelegates(JetClass toClass, CodegenContext delegateContext, StackValue field) {
|
protected void generateDelegates(ClassDescriptor toClass, CodegenContext delegateContext, StackValue field) {
|
||||||
final FunctionCodegen functionCodegen = new FunctionCodegen(delegateContext, v, state);
|
final FunctionCodegen functionCodegen = new FunctionCodegen(delegateContext, v, state);
|
||||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(delegateContext, v, functionCodegen, state);
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(delegateContext, v, functionCodegen, state);
|
||||||
|
|
||||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, toClass);
|
|
||||||
for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
|
for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
|
||||||
if (declaration instanceof CallableMemberDescriptor) {
|
if (declaration instanceof CallableMemberDescriptor) {
|
||||||
CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration;
|
CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration;
|
||||||
if (callableMemberDescriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION) {
|
if (callableMemberDescriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION) {
|
||||||
Set<? extends CallableMemberDescriptor> overriddenDescriptors = callableMemberDescriptor.getOverriddenDescriptors();
|
Set<? extends CallableMemberDescriptor> overriddenDescriptors = callableMemberDescriptor.getOverriddenDescriptors();
|
||||||
for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) {
|
for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) {
|
||||||
if (overriddenDescriptor.getContainingDeclaration() == classDescriptor) {
|
if (overriddenDescriptor.getContainingDeclaration() == toClass) {
|
||||||
if (declaration instanceof PropertyDescriptor) {
|
if (declaration instanceof PropertyDescriptor) {
|
||||||
propertyCodegen
|
propertyCodegen
|
||||||
.genDelegate((PropertyDescriptor) declaration, (PropertyDescriptor) overriddenDescriptor, field);
|
.genDelegate((PropertyDescriptor) declaration, (PropertyDescriptor) overriddenDescriptor, field);
|
||||||
|
|||||||
@@ -16,17 +16,21 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.lang.resolve;
|
package org.jetbrains.jet.lang.resolve;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.collect.Collections2;
|
import com.google.common.collect.Collections2;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||||
import org.jetbrains.jet.lang.psi.JetDelegationSpecifier;
|
import org.jetbrains.jet.lang.psi.JetDelegationSpecifier;
|
||||||
import org.jetbrains.jet.lang.psi.JetDelegatorByExpressionSpecifier;
|
import org.jetbrains.jet.lang.psi.JetDelegatorByExpressionSpecifier;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
@@ -41,12 +45,22 @@ public class DelegationResolver {
|
|||||||
JetDelegatorByExpressionSpecifier specifier = (JetDelegatorByExpressionSpecifier) delegationSpecifier;
|
JetDelegatorByExpressionSpecifier specifier = (JetDelegatorByExpressionSpecifier) delegationSpecifier;
|
||||||
JetType type = trace.get(BindingContext.TYPE, specifier.getTypeReference());
|
JetType type = trace.get(BindingContext.TYPE, specifier.getTypeReference());
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
@SuppressWarnings("unchecked")
|
final Collection<CallableMemberDescriptor> membersToSkip = getMembersFromClassSupertype(type);
|
||||||
Collection<CallableMemberDescriptor> callableDescriptors = (Collection) Collections2.filter(
|
Collection<CallableMemberDescriptor> descriptorsToDelegate = Collections2.filter(extractCallableMembers(type),
|
||||||
type.getMemberScope().getAllDescriptors(),
|
new Predicate<CallableMemberDescriptor>() {
|
||||||
Predicates.instanceOf(CallableMemberDescriptor.class));
|
@Override
|
||||||
Collection<CallableMemberDescriptor> descriptors = generateDelegatedMembers(classDescriptor, callableDescriptors);
|
public boolean apply(@Nullable CallableMemberDescriptor descriptor) {
|
||||||
for (CallableMemberDescriptor descriptor : descriptors) {
|
for (CallableMemberDescriptor memberToSkip : membersToSkip) {
|
||||||
|
if (haveSameSignatures(memberToSkip, descriptor)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Collection<CallableMemberDescriptor> generatedDescriptors = generateDelegatedMembers(classDescriptor, descriptorsToDelegate);
|
||||||
|
for (CallableMemberDescriptor descriptor : generatedDescriptors) {
|
||||||
if (descriptor instanceof PropertyDescriptor) {
|
if (descriptor instanceof PropertyDescriptor) {
|
||||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||||
classDescriptor.getBuilder().addPropertyDescriptor(propertyDescriptor);
|
classDescriptor.getBuilder().addPropertyDescriptor(propertyDescriptor);
|
||||||
@@ -61,6 +75,36 @@ public class DelegationResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean haveSameSignatures(CallableDescriptor memberOne, CallableDescriptor memberTwo) {
|
||||||
|
return OverridingUtil.isOverridableBy(memberOne, memberTwo).getResult() == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Collection<CallableMemberDescriptor> getMembersFromClassSupertype(JetType type) {
|
||||||
|
JetType classSupertype = null;
|
||||||
|
for (JetType supertype : TypeUtils.getAllSupertypes(type)) {
|
||||||
|
if (isNotTrait(supertype.getConstructor().getDeclarationDescriptor())) {
|
||||||
|
classSupertype = supertype;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return classSupertype != null ? extractCallableMembers(classSupertype) : Collections.<CallableMemberDescriptor>emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static Collection<CallableMemberDescriptor> extractCallableMembers(JetType type) {
|
||||||
|
return (Collection) Collections2.filter(type.getMemberScope().getAllDescriptors(),
|
||||||
|
Predicates.instanceOf(CallableMemberDescriptor.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isNotTrait(DeclarationDescriptor descriptor) {
|
||||||
|
if (descriptor instanceof ClassDescriptor) {
|
||||||
|
final ClassKind kind = ((ClassDescriptor) descriptor).getKind();
|
||||||
|
return kind != ClassKind.TRAIT;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static <T extends CallableMemberDescriptor> Collection<T> generateDelegatedMembers(DeclarationDescriptor newOwner, Collection<T> delegatedDescriptors) {
|
public static <T extends CallableMemberDescriptor> Collection<T> generateDelegatedMembers(DeclarationDescriptor newOwner, Collection<T> delegatedDescriptors) {
|
||||||
Collection<CallableMemberDescriptor> result = Lists.newArrayList();
|
Collection<CallableMemberDescriptor> result = Lists.newArrayList();
|
||||||
for (CallableMemberDescriptor memberDescriptor : delegatedDescriptors) {
|
for (CallableMemberDescriptor memberDescriptor : delegatedDescriptors) {
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
class TestJava(r : Runnable) : Runnable by r {}
|
||||||
|
class TestRunnable() : Runnable {
|
||||||
|
public override fun run() = System.out.println("foobar")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
var del = TestJava(TestRunnable())
|
||||||
|
del.run()
|
||||||
|
if (del !is Runnable)
|
||||||
|
return "Fail #1"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
class TestIface(r : Runnable) : Runnable by r {}
|
||||||
|
|
||||||
|
class TestObject(o : Object) : <!DELEGATION_NOT_TO_TRAIT!>Object<!> by o {}
|
||||||
@@ -187,6 +187,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
public void testDelegation_ScopeInitializationOrder() throws Exception {
|
public void testDelegation_ScopeInitializationOrder() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/Delegation_ScopeInitializationOrder.kt");
|
doTest("compiler/testData/diagnostics/tests/Delegation_ScopeInitializationOrder.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("DelegationToJavaIface.kt")
|
||||||
|
public void testDelegationToJavaIface() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/DelegationToJavaIface.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("DiamondFunction.kt")
|
@TestMetadata("DiamondFunction.kt")
|
||||||
public void testDiamondFunction() throws Exception {
|
public void testDiamondFunction() throws Exception {
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ public class ClassGenTest extends CodegenTestCase {
|
|||||||
assertInstanceOf(aClass.newInstance(), List.class);
|
assertInstanceOf(aClass.newInstance(), List.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDelegationJavaIface() throws Exception {
|
||||||
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||||
|
blackBoxFile("classes/delegationJava.kt");
|
||||||
|
}
|
||||||
|
|
||||||
public void testInheritanceAndDelegation_DelegatingDefaultConstructorProperties() throws Exception {
|
public void testInheritanceAndDelegation_DelegatingDefaultConstructorProperties() throws Exception {
|
||||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||||
blackBoxFile("classes/inheritance.jet");
|
blackBoxFile("classes/inheritance.jet");
|
||||||
|
|||||||
Reference in New Issue
Block a user