Use Visibilities.isVisible with ReceiverValue.

This commit is contained in:
Stanislav Erokhin
2014-10-16 16:30:13 +04:00
parent f640f82ed0
commit f9afdf7540
18 changed files with 305 additions and 13 deletions
@@ -53,6 +53,7 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.bindingContextUtil.BindingContextUtilPackage;
import org.jetbrains.jet.lang.resolve.calls.TailRecursionKind;
import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
@@ -414,8 +415,16 @@ public class JetFlowInformationProvider {
if (variableDescriptor.isVar() && variableDescriptor instanceof PropertyDescriptor) {
DeclarationDescriptor descriptor = BindingContextUtils.getEnclosingDescriptor(trace.getBindingContext(), expression);
PropertySetterDescriptor setterDescriptor = ((PropertyDescriptor) variableDescriptor).getSetter();
if (Visibilities.isVisible(variableDescriptor, descriptor) && setterDescriptor != null
&& !Visibilities.isVisible(setterDescriptor, descriptor)) {
ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilPackage.getResolvedCall(expression, trace.getBindingContext());
ReceiverValue receiverValue = ReceiverValue.IRRELEVANT_RECEIVER;
if (resolvedCall != null) {
receiverValue = ExpressionTypingUtils
.normalizeReceiverValueForVisibility(resolvedCall.getDispatchReceiver(), trace.getBindingContext());
}
if (Visibilities.isVisible(receiverValue, variableDescriptor, descriptor) && setterDescriptor != null
&& !Visibilities.isVisible(receiverValue, setterDescriptor, descriptor)) {
report(Errors.INVISIBLE_SETTER.on(expression, variableDescriptor, setterDescriptor.getVisibility(),
variableDescriptor.getContainingDeclaration()), ctxt);
return true;
@@ -37,6 +37,7 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
import org.jetbrains.jet.lang.resolve.dataClassUtils.DataClassUtilsPackage;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
@@ -821,7 +822,7 @@ public class OverrideResolver {
all.addAll((Collection) supertype.getMemberScope().getProperties(declared.getName()));
for (CallableMemberDescriptor fromSuper : all) {
if (OverridingUtil.DEFAULT.isOverridableBy(fromSuper, declared).getResult() == OVERRIDABLE) {
if (Visibilities.isVisible(fromSuper, declared)) {
if (Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, fromSuper, declared)) {
throw new IllegalStateException("Descriptor " + fromSuper + " is overridable by " + declared +
" and visible but does not appear in its getOverriddenDescriptors()");
}
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import java.util.Collection;
import java.util.Collections;
@@ -457,7 +458,7 @@ public class QualifiedExpressionResolver {
@NotNull JetSimpleNameExpression referenceExpression,
@NotNull JetScope scopeToCheckVisibility
) {
if (!Visibilities.isVisible(descriptor, scopeToCheckVisibility.getContainingDeclaration())) {
if (!Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, descriptor, scopeToCheckVisibility.getContainingDeclaration())) {
//noinspection ConstantConditions
trace.report(INVISIBLE_REFERENCE.on(referenceExpression, descriptor, descriptor.getVisibility(),
descriptor.getContainingDeclaration()));
@@ -91,8 +91,9 @@ public class CandidateResolver {
}
ReceiverValue receiverValue = ExpressionTypingUtils.normalizeReceiverValueForVisibility(candidateCall.getDispatchReceiver(), context.trace.getBindingContext());
DeclarationDescriptorWithVisibility invisibleMember =
Visibilities.findInvisibleMember(ReceiverValue.IRRELEVANT_RECEIVER, candidate, context.scope.getContainingDeclaration());
Visibilities.findInvisibleMember(receiverValue, candidate, context.scope.getContainingDeclaration());
if (invisibleMember != null) {
candidateCall.addStatus(OTHER_ERROR);
context.tracing.invisibleMember(context.trace, invisibleMember);
@@ -413,7 +413,8 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
if (call == null) return false
val candidateDescriptor = call.getDescriptor()
if (ErrorUtils.isError(candidateDescriptor)) return true
return Visibilities.isVisible(candidateDescriptor, context.scope.getContainingDeclaration())
val receiverValue = ExpressionTypingUtils.normalizeReceiverValueForVisibility(call.getDispatchReceiver(), context.trace.getBindingContext())
return Visibilities.isVisible(receiverValue, candidateDescriptor, context.scope.getContainingDeclaration())
}
private fun isSynthesized(call: ResolutionCandidate<D>): Boolean {
@@ -41,6 +41,7 @@ import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.ErrorUtils;
@@ -77,6 +78,28 @@ public class ExpressionTypingUtils {
this.builtIns = builtIns;
}
@NotNull
public static ReceiverValue normalizeReceiverValueForVisibility(@NotNull ReceiverValue receiverValue, @NotNull BindingContext trace) {
if (receiverValue instanceof ExpressionReceiver) {
JetExpression expression = ((ExpressionReceiver) receiverValue).getExpression();
JetReferenceExpression referenceExpression = null;
if (expression instanceof JetThisExpression) {
referenceExpression = ((JetThisExpression) expression).getInstanceReference();
}
else if (expression instanceof JetThisReferenceExpression) {
referenceExpression = (JetReferenceExpression) expression;
}
if (referenceExpression != null) {
DeclarationDescriptor descriptor = trace.get(BindingContext.REFERENCE_TARGET, referenceExpression);
if (descriptor instanceof ClassDescriptor) {
return new ClassReceiver((ClassDescriptor) descriptor.getOriginal());
}
}
}
return receiverValue;
}
@Nullable
protected static ExpressionReceiver getExpressionReceiver(@NotNull JetExpression expression, @Nullable JetType type) {
if (type == null) return null;
@@ -0,0 +1,39 @@
fun <T> getT(): T = null!!
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
class Test<in I> {
private fun foo() : I = getT()
fun apply(<!UNUSED_PARAMETER!>i<!>: I) {}
{
foo()
this.foo()
}
fun test() {
apply(foo())
apply(this.foo())
with(Test<I>()) {
apply(foo()) // resolved to this@Test.foo
apply(this.<!INVISIBLE_MEMBER(foo; private/*private to this*/; Test)!>foo<!>())
apply(this@with.<!INVISIBLE_MEMBER(foo; private/*private to this*/; Test)!>foo<!>())
apply(this@Test.foo())
}
}
fun <I> test(t: Test<I>) {
t.apply(t.<!INVISIBLE_MEMBER(foo; private/*private to this*/; Test)!>foo<!>())
}
class object {
fun <I> test(t: Test<I>) {
t.apply(t.<!INVISIBLE_MEMBER(foo; private/*private to this*/; Test)!>foo<!>())
}
}
}
fun <I> test(t: Test<I>) {
t.apply(t.<!INVISIBLE_MEMBER(foo; private/*private to this*/; Test)!>foo<!>())
}
@@ -0,0 +1,24 @@
package
internal fun </*0*/ T> getT(): T
internal fun </*0*/ I> test(/*0*/ t: Test<I>): kotlin.Unit
internal fun </*0*/ T, /*1*/ R> with(/*0*/ receiver: T, /*1*/ f: T.() -> R): R
internal final class Test</*0*/ in I> {
public constructor Test</*0*/ in I>()
internal final fun apply(/*0*/ i: I): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
private/*private to this*/ final fun foo(): I
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
internal final fun test(): kotlin.Unit
internal final fun </*0*/ I> test(/*0*/ t: Test<I>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
internal class object <class-object-for-Test> {
private constructor <class-object-for-Test>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
internal final fun </*0*/ I> test(/*0*/ t: Test<I>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -0,0 +1,38 @@
fun <T> getT(): T = null!!
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
class Test<in I, out O> {
private val i: I = getT()
;{
apply(i)
apply(this.i)
}
fun apply(<!UNUSED_PARAMETER!>i<!>: I) {}
fun test() {
apply(i)
apply(this.i)
with(Test<I, O>()) {
apply(i) // resolved to this@Test.i
apply(this.<!INVISIBLE_MEMBER(i; private/*private to this*/; Test)!>i<!>)
apply(this@with.<!INVISIBLE_MEMBER(i; private/*private to this*/; Test)!>i<!>)
apply(this@Test.i)
}
}
fun <I, O> test(t: Test<I, O>) {
t.apply(t.<!INVISIBLE_MEMBER(i; private/*private to this*/; Test)!>i<!>)
}
class object {
fun <I, O> test(t: Test<I, O>) {
t.apply(t.<!INVISIBLE_MEMBER(i; private/*private to this*/; Test)!>i<!>)
}
}
}
fun <I, O> test(t: Test<I, O>) {
t.apply(t.<!INVISIBLE_MEMBER(i; private/*private to this*/; Test)!>i<!>)
}
@@ -0,0 +1,24 @@
package
internal fun </*0*/ T> getT(): T
internal fun </*0*/ I, /*1*/ O> test(/*0*/ t: Test<I, O>): kotlin.Unit
internal fun </*0*/ T, /*1*/ R> with(/*0*/ receiver: T, /*1*/ f: T.() -> R): R
internal final class Test</*0*/ in I, /*1*/ out O> {
public constructor Test</*0*/ in I, /*1*/ out O>()
private/*private to this*/ final val i: I
internal final fun apply(/*0*/ i: I): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
internal final fun test(): kotlin.Unit
internal final fun </*0*/ I, /*1*/ O> test(/*0*/ t: Test<I, O>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
internal class object <class-object-for-Test> {
private constructor <class-object-for-Test>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
internal final fun </*0*/ I, /*1*/ O> test(/*0*/ t: Test<I, O>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -0,0 +1,38 @@
fun <T> getT(): T = null!!
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
class Test<in I, out O> {
private var i: I = getT()
private val j: I
;{
j = getT()
i = getT()
this.i = getT()
}
fun test() {
i = getT()
this.i = getT()
with(Test<I, O>()) {
i = getT() // resolved to this@Test.i
this.<!INVISIBLE_MEMBER(i; private/*private to this*/; Test)!>i<!> = getT()
this@with.<!INVISIBLE_MEMBER(i; private/*private to this*/; Test)!>i<!> = getT()
this@Test.i = getT()
}
}
fun <I, O> test(t: Test<I, O>) {
t.<!INVISIBLE_MEMBER(i; private/*private to this*/; Test)!>i<!> = getT()
}
class object {
fun <I, O> test(t: Test<I, O>) {
t.<!INVISIBLE_MEMBER(i; private/*private to this*/; Test)!>i<!> = getT()
}
}
}
fun <I, O> test(t: Test<I, O>) {
t.<!INVISIBLE_MEMBER(i; private/*private to this*/; Test)!>i<!> = getT()
}
@@ -0,0 +1,24 @@
package
internal fun </*0*/ T> getT(): T
internal fun </*0*/ I, /*1*/ O> test(/*0*/ t: Test<I, O>): kotlin.Unit
internal fun </*0*/ T, /*1*/ R> with(/*0*/ receiver: T, /*1*/ f: T.() -> R): R
internal final class Test</*0*/ in I, /*1*/ out O> {
public constructor Test</*0*/ in I, /*1*/ out O>()
private/*private to this*/ final var i: I
private/*private to this*/ final val j: I
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
internal final fun test(): kotlin.Unit
internal final fun </*0*/ I, /*1*/ O> test(/*0*/ t: Test<I, O>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
internal class object <class-object-for-Test> {
private constructor <class-object-for-Test>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
internal final fun </*0*/ I, /*1*/ O> test(/*0*/ t: Test<I, O>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -0,0 +1,20 @@
fun <T> getT(): T = null!!
class A<in I>(init: I) {
private val i: I
{
i = getT()
}
private var i2 = i
private val i3: I
private var i4 = getT<I>()
;{
i2 = getT()
i3 = init
i4 = i3
}
}
@@ -0,0 +1,14 @@
package
internal fun </*0*/ T> getT(): T
internal final class A</*0*/ in I> {
public constructor A</*0*/ in I>(/*0*/ init: I)
private/*private to this*/ final val i: I
private/*private to this*/ final var i2: I
private/*private to this*/ final val i3: I
private/*private to this*/ final var i4: I
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
}
@@ -10286,6 +10286,7 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
@TestMetadata("compiler/testData/diagnostics/tests/variance")
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({Variance.PrivateToThis.class})
@RunWith(JUnit3RunnerWithInners.class)
public static class Variance extends AbstractJetDiagnosticsTest {
public void testAllFilesPresentInVariance() throws Exception {
@@ -10357,6 +10358,39 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/variance/Visibility.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/diagnostics/tests/variance/privateToThis")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PrivateToThis extends AbstractJetDiagnosticsTest {
public void testAllFilesPresentInPrivateToThis() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/variance/privateToThis"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("FunctionCall.kt")
public void testFunctionCall() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/variance/privateToThis/FunctionCall.kt");
doTest(fileName);
}
@TestMetadata("GetVal.kt")
public void testGetVal() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/variance/privateToThis/GetVal.kt");
doTest(fileName);
}
@TestMetadata("SetVar.kt")
public void testSetVar() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/variance/privateToThis/SetVar.kt");
doTest(fileName);
}
@TestMetadata("ValReassigned.kt")
public void testValReassigned() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/variance/privateToThis/ValReassigned.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/diagnostics/tests/when")
@@ -139,10 +139,6 @@ public class Visibilities {
private Visibilities() {
}
public static boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
return isVisible(ReceiverValue.IRRELEVANT_RECEIVER, what, from);
}
public static boolean isVisible(@NotNull ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
return findInvisibleMember(receiver, what, from) == null;
}
@@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.PropertyAccessorDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
@@ -269,7 +270,7 @@ public class OverridingUtil {
for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) {
OverrideCompatibilityInfo.Result result = DEFAULT.isOverridableBy(fromSupertype, fromCurrent).getResult();
boolean isVisible = Visibilities.isVisible(fromSupertype, current);
boolean isVisible = Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, fromSupertype, current);
switch (result) {
case OVERRIDABLE:
if (isVisible) {
@@ -378,7 +379,8 @@ public class OverridingUtil {
@Override
public Boolean invoke(CallableMemberDescriptor descriptor) {
//nested class could capture private member, so check for private visibility added
return !Visibilities.isPrivate(descriptor.getVisibility()) && Visibilities.isVisible(descriptor, current);
return !Visibilities.isPrivate(descriptor.getVisibility()) &&
Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, descriptor, current);
}
});
}
@@ -68,6 +68,7 @@ import org.jetbrains.jet.lang.descriptors.VariableDescriptor
import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus
import org.jetbrains.jet.plugin.caches.resolve.ResolutionFacade
import org.jetbrains.jet.lang.types.typeUtil.isSubtypeOf
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils
enum class Tail {
COMMA
@@ -186,7 +187,9 @@ class ExpectedInfos(val bindingContext: BindingContext, val resolutionFacade: Re
// consider only candidates with more arguments than in the truncated call and with all arguments before the current one matched
if (candidate.noErrorsInValueArguments() && (candidate.getCandidateDescriptor().getValueParameters().size > argumentIndex || isFunctionLiteralArgument)) {
val descriptor = candidate.getResultingDescriptor()
if (!Visibilities.isVisible(descriptor, resolutionScope.getContainingDeclaration())) continue
val thisReceiver = ExpressionTypingUtils.normalizeReceiverValueForVisibility(candidate.getDispatchReceiver(), bindingContext)
if (!Visibilities.isVisible(thisReceiver, descriptor, resolutionScope.getContainingDeclaration())) continue
val parameters = descriptor.getValueParameters()
if (isFunctionLiteralArgument && argumentIndex != parameters.lastIndex) continue