Inline visibility checking

This commit is contained in:
Mikhael Bogdanov
2013-11-18 15:08:05 +04:00
parent c89c465fec
commit 558687f20f
7 changed files with 223 additions and 7 deletions
@@ -23,6 +23,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.model.ExpressionValueArgument;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
@@ -42,10 +43,13 @@ public class InlineCallResolverExtension implements CallResolverExtension {
private Set<DeclarationDescriptor> inlinableParameters = new HashSet<DeclarationDescriptor>();
private final boolean isEffectivelyPublicApiFunction;
public InlineCallResolverExtension(@NotNull SimpleFunctionDescriptor descriptor) {
assert descriptor.isInline() : "This extension should be created only for inline functions but not " + descriptor;
this.descriptor = descriptor;
this.isEffectivelyPublicApiFunction = isEffectivelyPublicApi(descriptor);
Iterator<ValueParameterDescriptor> iterator = descriptor.getValueParameters().iterator();
while (iterator.hasNext()) {
ValueParameterDescriptor next = iterator.next();
@@ -102,9 +106,10 @@ public class InlineCallResolverExtension implements CallResolverExtension {
checkFunctionCall(context, targetDescriptor, jetExpression);
}
}
//TODO default and vararg
}
checkVisibility(targetDescriptor, expression, context);
}
private void checkCallWithReceiver(
@@ -179,11 +184,20 @@ public class InlineCallResolverExtension implements CallResolverExtension {
((SimpleFunctionDescriptor) descriptor).isInline();
}
private void checkVisibility(){
private void checkVisibility(@NotNull CallableDescriptor declarationDescriptor, @NotNull JetElement expression, @NotNull BasicCallResolutionContext context){
if (isEffectivelyPublicApiFunction && !isEffectivelyPublicApi(declarationDescriptor) && declarationDescriptor.getVisibility() != Visibilities.LOCAL) {
context.trace.report(Errors.INVISIBLE_MEMBER_FROM_INLINE.on(expression, declarationDescriptor, descriptor));
}
}
interface FunctionParameter {
private static boolean isEffectivelyPublicApi(DeclarationDescriptorWithVisibility descriptor) {
DeclarationDescriptorWithVisibility parent = descriptor;
while (parent != null) {
if (!parent.getVisibility().isPublicAPI()) {
return false;
}
parent = DescriptorUtils.getParentOfType(parent, DeclarationDescriptorWithVisibility.class);
}
return true;
}
}
@@ -0,0 +1,47 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
private class Z public (){
public val publicProperty:Int = 12
public fun publicFun() {}
}
public inline fun test() {
<!INVISIBLE_MEMBER_FROM_INLINE!>Z<!>().<!INVISIBLE_MEMBER_FROM_INLINE!>publicProperty<!>
<!INVISIBLE_MEMBER_FROM_INLINE!>Z<!>().<!INVISIBLE_MEMBER_FROM_INLINE!>publicFun<!>()
}
inline fun testInternal() {
Z().publicProperty
Z().publicFun()
}
private class Z2 {
private val privateProperty = 11;
public val publicProperty:Int = 12
private fun privateFun() {}
public fun publicFun() {}
public inline fun test() {
privateProperty
privateFun()
publicProperty
publicFun()
Z2().publicProperty
Z2().publicFun()
Z2().privateProperty
Z2().privateFun()
}
inline fun testInternal() {
privateProperty
privateFun()
publicProperty
publicFun()
Z2().publicProperty
Z2().publicFun()
Z2().privateProperty
Z2().privateFun()
}
}
@@ -0,0 +1,36 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
private class Z2 {
private val privateProperty = 11;
public val publicProperty:Int = 12
private fun privateFun() {}
public fun publicFun() {}
private inner class ZInner {
public inline fun test() {
privateProperty
privateFun()
publicFun()
publicProperty
Z2().publicProperty
Z2().publicFun()
Z2().privateProperty
Z2().privateFun()
}
inline fun testInternal() {
privateProperty
privateFun()
publicFun()
publicProperty
Z2().publicProperty
Z2().publicFun()
Z2().privateProperty
Z2().privateFun()
}
}
}
@@ -0,0 +1,27 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
private val privateProperty = 11;
private fun privateFun() {}
val internalProperty = 11;
fun internalFun() {}
public inline fun test() {
<!INVISIBLE_MEMBER_FROM_INLINE!>privateFun<!>()
<!INVISIBLE_MEMBER_FROM_INLINE!>privateProperty<!>
}
public inline fun test2() {
<!INVISIBLE_MEMBER_FROM_INLINE!>internalFun<!>()
<!INVISIBLE_MEMBER_FROM_INLINE!>internalProperty<!>
}
inline fun testInternal() {
privateFun()
privateProperty
}
inline fun test2Internal() {
internalFun()
internalProperty
}
@@ -0,0 +1,37 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
public class Z {
val privateProperty = 11;
fun privateFun() {
}
}
public inline fun test() {
Z().<!INVISIBLE_MEMBER_FROM_INLINE!>privateProperty<!>
Z().<!INVISIBLE_MEMBER_FROM_INLINE!>privateFun<!>()
}
inline fun testInternal() {
Z().privateProperty
Z().privateFun()
}
public class Z2 {
private val privateProperty = 11;
private fun privateFun() {
}
public inline fun test() {
<!INVISIBLE_MEMBER_FROM_INLINE!>privateProperty<!>
<!INVISIBLE_MEMBER_FROM_INLINE!>privateFun<!>()
}
inline fun testInternal() {
privateProperty
privateFun()
}
}
@@ -0,0 +1,15 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -NOTHING_TO_INLINE
public class Z {
private val privateProperty = 11;
public fun privateFun() {
class Local {
public inline fun a() {
privateProperty
}
}
}
}
@@ -3751,6 +3751,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
}
@TestMetadata("compiler/testData/diagnostics/tests/inline")
@InnerTestClasses({Inline.NonPublicMember.class})
public static class Inline extends AbstractDiagnosticsTestWithEagerResolve {
public void testAllFilesPresentInInline() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/inline"), Pattern.compile("^(.+)\\.kt$"), true);
@@ -3806,6 +3807,45 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/inline/wrongUsage2.kt");
}
@TestMetadata("compiler/testData/diagnostics/tests/inline/nonPublicMember")
public static class NonPublicMember extends AbstractDiagnosticsTestWithEagerResolve {
public void testAllFilesPresentInNonPublicMember() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/inline/nonPublicMember"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("inNonPublicClass.kt")
public void testInNonPublicClass() throws Exception {
doTest("compiler/testData/diagnostics/tests/inline/nonPublicMember/inNonPublicClass.kt");
}
@TestMetadata("inNonPublicInnerClass.kt")
public void testInNonPublicInnerClass() throws Exception {
doTest("compiler/testData/diagnostics/tests/inline/nonPublicMember/inNonPublicInnerClass.kt");
}
@TestMetadata("inPackage.kt")
public void testInPackage() throws Exception {
doTest("compiler/testData/diagnostics/tests/inline/nonPublicMember/inPackage.kt");
}
@TestMetadata("inPublicClass.kt")
public void testInPublicClass() throws Exception {
doTest("compiler/testData/diagnostics/tests/inline/nonPublicMember/inPublicClass.kt");
}
@TestMetadata("localClass.kt")
public void testLocalClass() throws Exception {
doTest("compiler/testData/diagnostics/tests/inline/nonPublicMember/localClass.kt");
}
}
public static Test innerSuite() {
TestSuite suite = new TestSuite("Inline");
suite.addTestSuite(Inline.class);
suite.addTestSuite(NonPublicMember.class);
return suite;
}
}
@TestMetadata("compiler/testData/diagnostics/tests/inner")
@@ -6313,7 +6353,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
suite.addTest(IncompleteCode.innerSuite());
suite.addTest(Inference.innerSuite());
suite.addTestSuite(Infos.class);
suite.addTestSuite(Inline.class);
suite.addTest(Inline.innerSuite());
suite.addTest(Inner.innerSuite());
suite.addTestSuite(J_k.class);
suite.addTest(Jdk_annotations.innerSuite());