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.diagnostics.Errors;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
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.context.BasicCallResolutionContext;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ExpressionValueArgument;
|
import org.jetbrains.jet.lang.resolve.calls.model.ExpressionValueArgument;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
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 Set<DeclarationDescriptor> inlinableParameters = new HashSet<DeclarationDescriptor>();
|
||||||
|
|
||||||
|
private final boolean isEffectivelyPublicApiFunction;
|
||||||
|
|
||||||
public InlineCallResolverExtension(@NotNull SimpleFunctionDescriptor descriptor) {
|
public InlineCallResolverExtension(@NotNull SimpleFunctionDescriptor descriptor) {
|
||||||
assert descriptor.isInline() : "This extension should be created only for inline functions but not " + descriptor;
|
assert descriptor.isInline() : "This extension should be created only for inline functions but not " + descriptor;
|
||||||
|
|
||||||
this.descriptor = descriptor;
|
this.descriptor = descriptor;
|
||||||
|
this.isEffectivelyPublicApiFunction = isEffectivelyPublicApi(descriptor);
|
||||||
|
|
||||||
Iterator<ValueParameterDescriptor> iterator = descriptor.getValueParameters().iterator();
|
Iterator<ValueParameterDescriptor> iterator = descriptor.getValueParameters().iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
ValueParameterDescriptor next = iterator.next();
|
ValueParameterDescriptor next = iterator.next();
|
||||||
@@ -102,9 +106,10 @@ public class InlineCallResolverExtension implements CallResolverExtension {
|
|||||||
checkFunctionCall(context, targetDescriptor, jetExpression);
|
checkFunctionCall(context, targetDescriptor, jetExpression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO default and vararg
|
//TODO default and vararg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkVisibility(targetDescriptor, expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkCallWithReceiver(
|
private void checkCallWithReceiver(
|
||||||
@@ -179,11 +184,20 @@ public class InlineCallResolverExtension implements CallResolverExtension {
|
|||||||
((SimpleFunctionDescriptor) descriptor).isInline();
|
((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")
|
@TestMetadata("compiler/testData/diagnostics/tests/inline")
|
||||||
|
@InnerTestClasses({Inline.NonPublicMember.class})
|
||||||
public static class Inline extends AbstractDiagnosticsTestWithEagerResolve {
|
public static class Inline extends AbstractDiagnosticsTestWithEagerResolve {
|
||||||
public void testAllFilesPresentInInline() throws Exception {
|
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);
|
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");
|
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")
|
@TestMetadata("compiler/testData/diagnostics/tests/inner")
|
||||||
@@ -6313,7 +6353,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
suite.addTest(IncompleteCode.innerSuite());
|
suite.addTest(IncompleteCode.innerSuite());
|
||||||
suite.addTest(Inference.innerSuite());
|
suite.addTest(Inference.innerSuite());
|
||||||
suite.addTestSuite(Infos.class);
|
suite.addTestSuite(Infos.class);
|
||||||
suite.addTestSuite(Inline.class);
|
suite.addTest(Inline.innerSuite());
|
||||||
suite.addTest(Inner.innerSuite());
|
suite.addTest(Inner.innerSuite());
|
||||||
suite.addTestSuite(J_k.class);
|
suite.addTestSuite(J_k.class);
|
||||||
suite.addTest(Jdk_annotations.innerSuite());
|
suite.addTest(Jdk_annotations.innerSuite());
|
||||||
|
|||||||
Reference in New Issue
Block a user