Report INVISIBLE_MEMBER on private class object usage

This commit is contained in:
Alexander Udalov
2013-10-18 17:28:27 +04:00
parent 94deb21551
commit 57aa355b05
5 changed files with 90 additions and 2 deletions
@@ -72,6 +72,7 @@ public class CallExpressionResolver {
if (classObjectType != null) {
context.trace.record(REFERENCE_TARGET, expression, classifier);
JetType result = getExtendedClassObjectType(classObjectType, referencedName, classifier, context);
checkClassObjectVisibility(classifier, expression, context);
return DataFlowUtils.checkType(result, expression, context);
}
}
@@ -117,8 +118,22 @@ public class CallExpressionResolver {
return result[0];
}
private static void checkClassObjectVisibility(
@NotNull ClassifierDescriptor classifier,
@NotNull JetSimpleNameExpression expression,
@NotNull ResolutionContext context
) {
if (!(classifier instanceof ClassDescriptor)) return;
ClassDescriptor classObject = ((ClassDescriptor) classifier).getClassObjectDescriptor();
assert classObject != null : "This check should be done only for classes with class objects: " + classifier;
DeclarationDescriptor from = context.scope.getContainingDeclaration();
if (!Visibilities.isVisible(classObject, from)) {
context.trace.report(INVISIBLE_MEMBER.on(expression, classObject, classObject.getVisibility(), from));
}
}
@NotNull
private JetType getExtendedClassObjectType(
private static JetType getExtendedClassObjectType(
@NotNull JetType classObjectType,
@NotNull Name referencedName,
@NotNull ClassifierDescriptor classifier,
@@ -3,7 +3,7 @@ package foo
fun test() {
A.d
A.<!INVISIBLE_MEMBER!>f<!>
CCC.<!INVISIBLE_MEMBER!>classObjectVar<!>
<!INVISIBLE_MEMBER!>CCC<!>.<!INVISIBLE_MEMBER!>classObjectVar<!>
}
class A() {
@@ -0,0 +1,48 @@
//FILE:a.kt
package a
class A {
class object {
fun foo() {}
}
}
private class B {
class object {
fun bar() {}
}
}
class C {
private class object {
fun baz() {}
}
}
private class D {
private class object {
fun quux() {}
}
}
//FILE:b.kt
package b
import a.A
import a.<!INVISIBLE_REFERENCE!>B<!>
import a.C
import a.<!INVISIBLE_REFERENCE!>D<!>
fun test() {
f(A)
f(<!INVISIBLE_MEMBER!>B<!>)
f(<!INVISIBLE_MEMBER!>C<!>)
f(<!INVISIBLE_MEMBER!>D<!>)
A.foo()
<!INVISIBLE_MEMBER!>B<!>.<!INVISIBLE_MEMBER!>bar<!>()
<!INVISIBLE_MEMBER!>C<!>.<!INVISIBLE_MEMBER!>baz<!>()
<!INVISIBLE_MEMBER!>D<!>.<!INVISIBLE_MEMBER!>quux<!>()
}
fun f(<!UNUSED_PARAMETER!>unused<!>: Any) {}
@@ -0,0 +1,15 @@
class A {
private class object {
class B {
class C {
class object {
fun foo() {}
}
}
}
}
}
fun f1() = <!INVISIBLE_MEMBER!>A<!>.B.C
fun f2() = <!INVISIBLE_MEMBER!>A<!>.B.C.<!INVISIBLE_MEMBER!>foo<!>()
@@ -1374,6 +1374,16 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/classObjects/InnerClassClassObject.kt");
}
@TestMetadata("invisibleClassObjects.kt")
public void testInvisibleClassObjects() throws Exception {
doTest("compiler/testData/diagnostics/tests/classObjects/invisibleClassObjects.kt");
}
@TestMetadata("nestedClassInPrivateClassObject.kt")
public void testNestedClassInPrivateClassObject() throws Exception {
doTest("compiler/testData/diagnostics/tests/classObjects/nestedClassInPrivateClassObject.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis")