KT-13583: allow local classes to capture members of outer classes
This commit is contained in:
@@ -192,6 +192,10 @@ public final class ClosureTest extends SingleFileTranslationTest {
|
|||||||
checkFooBoxIsOk();
|
checkFooBoxIsOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testEnclosingClassFromLocalClass() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
|
||||||
public void testObjectWithInvokeOperator() throws Exception {
|
public void testObjectWithInvokeOperator() throws Exception {
|
||||||
checkFooBoxIsOk();
|
checkFooBoxIsOk();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,4 +63,8 @@ public final class ObjectTest extends SingleFileTranslationTest {
|
|||||||
public void testDontPolluteObject() throws Exception {
|
public void testDontPolluteObject() throws Exception {
|
||||||
checkFooBoxIsOk();
|
checkFooBoxIsOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testKt3684() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,9 +104,15 @@ class UsageTracker(
|
|||||||
if (descriptor !is ReceiverParameterDescriptor) return false
|
if (descriptor !is ReceiverParameterDescriptor) return false
|
||||||
if (containingDescriptor !is ClassDescriptor && containingDescriptor !is ConstructorDescriptor) return false
|
if (containingDescriptor !is ClassDescriptor && containingDescriptor !is ConstructorDescriptor) return false
|
||||||
|
|
||||||
|
// Class in which we are trying to capture variable
|
||||||
val containingClass = getParentOfType(containingDescriptor, ClassDescriptor::class.java, false) ?: return false
|
val containingClass = getParentOfType(containingDescriptor, ClassDescriptor::class.java, false) ?: return false
|
||||||
|
|
||||||
|
// Class which instance we are trying to capture
|
||||||
val currentClass = descriptor.containingDeclaration as? ClassDescriptor ?: return false
|
val currentClass = descriptor.containingDeclaration as? ClassDescriptor ?: return false
|
||||||
|
|
||||||
|
// We always capture enclosing class if it's not outer (i.e. we are capturing members of enclosing class to a local class)
|
||||||
|
if (containingClass.containingDeclaration !is ClassDescriptor) return false
|
||||||
|
|
||||||
for (outerDeclaration in generateSequence(containingClass) { it.containingDeclaration as? ClassDescriptor }) {
|
for (outerDeclaration in generateSequence(containingClass) { it.containingDeclaration as? ClassDescriptor }) {
|
||||||
if (DescriptorUtils.isSubclass(outerDeclaration, currentClass)) return true
|
if (DescriptorUtils.isSubclass(outerDeclaration, currentClass)) return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
open class A(private val x: String) {
|
||||||
|
fun foo(): String {
|
||||||
|
class B : A("fail1: simple nested") {
|
||||||
|
fun bar() = x
|
||||||
|
}
|
||||||
|
return B().bar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class A1(private val x: String) {
|
||||||
|
fun foo(): String {
|
||||||
|
class B1 {
|
||||||
|
fun bar(): String {
|
||||||
|
class C1 : A1("fail2: deeply nested") {
|
||||||
|
fun baz() = x
|
||||||
|
}
|
||||||
|
return C1().baz()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return B1().bar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class A2(private val x: String) {
|
||||||
|
fun foo(): String {
|
||||||
|
class B2 : A2("fail3: deeply nested") {
|
||||||
|
fun bar(): String {
|
||||||
|
class C2 {
|
||||||
|
fun baz() = x
|
||||||
|
}
|
||||||
|
return C2().baz()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return B2().bar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val result = A("OK").foo()
|
||||||
|
if (result != "OK") return result
|
||||||
|
|
||||||
|
val result1 = A1("OK").foo()
|
||||||
|
if (result1 != "OK") return result1
|
||||||
|
|
||||||
|
val result2 = A2("OK").foo()
|
||||||
|
if (result2 != "OK") return result2
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// copied from JVM backend tests
|
||||||
|
package foo
|
||||||
|
|
||||||
|
open class X(private val n: String) {
|
||||||
|
|
||||||
|
fun foo(): String {
|
||||||
|
return object : X("inner") {
|
||||||
|
fun print(): String {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}.print()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return X("OK").foo()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user