Refine isVisible for protected visibility

#KT-7437 Fixed
 #KT-7971 Fixed
 #KT-7051 Fixed
 #KT-6125 Fixed
 #KT-6186 Fixed
This commit is contained in:
Denis Zharkov
2016-03-23 20:03:52 +03:00
parent 182b349492
commit 935355ad2f
20 changed files with 411 additions and 44 deletions
@@ -101,6 +101,9 @@ public interface BindingContext {
*/
WritableSlice<KtExpression, Qualifier> QUALIFIER = new BasicWritableSlice<KtExpression, Qualifier>(DO_NOTHING);
WritableSlice<KtSuperExpression, KotlinType> THIS_TYPE_FOR_SUPER_EXPRESSION =
new BasicWritableSlice<KtSuperExpression, KotlinType>(DO_NOTHING);
WritableSlice<KtReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET =
new BasicWritableSlice<KtReferenceExpression, DeclarationDescriptor>(DO_NOTHING);
// if 'A' really means 'A.Companion' then this slice stores class descriptor for A, REFERENCE_TARGET stores descriptor Companion in this case
@@ -17,10 +17,7 @@
package org.jetbrains.kotlin.resolve.scopes.receivers
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtReferenceExpression
import org.jetbrains.kotlin.psi.KtThisExpression
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.types.KotlinType
@@ -40,6 +37,12 @@ interface ExpressionReceiver : ReceiverValue {
type: KotlinType
) : ExpressionReceiverImpl(expression, type), ThisClassReceiver
private class SuperExpressionReceiver(
override val thisType: KotlinType,
expression: KtExpression,
type: KotlinType
) : ExpressionReceiverImpl(expression, type), SuperCallReceiverValue
fun create(
expression: KtExpression,
type: KotlinType,
@@ -59,6 +62,13 @@ interface ExpressionReceiver : ReceiverValue {
return ThisExpressionClassReceiver(descriptor.original as ClassDescriptor, expression, type)
}
}
else if (expression is KtSuperExpression) {
// if there is no THIS_TYPE_FOR_SUPER_EXPRESSION in binding context, we fall through into more restrictive option
// i.e. just return common ExpressionReceiverImpl
bindingContext[BindingContext.THIS_TYPE_FOR_SUPER_EXPRESSION, expression]?.let {
thisType -> return SuperExpressionReceiver(thisType, expression, type)
}
}
return ExpressionReceiverImpl(expression, type)
}
@@ -502,6 +502,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
context.trace.recordType(expression.getInstanceReference(), result);
context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(),
result.getConstructor().getDeclarationDescriptor());
context.trace.record(THIS_TYPE_FOR_SUPER_EXPRESSION, expression, thisType);
}
BindingContextUtilsKt.recordScope(context.trace, context.scope, superTypeQualifier);
+1 -1
View File
@@ -6,7 +6,7 @@ class B: A()
class C: A() {
fun bar() {
A().foo()
A().<!INVISIBLE_MEMBER!>foo<!>()
B().<!INVISIBLE_MEMBER!>foo<!>()
}
}
@@ -0,0 +1,18 @@
open class A {
protected fun foo() {}
init {
B.foo() // Ok, receiver (B.Companion) is subtype of A
(B.Companion).foo()
}
}
class B {
companion object : A()
}
class C: A() {
init {
B.<!INVISIBLE_MEMBER!>foo<!>() // Error: receiver is not suitable
}
}
@@ -0,0 +1,32 @@
package
public open class A {
public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected final fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class B {
public constructor B()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public companion object Companion : A {
private constructor Companion()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected final override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
public final class C : A {
public constructor C()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected final override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,24 @@
// FILE: p1/BaseClass.java
package p1;
public class BaseClass {
protected class ProtSubClass {
public ProtSubClass() {}
}
}
// FILE: k1/main.kt
package k1
import p1.BaseClass
class Foo : BaseClass() {
fun foo() {
ProtSubClass()
super.ProtSubClass()
}
private val v1: BaseClass.ProtSubClass = ProtSubClass()
}
@@ -0,0 +1,13 @@
package
package k1 {
public final class Foo : p1.BaseClass {
public constructor Foo()
private final val v1: p1.BaseClass.ProtSubClass
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -0,0 +1,58 @@
// FILE: bar/JavaClass.java
package bar;
public class JavaClass {
protected void foo() {}
protected static void bar1() {}
protected static void bar2() {}
protected String field = "";
protected static String CONST1 = "";
protected static String CONST2 = "";
}
// FILE: foo/JavaClassSamePackage.java
package foo
public class JavaClassSamePackage extends bar.JavaClass {
protected static void bar2() {}
protected static String CONST2 = "";
}
// FILE: foo/main.kt
package foo
import bar.JavaClass
class KotlinClass : JavaClass() {
fun baz() {
foo() // OK
}
}
class KotlinClass2 : JavaClass() {
override fun foo() {}
val field: String = "abc"
}
fun test(a: KotlinClass, b: KotlinClass2) {
a.<!INVISIBLE_MEMBER!>foo<!>() // Error, protected_and_package declared in different package
b.<!INVISIBLE_MEMBER!>foo<!>() // Error, protected visibility in same package (but could be protected_and_package)
a.<!INVISIBLE_MEMBER!>field<!>
JavaClass.<!INVISIBLE_MEMBER!>bar1<!>()
JavaClass.<!INVISIBLE_MEMBER!>CONST1<!>
KotlinClass.<!UNRESOLVED_REFERENCE!>bar1<!>() // Currently it's unresolved, but it should be prohibited even in case it would be resolved
KotlinClass.<!UNRESOLVED_REFERENCE!>CONST1<!>
JavaClassSamePackage.<!INVISIBLE_MEMBER!>bar1<!>()
JavaClassSamePackage.bar2()
JavaClassSamePackage.<!INVISIBLE_MEMBER!>CONST1<!>
JavaClassSamePackage.CONST2
}
@@ -0,0 +1,40 @@
package
package foo {
public fun test(/*0*/ a: foo.KotlinClass, /*1*/ b: foo.KotlinClass2): kotlin.Unit
public open class JavaClassSamePackage : bar.JavaClass {
public constructor JavaClassSamePackage()
protected/*protected and package*/ final override /*1*/ /*fake_override*/ var field: kotlin.String!
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected/*protected and package*/ open override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
protected/*protected static*/ final override /*1*/ /*fake_override*/ var CONST1: kotlin.String!
protected/*protected static*/ final var CONST2: kotlin.String!
protected/*protected static*/ open override /*1*/ /*fake_override*/ fun bar1(): kotlin.Unit
protected/*protected static*/ open fun bar2(): kotlin.Unit
}
public final class KotlinClass : bar.JavaClass {
public constructor KotlinClass()
protected/*protected and package*/ final override /*1*/ /*fake_override*/ var field: kotlin.String!
public final fun baz(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected/*protected and package*/ open override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class KotlinClass2 : bar.JavaClass {
public constructor KotlinClass2()
public final val field: kotlin.String = "abc"
protected/*protected and package*/ final override /*1*/ /*fake_override*/ var field: kotlin.String!
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected open override /*1*/ fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -0,0 +1,22 @@
// !CHECK_TYPE
// FILE: module1/AbstractModule.java
package module1;
public abstract class AbstractModule<S> {
protected <T> S bind(Class<T> clazz) { return null; }
}
// FILE: module2/main.kt
package module2
import module1.*
fun <T> javaClass(): Class<T> = null!!
public class AppServiceModule : AbstractModule<String>() {
inline fun <reified T> AbstractModule<Int>.bind() {
val x = bind(javaClass<T>())
x checkType { _<String>() } // check that Class receiver is used instead of extension one
}
}
@@ -0,0 +1,14 @@
package
package module2 {
public fun </*0*/ T> javaClass(): java.lang.Class<T>
public final class AppServiceModule : module1.AbstractModule<kotlin.String> {
public constructor AppServiceModule()
protected/*protected and package*/ open override /*1*/ /*fake_override*/ fun </*0*/ T : kotlin.Any!> bind(/*0*/ clazz: java.lang.Class<T!>!): kotlin.String!
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final inline fun </*0*/ reified T> module1.AbstractModule<kotlin.Int>.bind(): kotlin.Unit
}
}
@@ -0,0 +1,15 @@
open class A {
open protected fun foo() { }
open protected fun foobaz() { }
fun bar(x: B) {
x.foo() // OK, foo declared in A
x.<!INVISIBLE_MEMBER!>baz<!>() // Declared in B
x.<!INVISIBLE_MEMBER!>foobaz<!>() // Declared in B
}
}
class B : A() {
protected fun baz() {}
override fun foobaz() {}
}
@@ -0,0 +1,22 @@
package
public open class A {
public constructor A()
public final fun bar(/*0*/ x: B): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected open fun foo(): kotlin.Unit
protected open fun foobaz(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class B : A {
public constructor B()
public final override /*1*/ /*fake_override*/ fun bar(/*0*/ x: B): kotlin.Unit
protected final fun baz(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected open override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
protected open override /*1*/ fun foobaz(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
+1 -1
View File
@@ -72,7 +72,7 @@ class E : C() {
class F : C() {
fun test8(c: C) {
doSmth(c.i)
doSmth(c.<!INVISIBLE_MEMBER!>i<!>)
}
}
@@ -15455,6 +15455,45 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
}
}
}
@TestMetadata("compiler/testData/diagnostics/tests/scopes/protectedVisibility")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ProtectedVisibility extends AbstractDiagnosticsTest {
public void testAllFilesPresentInProtectedVisibility() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/scopes/protectedVisibility"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("complexCompanion.kt")
public void testComplexCompanion() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/protectedVisibility/complexCompanion.kt");
doTest(fileName);
}
@TestMetadata("innerClassInJava.kt")
public void testInnerClassInJava() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/protectedVisibility/innerClassInJava.kt");
doTest(fileName);
}
@TestMetadata("javaInheritedInKotlin.kt")
public void testJavaInheritedInKotlin() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/protectedVisibility/javaInheritedInKotlin.kt");
doTest(fileName);
}
@TestMetadata("kt7971.kt")
public void testKt7971() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/protectedVisibility/kt7971.kt");
doTest(fileName);
}
@TestMetadata("protectedCallOnSubClass.kt")
public void testProtectedCallOnSubClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/protectedVisibility/protectedCallOnSubClass.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/diagnostics/tests/script")