KT-2193 Nullability information lost for functions inherited from traits
#KT-2193 fixed
This commit is contained in:
@@ -23,6 +23,7 @@ import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.signature.*;
|
||||
import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
|
||||
import org.jetbrains.jet.codegen.signature.kotlin.JetValueParameterAnnotationWriter;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
@@ -720,18 +721,24 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
for (Pair<CallableMemberDescriptor, CallableMemberDescriptor> needDelegates : getTraitImplementations(descriptor)) {
|
||||
CallableMemberDescriptor callableDescriptor = needDelegates.first;
|
||||
if (needDelegates.second instanceof SimpleFunctionDescriptor) {
|
||||
generateDelegationToTraitImpl(codegen, (FunctionDescriptor) needDelegates.second);
|
||||
generateDelegationToTraitImpl(codegen, (FunctionDescriptor) needDelegates.second, (FunctionDescriptor) needDelegates.first);
|
||||
}
|
||||
else if (needDelegates.second instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor property = (PropertyDescriptor) needDelegates.second;
|
||||
List<PropertyAccessorDescriptor> inheritedAccessors = ((PropertyDescriptor) needDelegates.first).getAccessors();
|
||||
for (PropertyAccessorDescriptor accessor : property.getAccessors()) {
|
||||
generateDelegationToTraitImpl(codegen, accessor);
|
||||
for (PropertyAccessorDescriptor inheritedAccessor : inheritedAccessors) {
|
||||
if (inheritedAccessor.getClass() == accessor.getClass()) { // same accessor kind
|
||||
generateDelegationToTraitImpl(codegen, accessor, inheritedAccessor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateDelegationToTraitImpl(ExpressionCodegen codegen, FunctionDescriptor fun) {
|
||||
|
||||
private void generateDelegationToTraitImpl(ExpressionCodegen codegen, FunctionDescriptor fun, @NotNull FunctionDescriptor inheritedFun) {
|
||||
DeclarationDescriptor containingDeclaration = fun.getContainingDeclaration();
|
||||
if (containingDeclaration instanceof ClassDescriptor) {
|
||||
ClassDescriptor declaration = (ClassDescriptor) containingDeclaration;
|
||||
@@ -741,10 +748,44 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
if (jetClass.isTrait()) {
|
||||
int flags = ACC_PUBLIC; // TODO.
|
||||
|
||||
Method function = typeMapper.mapSignature(fun.getName(), fun).getAsmMethod();
|
||||
Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal()).getAsmMethod();
|
||||
Method function;
|
||||
Method functionOriginal;
|
||||
if (fun instanceof PropertyAccessorDescriptor) {
|
||||
PropertyDescriptor property = ((PropertyAccessorDescriptor) fun).getCorrespondingProperty();
|
||||
if (fun instanceof PropertyGetterDescriptor) {
|
||||
function = typeMapper.mapGetterSignature(property, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
|
||||
functionOriginal = typeMapper.mapGetterSignature(property.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
|
||||
}
|
||||
else if (fun instanceof PropertySetterDescriptor) {
|
||||
function = typeMapper.mapSetterSignature(property, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
|
||||
functionOriginal = typeMapper.mapSetterSignature(property.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Accessor is neither getter, nor setter, what is it?");
|
||||
}
|
||||
}
|
||||
else {
|
||||
function = typeMapper.mapSignature(fun.getName(), fun).getAsmMethod();
|
||||
functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal()).getAsmMethod();
|
||||
}
|
||||
|
||||
final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null);
|
||||
AnnotationCodegen.forMethod(mv, state.getInjector().getJetTypeMapper()).genAnnotations(fun);
|
||||
|
||||
JvmMethodSignature jvmSignature = typeMapper.mapToCallableMethod(inheritedFun, false, OwnerKind.IMPLEMENTATION).getSignature();
|
||||
JetMethodAnnotationWriter aw = JetMethodAnnotationWriter.visitAnnotation(mv);
|
||||
if (fun instanceof PropertyAccessorDescriptor) {
|
||||
aw.writeFlags(JvmStdlibNames.JET_METHOD_FLAG_PROPERTY_BIT);
|
||||
aw.writeTypeParameters(jvmSignature.getKotlinTypeParameter());
|
||||
aw.writePropertyType(jvmSignature.getKotlinReturnType());
|
||||
} else {
|
||||
aw.writeFlags();
|
||||
aw.writeNullableReturnType(fun.getReturnType().isNullable());
|
||||
aw.writeTypeParameters(jvmSignature.getKotlinTypeParameter());
|
||||
aw.writeReturnType(jvmSignature.getKotlinReturnType());
|
||||
}
|
||||
aw.visitEnd();
|
||||
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
||||
StubCodegen.generateStubCode(mv);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
//KT-2206
|
||||
trait A {
|
||||
fun f():Int = 239
|
||||
}
|
||||
|
||||
class B() : A
|
||||
|
||||
fun box() : String {
|
||||
return if (B().f() == 239) "OK" else "fail"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
//KT-2206
|
||||
|
||||
trait A {
|
||||
var a:Int
|
||||
get() = 239
|
||||
set(value) {
|
||||
}
|
||||
}
|
||||
|
||||
class B() : A
|
||||
|
||||
fun box() : String {
|
||||
return if (B().a == 239) "OK" else "fail"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
// test composed from KT-2193
|
||||
|
||||
trait A {
|
||||
open fun f(): String = "test"
|
||||
}
|
||||
|
||||
class B() : A
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace test
|
||||
|
||||
abstract trait test.A : jet.Any {
|
||||
open fun f(): jet.String
|
||||
}
|
||||
final class test.B : test.A {
|
||||
final /*constructor*/ fun <init>(): test.B
|
||||
open override /*1*/ fun f(): jet.String
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package test
|
||||
|
||||
// test composed from KT-2193
|
||||
|
||||
trait A {
|
||||
open var v: String
|
||||
get() = "test"
|
||||
set(value) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
|
||||
class B() : A
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace test
|
||||
|
||||
abstract trait test.A : jet.Any {
|
||||
open var v: jet.String
|
||||
}
|
||||
final class test.B : test.A {
|
||||
final /*constructor*/ fun <init>(): test.B
|
||||
open var v: jet.String
|
||||
}
|
||||
@@ -48,4 +48,12 @@ public class TraitsTest extends CodegenTestCase {
|
||||
public void testStdlib () throws Exception {
|
||||
blackBoxFile("traits/stdlib.jet");
|
||||
}
|
||||
|
||||
public void testInheritedFun() throws Exception {
|
||||
blackBoxFile("traits/inheritedFun.jet");
|
||||
}
|
||||
|
||||
public void testInheritedVar() throws Exception {
|
||||
blackBoxFile("traits/inheritedVar.jet");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user