Weaken PRIVATE_CLASS_MEMBER_FROM_INLINE diagnostic

This commit is contained in:
Michael Bogdanov
2016-02-11 17:41:03 +03:00
parent 384d2ea0d1
commit 4f0f81155a
7 changed files with 56 additions and 3 deletions
@@ -52,12 +52,13 @@ class InlineChecker implements CallChecker {
private final SimpleFunctionDescriptor descriptor; private final SimpleFunctionDescriptor descriptor;
private final Set<CallableDescriptor> inlinableParameters = new LinkedHashSet<CallableDescriptor>(); private final Set<CallableDescriptor> inlinableParameters = new LinkedHashSet<CallableDescriptor>();
private final boolean isEffectivelyPublicApiFunction; private final boolean isEffectivelyPublicApiFunction;
private final boolean isEffectivelyPrivateApiFunction;
public InlineChecker(@NotNull SimpleFunctionDescriptor descriptor) { public InlineChecker(@NotNull SimpleFunctionDescriptor descriptor) {
assert InlineUtil.isInline(descriptor) : "This extension should be created only for inline functions: " + descriptor; assert InlineUtil.isInline(descriptor) : "This extension should be created only for inline functions: " + descriptor;
this.descriptor = descriptor; this.descriptor = descriptor;
this.isEffectivelyPublicApiFunction = DescriptorUtilsKt.isEffectivelyPublicApi(descriptor); this.isEffectivelyPublicApiFunction = DescriptorUtilsKt.isEffectivelyPublicApi(descriptor);
this.isEffectivelyPrivateApiFunction = DescriptorUtilsKt.isEffectivelyPrivateApi(descriptor);
for (ValueParameterDescriptor param : descriptor.getValueParameters()) { for (ValueParameterDescriptor param : descriptor.getValueParameters()) {
if (isInlinableParameter(param)) { if (isInlinableParameter(param)) {
inlinableParameters.add(param); inlinableParameters.add(param);
@@ -253,7 +254,7 @@ class InlineChecker implements CallChecker {
@NotNull KtElement expression, @NotNull KtElement expression,
@NotNull BasicCallResolutionContext context @NotNull BasicCallResolutionContext context
) { ) {
if (!Visibilities.isPrivate(descriptor.getVisibility())) { if (!isEffectivelyPrivateApiFunction) {
if (DescriptorUtilsKt.isInsidePrivateClass(declarationDescriptor)) { if (DescriptorUtilsKt.isInsidePrivateClass(declarationDescriptor)) {
context.trace.report(Errors.PRIVATE_CLASS_MEMBER_FROM_INLINE.on(expression, declarationDescriptor, descriptor)); context.trace.report(Errors.PRIVATE_CLASS_MEMBER_FROM_INLINE.on(expression, declarationDescriptor, descriptor));
} }
@@ -0,0 +1,5 @@
import test.*
fun box() : String {
return Test().run()
}
@@ -0,0 +1,21 @@
package test
class Test {
private abstract class Base {
protected fun duplicate(s: String) = s + "K"
protected inline fun doInline(block: () -> String): String {
return duplicate(block())
}
}
private class Extender: Base() {
fun doSomething(): String {
return doInline { "O" }
}
}
fun run(): String {
return Extender().doSomething();
}
}
@@ -1381,6 +1381,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/private"), Pattern.compile("^(.+)\\.1.kt$"), true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/private"), Pattern.compile("^(.+)\\.1.kt$"), true);
} }
@TestMetadata("effectivePrivate.1.kt")
public void testEffectivePrivate() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/private/effectivePrivate.1.kt");
doTestMultiFileWithInlineCheck(fileName);
}
@TestMetadata("kt6453.1.kt") @TestMetadata("kt6453.1.kt")
public void testKt6453() throws Exception { public void testKt6453() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/private/kt6453.1.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/private/kt6453.1.kt");
@@ -1381,6 +1381,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/private"), Pattern.compile("^(.+)\\.1.kt$"), true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/private"), Pattern.compile("^(.+)\\.1.kt$"), true);
} }
@TestMetadata("effectivePrivate.1.kt")
public void testEffectivePrivate() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/private/effectivePrivate.1.kt");
doBoxTestWithInlineCheck(fileName);
}
@TestMetadata("kt6453.1.kt") @TestMetadata("kt6453.1.kt")
public void testKt6453() throws Exception { public void testKt6453() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/private/kt6453.1.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/private/kt6453.1.kt");
@@ -106,6 +106,20 @@ val DeclarationDescriptorWithVisibility.isEffectivelyPublicApi: Boolean
return true return true
} }
val DeclarationDescriptorWithVisibility.isEffectivelyPrivateApi: Boolean
get() {
var parent: DeclarationDescriptorWithVisibility? = this
while (parent != null) {
if (Visibilities.isPrivate(parent.visibility)) return true
parent = DescriptorUtils.getParentOfType(parent, DeclarationDescriptorWithVisibility::class.java)
}
return false
}
val DeclarationDescriptor.isInsidePrivateClass: Boolean val DeclarationDescriptor.isInsidePrivateClass: Boolean
get() { get() {
var parent = containingDeclaration as? ClassDescriptor var parent = containingDeclaration as? ClassDescriptor
@@ -1066,7 +1066,7 @@ fun main(args: Array<String>) {
} }
} }
internal class TestGroup(val testsRoot: String, val testDataRoot: String) { private class TestGroup(val testsRoot: String, val testDataRoot: String) {
inline fun <reified T: TestCase> testClass( inline fun <reified T: TestCase> testClass(
suiteTestClass: String = getDefaultSuiteTestClass(T::class.java), suiteTestClass: String = getDefaultSuiteTestClass(T::class.java),
noinline init: TestClass.() -> Unit noinline init: TestClass.() -> Unit