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:
@@ -101,6 +101,9 @@ public interface BindingContext {
|
|||||||
*/
|
*/
|
||||||
WritableSlice<KtExpression, Qualifier> QUALIFIER = new BasicWritableSlice<KtExpression, Qualifier>(DO_NOTHING);
|
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 =
|
WritableSlice<KtReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET =
|
||||||
new BasicWritableSlice<KtReferenceExpression, DeclarationDescriptor>(DO_NOTHING);
|
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
|
// if 'A' really means 'A.Companion' then this slice stores class descriptor for A, REFERENCE_TARGET stores descriptor Companion in this case
|
||||||
|
|||||||
+14
-4
@@ -17,10 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.resolve.scopes.receivers
|
package org.jetbrains.kotlin.resolve.scopes.receivers
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
|
||||||
import org.jetbrains.kotlin.psi.KtReferenceExpression
|
|
||||||
import org.jetbrains.kotlin.psi.KtThisExpression
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
@@ -40,6 +37,12 @@ interface ExpressionReceiver : ReceiverValue {
|
|||||||
type: KotlinType
|
type: KotlinType
|
||||||
) : ExpressionReceiverImpl(expression, type), ThisClassReceiver
|
) : ExpressionReceiverImpl(expression, type), ThisClassReceiver
|
||||||
|
|
||||||
|
private class SuperExpressionReceiver(
|
||||||
|
override val thisType: KotlinType,
|
||||||
|
expression: KtExpression,
|
||||||
|
type: KotlinType
|
||||||
|
) : ExpressionReceiverImpl(expression, type), SuperCallReceiverValue
|
||||||
|
|
||||||
fun create(
|
fun create(
|
||||||
expression: KtExpression,
|
expression: KtExpression,
|
||||||
type: KotlinType,
|
type: KotlinType,
|
||||||
@@ -59,6 +62,13 @@ interface ExpressionReceiver : ReceiverValue {
|
|||||||
return ThisExpressionClassReceiver(descriptor.original as ClassDescriptor, expression, type)
|
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)
|
return ExpressionReceiverImpl(expression, type)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -502,6 +502,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
context.trace.recordType(expression.getInstanceReference(), result);
|
context.trace.recordType(expression.getInstanceReference(), result);
|
||||||
context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(),
|
context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(),
|
||||||
result.getConstructor().getDeclarationDescriptor());
|
result.getConstructor().getDeclarationDescriptor());
|
||||||
|
context.trace.record(THIS_TYPE_FOR_SUPER_EXPRESSION, expression, thisType);
|
||||||
}
|
}
|
||||||
|
|
||||||
BindingContextUtilsKt.recordScope(context.trace, context.scope, superTypeQualifier);
|
BindingContextUtilsKt.recordScope(context.trace, context.scope, superTypeQualifier);
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ class B: A()
|
|||||||
|
|
||||||
class C: A() {
|
class C: A() {
|
||||||
fun bar() {
|
fun bar() {
|
||||||
A().foo()
|
A().<!INVISIBLE_MEMBER!>foo<!>()
|
||||||
B().<!INVISIBLE_MEMBER!>foo<!>()
|
B().<!INVISIBLE_MEMBER!>foo<!>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+32
@@ -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
|
||||||
|
}
|
||||||
+24
@@ -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()
|
||||||
|
}
|
||||||
+13
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+58
@@ -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
|
||||||
|
}
|
||||||
+40
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -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() {}
|
||||||
|
}
|
||||||
+22
@@ -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
|
||||||
|
}
|
||||||
@@ -72,7 +72,7 @@ class E : C() {
|
|||||||
|
|
||||||
class F : C() {
|
class F : C() {
|
||||||
fun test8(c: 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")
|
@TestMetadata("compiler/testData/diagnostics/tests/script")
|
||||||
|
|||||||
+14
-29
@@ -66,21 +66,7 @@ public class JavaVisibilities {
|
|||||||
public static final Visibility PROTECTED_STATIC_VISIBILITY = new Visibility("protected_static", true) {
|
public static final Visibility PROTECTED_STATIC_VISIBILITY = new Visibility("protected_static", true) {
|
||||||
@Override
|
@Override
|
||||||
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
|
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
|
||||||
if (areInSamePackage(what, from)) {
|
return isVisibleForProtectedAndPackage(receiver, what, from);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false);
|
|
||||||
if (fromClass == null) return false;
|
|
||||||
|
|
||||||
DeclarationDescriptor containingDeclaration = what.getContainingDeclaration();
|
|
||||||
assert containingDeclaration instanceof ClassDescriptor : "Only class members can have protected_static visibility";
|
|
||||||
ClassDescriptor whatClass = (ClassDescriptor) containingDeclaration;
|
|
||||||
|
|
||||||
if (DescriptorUtils.isSubclass(fromClass, whatClass)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return isVisible(receiver, what, fromClass.getContainingDeclaration());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -104,20 +90,7 @@ public class JavaVisibilities {
|
|||||||
public static final Visibility PROTECTED_AND_PACKAGE = new Visibility("protected_and_package", true) {
|
public static final Visibility PROTECTED_AND_PACKAGE = new Visibility("protected_and_package", true) {
|
||||||
@Override
|
@Override
|
||||||
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
|
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
|
||||||
if (areInSamePackage(what, from)) {
|
return isVisibleForProtectedAndPackage(receiver, what, from);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClassDescriptor whatClass = DescriptorUtils.getParentOfType(what, ClassDescriptor.class, false);
|
|
||||||
if (whatClass == null) return false;
|
|
||||||
|
|
||||||
ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false);
|
|
||||||
if (fromClass == null) return false;
|
|
||||||
|
|
||||||
if (DescriptorUtils.isSubclass(fromClass, whatClass)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return isVisible(receiver, what, fromClass.getContainingDeclaration());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -146,6 +119,18 @@ public class JavaVisibilities {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static boolean isVisibleForProtectedAndPackage(
|
||||||
|
@Nullable ReceiverValue receiver,
|
||||||
|
@NotNull DeclarationDescriptorWithVisibility what,
|
||||||
|
@NotNull DeclarationDescriptor from
|
||||||
|
) {
|
||||||
|
if (areInSamePackage(DescriptorUtils.unwrapFakeOverrideToAnyDeclaration(what), from)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Visibilities.PROTECTED.isVisible(receiver, what, from);
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean areInSamePackage(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) {
|
private static boolean areInSamePackage(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) {
|
||||||
PackageFragmentDescriptor whatPackage = DescriptorUtils.getParentOfType(first, PackageFragmentDescriptor.class, false);
|
PackageFragmentDescriptor whatPackage = DescriptorUtils.getParentOfType(first, PackageFragmentDescriptor.class, false);
|
||||||
PackageFragmentDescriptor fromPackage = DescriptorUtils.getParentOfType(second, PackageFragmentDescriptor.class, false);
|
PackageFragmentDescriptor fromPackage = DescriptorUtils.getParentOfType(second, PackageFragmentDescriptor.class, false);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.SuperCallReceiverValue;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisClassReceiver;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisClassReceiver;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.util.ModuleVisibilityHelper;
|
import org.jetbrains.kotlin.util.ModuleVisibilityHelper;
|
||||||
@@ -121,20 +122,57 @@ public class Visibilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
|
public boolean isVisible(
|
||||||
ClassDescriptor classDescriptor = DescriptorUtils.getParentOfType(what, ClassDescriptor.class);
|
@Nullable ReceiverValue receiver,
|
||||||
if (DescriptorUtils.isCompanionObject(classDescriptor)) {
|
@NotNull DeclarationDescriptorWithVisibility what,
|
||||||
classDescriptor = DescriptorUtils.getParentOfType(classDescriptor, ClassDescriptor.class);
|
@NotNull DeclarationDescriptor from
|
||||||
}
|
) {
|
||||||
if (classDescriptor == null) return false;
|
ClassDescriptor givenDescriptorContainingClass = DescriptorUtils.getParentOfType(what, ClassDescriptor.class);
|
||||||
|
|
||||||
ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false);
|
ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false);
|
||||||
if (fromClass == null) return false;
|
if (fromClass == null) return false;
|
||||||
if (DescriptorUtils.isSubclass(fromClass, classDescriptor)) {
|
|
||||||
|
if (givenDescriptorContainingClass != null && DescriptorUtils.isCompanionObject(givenDescriptorContainingClass)) {
|
||||||
|
// Access to protected members inside companion is allowed to all subclasses
|
||||||
|
// Receiver type does not matter because objects are final
|
||||||
|
// NB: protected fake overrides in companion from super class should also be allowed
|
||||||
|
ClassDescriptor companionOwner = DescriptorUtils.getParentOfType(givenDescriptorContainingClass, ClassDescriptor.class);
|
||||||
|
if (companionOwner != null && DescriptorUtils.isSubclass(fromClass, companionOwner)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The rest part of method checks visibility similarly to Java does for protected (see JLS §6.6.2)
|
||||||
|
|
||||||
|
// Protected fake overrides can have only one protected overridden (as protected is not allowed for interface members)
|
||||||
|
DeclarationDescriptorWithVisibility whatDeclaration = DescriptorUtils.unwrapFakeOverrideToAnyDeclaration(what);
|
||||||
|
|
||||||
|
ClassDescriptor classDescriptor = DescriptorUtils.getParentOfType(whatDeclaration, ClassDescriptor.class);
|
||||||
|
if (classDescriptor == null) return false;
|
||||||
|
|
||||||
|
if (DescriptorUtils.isSubclass(fromClass, classDescriptor)
|
||||||
|
&& doesReceiverFitForProtectedVisibility(receiver, whatDeclaration, fromClass)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return isVisible(receiver, what, fromClass.getContainingDeclaration());
|
return isVisible(receiver, what, fromClass.getContainingDeclaration());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean doesReceiverFitForProtectedVisibility(
|
||||||
|
@Nullable ReceiverValue receiver,
|
||||||
|
@NotNull DeclarationDescriptorWithVisibility whatDeclaration,
|
||||||
|
@NotNull ClassDescriptor fromClass
|
||||||
|
) {
|
||||||
|
// Do not check receiver for non-callable declarations
|
||||||
|
if (!(whatDeclaration instanceof CallableMemberDescriptor)) return true;
|
||||||
|
|
||||||
|
// See Visibility.isVisible contract
|
||||||
|
if (receiver == ALWAYS_SUITABLE_RECEIVER) return true;
|
||||||
|
if (receiver == IRRELEVANT_RECEIVER || receiver == null) return false;
|
||||||
|
|
||||||
|
KotlinType actualReceiverType = receiver instanceof SuperCallReceiverValue
|
||||||
|
? ((SuperCallReceiverValue) receiver).getThisType()
|
||||||
|
: receiver.getType();
|
||||||
|
|
||||||
|
return DescriptorUtils.isSubtypeOfClass(actualReceiverType, fromClass);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final Visibility INTERNAL = new Visibility("internal", false) {
|
public static final Visibility INTERNAL = new Visibility("internal", false) {
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ public class DescriptorUtils {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isSubtypeOfClass(@NotNull KotlinType type, @NotNull DeclarationDescriptor superClass) {
|
public static boolean isSubtypeOfClass(@NotNull KotlinType type, @NotNull DeclarationDescriptor superClass) {
|
||||||
if (isSameClass(type, superClass)) return true;
|
if (isSameClass(type, superClass)) return true;
|
||||||
for (KotlinType superType : type.getConstructor().getSupertypes()) {
|
for (KotlinType superType : type.getConstructor().getSupertypes()) {
|
||||||
if (isSubtypeOfClass(superType, superClass)) {
|
if (isSubtypeOfClass(superType, superClass)) {
|
||||||
@@ -432,6 +432,15 @@ public class DescriptorUtils {
|
|||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <D extends DeclarationDescriptorWithVisibility> D unwrapFakeOverrideToAnyDeclaration(@NotNull D descriptor) {
|
||||||
|
if (descriptor instanceof CallableMemberDescriptor) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (D) unwrapFakeOverride((CallableMemberDescriptor) descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean shouldRecordInitializerForProperty(@NotNull VariableDescriptor variable, @NotNull KotlinType type) {
|
public static boolean shouldRecordInitializerForProperty(@NotNull VariableDescriptor variable, @NotNull KotlinType type) {
|
||||||
if (variable.isVar() || type.isError()) return false;
|
if (variable.isVar() || type.isError()) return false;
|
||||||
|
|
||||||
|
|||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.resolve.scopes.receivers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
|
interface SuperCallReceiverValue : ReceiverValue {
|
||||||
|
// This type is an actual receiver type used for invoke super-descriptor while ReceiverValue.type is some specific super-type of it
|
||||||
|
val thisType: KotlinType
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user