Inline visibility checking
This commit is contained in:
+20
-6
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user