From 57aa355b05821272c7d9aa482bfa780ef9594d08 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 18 Oct 2013 17:28:27 +0400 Subject: [PATCH] Report INVISIBLE_MEMBER on private class object usage --- .../resolve/calls/CallExpressionResolver.java | 17 ++++++- .../classObjects/ClassObjectVisibility.kt | 2 +- .../classObjects/invisibleClassObjects.kt | 48 +++++++++++++++++++ .../nestedClassInPrivateClassObject.kt | 15 ++++++ .../checkers/JetDiagnosticsTestGenerated.java | 10 ++++ 5 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/classObjects/invisibleClassObjects.kt create mode 100644 compiler/testData/diagnostics/tests/classObjects/nestedClassInPrivateClassObject.kt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java index e3cfffc2ed9..cba60b6f806 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java @@ -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, diff --git a/compiler/testData/diagnostics/tests/classObjects/ClassObjectVisibility.kt b/compiler/testData/diagnostics/tests/classObjects/ClassObjectVisibility.kt index e970d3179ac..c917603712c 100644 --- a/compiler/testData/diagnostics/tests/classObjects/ClassObjectVisibility.kt +++ b/compiler/testData/diagnostics/tests/classObjects/ClassObjectVisibility.kt @@ -3,7 +3,7 @@ package foo fun test() { A.d A.f - CCC.classObjectVar + CCC.classObjectVar } class A() { diff --git a/compiler/testData/diagnostics/tests/classObjects/invisibleClassObjects.kt b/compiler/testData/diagnostics/tests/classObjects/invisibleClassObjects.kt new file mode 100644 index 00000000000..da9383619df --- /dev/null +++ b/compiler/testData/diagnostics/tests/classObjects/invisibleClassObjects.kt @@ -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.B +import a.C +import a.D + +fun test() { + f(A) + f(B) + f(C) + f(D) + + A.foo() + B.bar() + C.baz() + D.quux() +} + +fun f(unused: Any) {} diff --git a/compiler/testData/diagnostics/tests/classObjects/nestedClassInPrivateClassObject.kt b/compiler/testData/diagnostics/tests/classObjects/nestedClassInPrivateClassObject.kt new file mode 100644 index 00000000000..dafa3f1d71d --- /dev/null +++ b/compiler/testData/diagnostics/tests/classObjects/nestedClassInPrivateClassObject.kt @@ -0,0 +1,15 @@ +class A { + private class object { + class B { + class C { + class object { + fun foo() {} + } + } + } + } +} + +fun f1() = A.B.C + +fun f2() = A.B.C.foo() diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index d39b74a6fb1..c4082cd0f3b 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -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")