Fix concrete method inheritance in interfaces
For each non-abstract non-declared (i.e. inherited from supertypes) method in an interface we generate its static form to the TImpl, which calls the TImpl method from the corresponding supertype. The accidental override tests changed because we're now trying to generate the delegate for the super method, not knowing that it will clash with the declared method #KT-2888 Fixed #KT-5393 Fixed
This commit is contained in:
@@ -16,11 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.bridges
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.OverrideResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.CallResolverUtil
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
|
||||
public fun <Signature> generateBridgesForFunctionDescriptor(
|
||||
descriptor: FunctionDescriptor,
|
||||
@@ -64,36 +65,50 @@ private data class DescriptorBasedFunctionHandle(val descriptor: FunctionDescrip
|
||||
/**
|
||||
* Given a fake override in a class, returns an overridden declaration with implementation in trait, such that a method delegating to that
|
||||
* trait implementation should be generated into the class containing the fake override; or null if the given function is not a fake
|
||||
* override of any trait implementation or such method was already generated into some superclass
|
||||
* override of any trait implementation or such method was already generated into the superclass or is a method from Any.
|
||||
*/
|
||||
public fun findTraitImplementation(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? {
|
||||
if (descriptor.getKind().isReal()) return null
|
||||
if (CallResolverUtil.isOrOverridesSynthesized(descriptor)) return null
|
||||
|
||||
// TODO: this logic is quite common for bridge generation, find a way to abstract it to a single place
|
||||
// TODO: don't use filterOutOverridden() here, it's an internal front-end utility (see its implementation)
|
||||
val overriddenDeclarations = OverrideResolver.getOverriddenDeclarations(descriptor)
|
||||
val filteredOverriddenDeclarations = OverrideResolver.filterOutOverridden(overriddenDeclarations)
|
||||
val implementation = findImplementationFromInterface(descriptor) ?: return null
|
||||
val immediateConcreteSuper = firstSuperMethodFromKotlin(descriptor, implementation) ?: return null
|
||||
|
||||
var implementation: CallableMemberDescriptor? = null
|
||||
for (overriddenDeclaration in filteredOverriddenDeclarations) {
|
||||
if (DescriptorUtils.isTrait(overriddenDeclaration.getContainingDeclaration()) && overriddenDeclaration.getModality() != Modality.ABSTRACT) {
|
||||
implementation = overriddenDeclaration
|
||||
}
|
||||
}
|
||||
if (implementation == null) {
|
||||
if (!DescriptorUtils.isTrait(immediateConcreteSuper.getContainingDeclaration())) {
|
||||
// If this implementation is already generated into the superclass, we need not generate it again, it'll be inherited
|
||||
return null
|
||||
}
|
||||
|
||||
// If this implementation is already generated into one of the superclasses, we need not generate it again, it'll be inherited
|
||||
val containingClass = descriptor.getContainingDeclaration() as ClassDescriptor
|
||||
val implClassType = implementation!!.getDispatchReceiverParameter()!!.getType()
|
||||
for (supertype in containingClass.getDefaultType().getConstructor().getSupertypes()) {
|
||||
if (!DescriptorUtils.isTrait(supertype.getConstructor().getDeclarationDescriptor()!!) &&
|
||||
TypeUtils.getAllSupertypes(supertype).contains(implClassType)) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return implementation
|
||||
return immediateConcreteSuper
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a fake override, returns an overridden non-abstract function from an interface which is the actual implementation of this function
|
||||
* that should be called when the given fake override is called.
|
||||
*/
|
||||
public fun findImplementationFromInterface(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? {
|
||||
val overridden = OverrideResolver.getOverriddenDeclarations(descriptor)
|
||||
val filtered = OverrideResolver.filterOutOverridden(overridden)
|
||||
|
||||
val result = filtered.firstOrNull { it.getModality() != Modality.ABSTRACT } ?: return null
|
||||
|
||||
val container = result.getContainingDeclaration()
|
||||
if (DescriptorUtils.isClass(container) || DescriptorUtils.isEnumClass(container)) return null
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a fake override and its implementation (non-abstract declaration) somewhere in supertypes,
|
||||
* returns the first immediate super function of the given fake override which overrides that implementation.
|
||||
* The returned function should be called from TImpl-bridges generated for the given fake override.
|
||||
*/
|
||||
public fun firstSuperMethodFromKotlin(
|
||||
descriptor: CallableMemberDescriptor,
|
||||
implementation: CallableMemberDescriptor
|
||||
): CallableMemberDescriptor? {
|
||||
return descriptor.getOverriddenDescriptors().firstOrNull { overridden ->
|
||||
overridden.getModality() != Modality.ABSTRACT &&
|
||||
(overridden == implementation || OverrideResolver.overrides(overridden, implementation))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,15 +21,27 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.context.ClassContext;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor;
|
||||
import org.jetbrains.kotlin.psi.JetClassOrObject;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.DiagnosticsPackage;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.backend.common.bridges.BridgesPackage.findImplementationFromInterface;
|
||||
import static org.jetbrains.kotlin.backend.common.bridges.BridgesPackage.firstSuperMethodFromKotlin;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation;
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
public TraitImplBodyCodegen(
|
||||
@NotNull JetClassOrObject aClass,
|
||||
@NotNull ClassContext context,
|
||||
@@ -52,6 +64,91 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
||||
v.visitSource(myClass.getContainingFile().getName(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateSyntheticParts() {
|
||||
for (DeclarationDescriptor memberDescriptor : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
|
||||
if (!(memberDescriptor instanceof CallableMemberDescriptor)) continue;
|
||||
|
||||
CallableMemberDescriptor fakeOverride = (CallableMemberDescriptor) memberDescriptor;
|
||||
if (fakeOverride.getKind().isReal()) continue;
|
||||
if (fakeOverride.getVisibility() == Visibilities.INVISIBLE_FAKE) continue;
|
||||
if (fakeOverride.getModality() == Modality.ABSTRACT) continue;
|
||||
|
||||
CallableMemberDescriptor implementation = findImplementationFromInterface(fakeOverride);
|
||||
if (implementation == null) continue;
|
||||
|
||||
// If implementation is located in a Java interface, it will be inherited via normal Java rules
|
||||
if (implementation instanceof JavaMethodDescriptor) continue;
|
||||
|
||||
// We create a copy of the function with kind = DECLARATION so that FunctionCodegen will generate its body
|
||||
CallableMemberDescriptor copy = fakeOverride.copy(
|
||||
fakeOverride.getContainingDeclaration(), Modality.OPEN, fakeOverride.getVisibility(),
|
||||
CallableMemberDescriptor.Kind.DECLARATION, true
|
||||
);
|
||||
|
||||
if (fakeOverride instanceof FunctionDescriptor) {
|
||||
generateDelegationToSuperTraitImpl((FunctionDescriptor) copy, (FunctionDescriptor) implementation);
|
||||
}
|
||||
else if (fakeOverride instanceof PropertyDescriptor) {
|
||||
PropertyGetterDescriptor getter = ((PropertyDescriptor) copy).getGetter();
|
||||
PropertyGetterDescriptor implGetter = ((PropertyDescriptor) implementation).getGetter();
|
||||
if (getter != null && implGetter != null) {
|
||||
generateDelegationToSuperTraitImpl(getter, implGetter);
|
||||
}
|
||||
PropertySetterDescriptor setter = ((PropertyDescriptor) copy).getSetter();
|
||||
PropertySetterDescriptor implSetter = ((PropertyDescriptor) implementation).getSetter();
|
||||
if (setter != null && implSetter != null) {
|
||||
generateDelegationToSuperTraitImpl(setter, implSetter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateDelegationToSuperTraitImpl(@NotNull FunctionDescriptor descriptor, @NotNull FunctionDescriptor implementation) {
|
||||
final FunctionDescriptor delegateTo = (FunctionDescriptor) firstSuperMethodFromKotlin(descriptor, implementation);
|
||||
if (delegateTo == null) return;
|
||||
|
||||
// We can't call super methods from Java 1.8 interfaces because that requires INVOKESPECIAL which is forbidden from TImpl class
|
||||
if (delegateTo instanceof JavaMethodDescriptor) return;
|
||||
|
||||
functionCodegen.generateMethod(
|
||||
DiagnosticsPackage.DelegationToTraitImpl(descriptorToDeclaration(descriptor), descriptor),
|
||||
descriptor,
|
||||
new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, descriptor) {
|
||||
@Override
|
||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||
InstructionAdapter iv = codegen.v;
|
||||
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(delegateTo, true, context);
|
||||
List<JvmMethodParameterSignature> myParameters = signature.getValueParameters();
|
||||
List<JvmMethodParameterSignature> calleeParameters = method.getValueParameters();
|
||||
|
||||
if (myParameters.size() != calleeParameters.size()) {
|
||||
throw new AssertionError(
|
||||
String.format(
|
||||
"Method from super interface has a different signature.\n" +
|
||||
"This method:\n%s\n%s\n%s\nSuper method:\n%s\n%s\n%s",
|
||||
callableDescriptor, signature, myParameters, delegateTo, method, calleeParameters
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
int k = 0;
|
||||
Iterator<JvmMethodParameterSignature> it = calleeParameters.iterator();
|
||||
for (JvmMethodParameterSignature parameter : myParameters) {
|
||||
Type type = parameter.getAsmType();
|
||||
StackValue.local(k, type).put(it.next().getAsmType(), iv);
|
||||
k += type.getSize();
|
||||
}
|
||||
|
||||
method.genInvokeInstruction(iv);
|
||||
StackValue.coerce(method.getReturnType(), signature.getReturnType(), iv);
|
||||
iv.areturn(signature.getReturnType());
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateKotlinAnnotation() {
|
||||
writeKotlinSyntheticClassAnnotation(v, DescriptorUtils.isTopLevelOrInnerClass(descriptor)
|
||||
|
||||
@@ -578,7 +578,7 @@ public class JetTypeMapper {
|
||||
}
|
||||
else {
|
||||
invokeOpcode = INVOKESTATIC;
|
||||
signature = mapSignature(functionDescriptor, OwnerKind.TRAIT_IMPL);
|
||||
signature = mapSignature(descriptor.getOriginal(), OwnerKind.TRAIT_IMPL);
|
||||
owner = mapTraitImpl(currentOwner);
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -77,6 +77,12 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg
|
||||
doTestWithJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("longChainOfKotlinExtendsFromJavaWithDefault")
|
||||
public void testLongChainOfKotlinExtendsFromJavaWithDefault() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/java8/boxWithJava/longChainOfKotlinExtendsFromJavaWithDefault/");
|
||||
doTestWithJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("samOnInterfaceWithDefaultMethod")
|
||||
public void testSamOnInterfaceWithDefaultMethod() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/java8/boxWithJava/samOnInterfaceWithDefaultMethod/");
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
interface A {
|
||||
fun foo(): String {
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
interface B : A
|
||||
|
||||
class C : B {
|
||||
override fun foo(): String {
|
||||
return super.foo()
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return C().foo()
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
var result = "Fail"
|
||||
|
||||
interface A {
|
||||
var foo: String
|
||||
get() = result
|
||||
set(value) { result = value }
|
||||
}
|
||||
|
||||
interface B : A
|
||||
|
||||
class C : B {
|
||||
override var foo: String
|
||||
get() = super.foo
|
||||
set(value) { super.foo = value }
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
C().foo = "OK"
|
||||
return C().foo
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
interface A {
|
||||
override fun toString(): String {
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
interface B : A
|
||||
|
||||
class C : B {
|
||||
override fun toString(): String {
|
||||
return super.toString()
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = "${C()}"
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
interface A {
|
||||
fun foo(): Number {
|
||||
return 42
|
||||
}
|
||||
}
|
||||
|
||||
interface B : A
|
||||
|
||||
class C : B {
|
||||
override fun foo(): Int {
|
||||
return super.foo() as Int
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val x = C().foo()
|
||||
return if (x == 42) "OK" else "Fail: $x"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
interface A {
|
||||
fun foo() = "Fail"
|
||||
}
|
||||
|
||||
interface B : A
|
||||
|
||||
interface C : A {
|
||||
override fun foo() = "OK"
|
||||
}
|
||||
|
||||
interface D : B, C
|
||||
|
||||
class Impl : D
|
||||
|
||||
fun box(): String = Impl().foo()
|
||||
@@ -0,0 +1,18 @@
|
||||
interface A<T, U : Number, V : Any> {
|
||||
fun foo(t: T, u: U): V? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
interface B<T, V : Any> : A<T, Int, V>
|
||||
|
||||
class C : B<String, Runnable> {
|
||||
override fun foo(t: String, u: Int): Runnable? {
|
||||
return super.foo(t, u)
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val x = C().foo("", 0)
|
||||
return if (x == null) "OK" else "Fail: $x"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
interface A {
|
||||
void foo();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
interface B : A {
|
||||
fun bar() = 1
|
||||
}
|
||||
|
||||
interface C : B
|
||||
|
||||
class D : C {
|
||||
override fun foo() {}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val d = D()
|
||||
d.foo()
|
||||
d.bar()
|
||||
return "OK"
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
interface A {
|
||||
fun foo(): String
|
||||
}
|
||||
|
||||
interface B {
|
||||
fun foo(): String = "OK"
|
||||
}
|
||||
|
||||
interface C : A, B
|
||||
|
||||
// There's no 'foo' in A$$TImpl, proguard and other tools may fail if we generate calls to it
|
||||
// 0 INVOKESTATIC A\$\$TImpl.foo
|
||||
// 1 INVOKESTATIC B\$\$TImpl.foo
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// If we generate equals/hashCode/toString in all interfaces, there will be too much bytecode
|
||||
|
||||
interface A {
|
||||
fun foo(): Number = 42
|
||||
}
|
||||
|
||||
interface B : A
|
||||
|
||||
class C : B {
|
||||
override fun foo(): Int = super.foo() as Int
|
||||
}
|
||||
|
||||
// 0 equals
|
||||
// 0 hashCode
|
||||
// 0 toString
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
public interface Base {
|
||||
default String foo() {
|
||||
return "OK";
|
||||
}
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
interface K1 : Base
|
||||
|
||||
interface K2 : K1
|
||||
|
||||
interface K3 : K2
|
||||
|
||||
class C : K3 {
|
||||
override fun foo() = super.foo()
|
||||
}
|
||||
|
||||
fun box(): String = C().foo()
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
interface T {
|
||||
fun getX() = 1
|
||||
}
|
||||
|
||||
interface C : T {
|
||||
val x: Int
|
||||
<!ACCIDENTAL_OVERRIDE!>get()<!> = 1
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
interface T {
|
||||
val x: Int
|
||||
get() = 1
|
||||
}
|
||||
|
||||
interface C : T {
|
||||
<!ACCIDENTAL_OVERRIDE!>fun getX()<!> = 1
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
interface T {
|
||||
fun getX() = 1
|
||||
}
|
||||
|
||||
interface <!CONFLICTING_JVM_DECLARATIONS!>C<!> : T {
|
||||
val x: Int
|
||||
get() = 1
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
interface T {
|
||||
val x: Int
|
||||
get() = 1
|
||||
}
|
||||
|
||||
interface <!CONFLICTING_JVM_DECLARATIONS!>C<!> : T {
|
||||
fun getX() = 1
|
||||
}
|
||||
@@ -4328,12 +4328,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("traitFunctionOverriddenByPropertyInTrait.kt")
|
||||
public void testTraitFunctionOverriddenByPropertyInTrait() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitFunctionOverriddenByPropertyInTrait.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("traitFunctionOverriddenByPropertyNoImpl.kt")
|
||||
public void testTraitFunctionOverriddenByPropertyNoImpl() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitFunctionOverriddenByPropertyNoImpl.kt");
|
||||
@@ -4346,12 +4340,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("traitPropertyOverriddenByFunctionInTrait.kt")
|
||||
public void testTraitPropertyOverriddenByFunctionInTrait() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitPropertyOverriddenByFunctionInTrait.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("traitPropertyOverriddenByFunctionNoImpl.kt")
|
||||
public void testTraitPropertyOverriddenByFunctionNoImpl() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitPropertyOverriddenByFunctionNoImpl.kt");
|
||||
@@ -4712,6 +4700,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("traitFunctionOverriddenByPropertyInTrait.kt")
|
||||
public void testTraitFunctionOverriddenByPropertyInTrait() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitFunctionOverriddenByPropertyInTrait.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("traitPropertyOverriddenByFunctionInTrait.kt")
|
||||
public void testTraitPropertyOverriddenByFunctionInTrait() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitPropertyOverriddenByFunctionInTrait.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("twoTraits.kt")
|
||||
public void testTwoTraits() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/twoTraits.kt");
|
||||
|
||||
@@ -215,12 +215,6 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("traitImplGeneratedOnce.kt")
|
||||
public void testTraitImplGeneratedOnce() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/traitImplGeneratedOnce.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/bytecodeText/boxingOptimization")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -512,6 +506,33 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/bytecodeText/interfaces")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Interfaces extends AbstractBytecodeTextTest {
|
||||
public void testAllFilesPresentInInterfaces() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/interfaces"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("firstInheritedMethodIsAbstract.kt")
|
||||
public void testFirstInheritedMethodIsAbstract() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/interfaces/firstInheritedMethodIsAbstract.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noAnyMethodsOnInterfaceInheritance.kt")
|
||||
public void testNoAnyMethodsOnInterfaceInheritance() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/interfaces/noAnyMethodsOnInterfaceInheritance.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("traitImplGeneratedOnce.kt")
|
||||
public void testTraitImplGeneratedOnce() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/interfaces/traitImplGeneratedOnce.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/bytecodeText/lazyCodegen")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+15
@@ -395,6 +395,21 @@ public class BlackBoxAgainstJavaCodegenTestGenerated extends AbstractBlackBoxCod
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxAgainstJava/interfaces")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Interfaces extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInInterfaces() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxAgainstJava/interfaces"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("inheritJavaInterface.kt")
|
||||
public void testInheritJavaInterface() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/interfaces/inheritJavaInterface.kt");
|
||||
doTestAgainstJava(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxAgainstJava/notNullAssertions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+36
@@ -7045,6 +7045,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt5393.kt")
|
||||
public void testKt5393() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/kt5393.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt5393_property.kt")
|
||||
public void testKt5393_property() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/kt5393_property.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt5393_toString.kt")
|
||||
public void testKt5393_toString() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/kt5393_toString.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt5495.kt")
|
||||
public void testKt5495() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/kt5495.kt");
|
||||
@@ -7057,6 +7075,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("traitImplDelegationWithCovariantOverride.kt")
|
||||
public void testTraitImplDelegationWithCovariantOverride() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitImplDelegationWithCovariantOverride.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("traitImplDiamond.kt")
|
||||
public void testTraitImplDiamond() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitImplDiamond.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("traitImplGenericDelegation.kt")
|
||||
public void testTraitImplGenericDelegation() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitImplGenericDelegation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("traitWithPrivateExtension.kt")
|
||||
public void testTraitWithPrivateExtension() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitWithPrivateExtension.kt");
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.descriptors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface PropertyAccessorDescriptor extends FunctionDescriptor {
|
||||
boolean hasBody();
|
||||
|
||||
@@ -27,6 +29,10 @@ public interface PropertyAccessorDescriptor extends FunctionDescriptor {
|
||||
@Override
|
||||
PropertyAccessorDescriptor getOriginal();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
Set<? extends PropertyAccessorDescriptor> getOverriddenDescriptors();
|
||||
|
||||
@NotNull
|
||||
PropertyDescriptor getCorrespondingProperty();
|
||||
|
||||
|
||||
@@ -18,8 +18,14 @@ package org.jetbrains.kotlin.descriptors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface PropertyGetterDescriptor extends PropertyAccessorDescriptor {
|
||||
@NotNull
|
||||
@Override
|
||||
PropertyGetterDescriptor getOriginal();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
Set<? extends PropertyGetterDescriptor> getOverriddenDescriptors();
|
||||
}
|
||||
|
||||
@@ -18,8 +18,14 @@ package org.jetbrains.kotlin.descriptors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface PropertySetterDescriptor extends PropertyAccessorDescriptor {
|
||||
@NotNull
|
||||
@Override
|
||||
PropertySetterDescriptor getOriginal();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
Set<? extends PropertySetterDescriptor> getOverriddenDescriptors();
|
||||
}
|
||||
|
||||
+3
-2
@@ -56,8 +56,9 @@ public class PropertyGetterDescriptorImpl extends PropertyAccessorDescriptorImpl
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<? extends PropertyAccessorDescriptor> getOverriddenDescriptors() {
|
||||
return super.getOverriddenDescriptors(true);
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<? extends PropertyGetterDescriptor> getOverriddenDescriptors() {
|
||||
return (Set) super.getOverriddenDescriptors(true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+3
-2
@@ -72,8 +72,9 @@ public class PropertySetterDescriptorImpl extends PropertyAccessorDescriptorImpl
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<? extends PropertyAccessorDescriptor> getOverriddenDescriptors() {
|
||||
return super.getOverriddenDescriptors(false);
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<? extends PropertySetterDescriptor> getOverriddenDescriptors() {
|
||||
return (Set) super.getOverriddenDescriptors(false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
Reference in New Issue
Block a user