K1: add deprecation for implicit non-public calls #KT-54762 Fixed

This commit is contained in:
Mikhail Glukhikh
2022-11-15 16:40:15 +01:00
committed by Space Team
parent f4b5f5ff5d
commit ac514849f4
10 changed files with 187 additions and 6 deletions
@@ -375,6 +375,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/initializedAfterRethrow.kt");
}
@Test
@TestMetadata("inlineDeprecationsOnImplicitCalls.kt")
public void testInlineDeprecationsOnImplicitCalls() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineDeprecationsOnImplicitCalls.kt");
}
@Test
@TestMetadata("InvokeAndRecursiveResolve.kt")
public void testInvokeAndRecursiveResolve() throws Exception {
@@ -375,6 +375,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/initializedAfterRethrow.kt");
}
@Test
@TestMetadata("inlineDeprecationsOnImplicitCalls.kt")
public void testInlineDeprecationsOnImplicitCalls() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineDeprecationsOnImplicitCalls.kt");
}
@Test
@TestMetadata("InvokeAndRecursiveResolve.kt")
public void testInvokeAndRecursiveResolve() throws Exception {
@@ -375,6 +375,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/initializedAfterRethrow.kt");
}
@Test
@TestMetadata("inlineDeprecationsOnImplicitCalls.kt")
public void testInlineDeprecationsOnImplicitCalls() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineDeprecationsOnImplicitCalls.kt");
}
@Test
@TestMetadata("InvokeAndRecursiveResolve.kt")
public void testInvokeAndRecursiveResolve() throws Exception {
@@ -1272,6 +1272,7 @@ public interface Errors {
//Inline and inlinable parameters
DiagnosticFactory2<KtElement, DeclarationDescriptor, DeclarationDescriptor> NON_PUBLIC_CALL_FROM_PUBLIC_INLINE =
DiagnosticFactory2.create(ERROR, CALL_ELEMENT);
DiagnosticFactory0<KtElement> DEPRECATED_IMPLICIT_NON_PUBLIC_API_ACCESS = DiagnosticFactory0.create(WARNING, CALL_ELEMENT);
DiagnosticFactory2<KtElement, DeclarationDescriptor, DeclarationDescriptor> PRIVATE_CLASS_MEMBER_FROM_INLINE =
DiagnosticFactory2.create(ERROR, CALL_ELEMENT);
DiagnosticFactory1<KtElement, KtElement> NON_LOCAL_RETURN_NOT_ALLOWED = DiagnosticFactory1.create(ERROR, CALL_ELEMENT);
@@ -1106,6 +1106,7 @@ public class DefaultErrorMessages {
//Inline
MAP.put(NON_PUBLIC_CALL_FROM_PUBLIC_INLINE, "Public-API inline function cannot access non-public-API ''{0}''", SHORT_NAMES_IN_TYPES, SHORT_NAMES_IN_TYPES);
MAP.put(DEPRECATED_IMPLICIT_NON_PUBLIC_API_ACCESS, "Deprecated implicit access of non-public-API from public-API inline function");
MAP.put(PRIVATE_CLASS_MEMBER_FROM_INLINE, "Non-private inline function cannot access members of private classes: ''{0}''", SHORT_NAMES_IN_TYPES, SHORT_NAMES_IN_TYPES);
MAP.put(NOT_YET_SUPPORTED_IN_INLINE, "{0} are not yet supported in inline functions", STRING);
MAP.put(DECLARATION_CANT_BE_INLINED, "'inline' modifier is not allowed on virtual members. Only private or final members can be inlined");
@@ -91,8 +91,9 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
}
}
checkVisibilityAndAccess(targetDescriptor, expression, context, call)
checkRecursion(context, targetDescriptor, expression)
val replacementForReport = (call.dispatchReceiver as? ExpressionReceiver)?.expression
checkVisibilityAndAccess(targetDescriptor, expression, replacementForReport, context, call)
checkRecursion(context, targetDescriptor, expression, replacementForReport)
}
private fun checkNotInDefaultParameter(context: CallCheckerContext, expression: KtExpression) =
@@ -233,10 +234,12 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
private fun checkRecursion(
context: CallCheckerContext,
targetDescriptor: CallableDescriptor,
expression: KtElement
expression: KtElement,
replacementForReport: KtElement?
) {
if (targetDescriptor.original === descriptor) {
context.trace.report(RECURSION_IN_INLINE.on(expression, expression, descriptor))
context.reportDeprecationOnReplacement(expression, replacementForReport)
}
}
@@ -255,6 +258,7 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
private fun checkVisibilityAndAccess(
calledDescriptor: CallableDescriptor,
expression: KtElement,
replacementForReport: KtElement?,
context: CallCheckerContext,
call: Call
) {
@@ -267,10 +271,12 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
val isInlineFunPublicOrPublishedApi = inlineFunEffectiveVisibility.publicApi
if (isInlineFunPublicOrPublishedApi &&
!isCalledFunPublicOrPublishedApi &&
calledDescriptor.visibility !== DescriptorVisibilities.LOCAL) {
calledDescriptor.visibility !== DescriptorVisibilities.LOCAL
) {
context.trace.report(NON_PUBLIC_CALL_FROM_PUBLIC_INLINE.on(expression, calledDescriptor, descriptor))
context.reportDeprecationOnReplacement(expression, replacementForReport)
} else {
checkPrivateClassMemberAccess(calledDescriptor, expression, context)
checkPrivateClassMemberAccess(calledDescriptor, expression, replacementForReport, context)
if (isInlineFunPublicOrPublishedApi) {
checkSuperCalls(calledDescriptor, call, expression, context)
}
@@ -280,7 +286,8 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
if ((!isConstructorCall || expression !is KtConstructorCalleeExpression) &&
isInlineFunPublicOrPublishedApi &&
inlineFunEffectiveVisibility.toVisibility() !== Visibilities.Protected &&
calledFunEffectiveVisibility.toVisibility() === Visibilities.Protected) {
calledFunEffectiveVisibility.toVisibility() === Visibilities.Protected
) {
when {
isConstructorCall -> {
context.trace.report(
@@ -293,17 +300,20 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
)
}
}
context.reportDeprecationOnReplacement(expression, replacementForReport)
}
}
private fun checkPrivateClassMemberAccess(
declarationDescriptor: DeclarationDescriptor,
expression: KtElement,
replacementForReport: KtElement?,
context: CallCheckerContext
) {
if (!isEffectivelyPrivateApiFunction) {
if (declarationDescriptor.isInsidePrivateClass) {
context.trace.report(PRIVATE_CLASS_MEMBER_FROM_INLINE.on(expression, declarationDescriptor, descriptor))
context.reportDeprecationOnReplacement(expression, replacementForReport)
}
}
}
@@ -356,4 +366,13 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
context.trace.report(NON_LOCAL_RETURN_NOT_ALLOWED.on(parameterUsage, parameterUsage))
}
}
private fun CallCheckerContext.reportDeprecationOnReplacement(
expression: KtElement,
replacementForReport: KtElement?
) {
if (!expression.isPhysical && replacementForReport != null) {
trace.report(DEPRECATED_IMPLICIT_NON_PUBLIC_API_ACCESS.on(replacementForReport))
}
}
}
@@ -0,0 +1,42 @@
// !DIAGNOSTICS: -NOTHING_TO_INLINE
@PublishedApi
internal class InternalClassPrivateConstructor private constructor() {
companion object {
internal inline operator fun invoke(): InternalClassPrivateConstructor = InternalClassPrivateConstructor()
internal inline operator fun invoke(i: Int): InternalClassPrivateConstructor = <!RECURSION_IN_INLINE!>InternalClassPrivateConstructor<!>(i)
}
}
private class PrivateClass public constructor() {
operator fun invoke() = 42
}
open class OpenClass {
protected operator fun invoke() = 42
inline fun foo() {
<!PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR!>this<!>()
}
}
@PublishedApi
internal open class InternalClassProtectedConstructor protected constructor() {
companion object {
internal inline operator fun invoke(): InternalClassProtectedConstructor = InternalClassProtectedConstructor()
}
}
inline fun publicInline() {
<!NON_PUBLIC_CALL_FROM_PUBLIC_INLINE!>InternalClassPrivateConstructor<!>()
InternalClassPrivateConstructor.<!NON_PUBLIC_CALL_FROM_PUBLIC_INLINE!>invoke<!>()
<!NON_PUBLIC_CALL_FROM_PUBLIC_INLINE!>InternalClassProtectedConstructor<!>()
}
internal inline fun internalInline() {
val pc = <!PRIVATE_CLASS_MEMBER_FROM_INLINE!>PrivateClass<!>()
<!PRIVATE_CLASS_MEMBER_FROM_INLINE!>pc<!>()
}
@@ -0,0 +1,42 @@
// !DIAGNOSTICS: -NOTHING_TO_INLINE
@PublishedApi
internal class InternalClassPrivateConstructor private constructor() {
companion object {
internal inline operator fun invoke(): InternalClassPrivateConstructor = InternalClassPrivateConstructor()
internal inline operator fun invoke(i: Int): InternalClassPrivateConstructor = <!DEPRECATED_IMPLICIT_NON_PUBLIC_API_ACCESS!>InternalClassPrivateConstructor<!>(i)
}
}
private class PrivateClass public constructor() {
operator fun invoke() = 42
}
open class OpenClass {
protected operator fun invoke() = 42
inline fun foo() {
<!DEPRECATED_IMPLICIT_NON_PUBLIC_API_ACCESS!>this<!>()
}
}
@PublishedApi
internal open class InternalClassProtectedConstructor protected constructor() {
companion object {
internal inline operator fun invoke(): InternalClassProtectedConstructor = InternalClassProtectedConstructor()
}
}
inline fun publicInline() {
<!DEPRECATED_IMPLICIT_NON_PUBLIC_API_ACCESS!>InternalClassPrivateConstructor<!>()
InternalClassPrivateConstructor.<!NON_PUBLIC_CALL_FROM_PUBLIC_INLINE!>invoke<!>()
<!DEPRECATED_IMPLICIT_NON_PUBLIC_API_ACCESS!>InternalClassProtectedConstructor<!>()
}
internal inline fun internalInline() {
val pc = <!PRIVATE_CLASS_MEMBER_FROM_INLINE!>PrivateClass<!>()
<!DEPRECATED_IMPLICIT_NON_PUBLIC_API_ACCESS!>pc<!>()
}
@@ -0,0 +1,52 @@
package
internal inline fun internalInline(): kotlin.Unit
public inline fun publicInline(): kotlin.Unit
@kotlin.PublishedApi internal final class InternalClassPrivateConstructor {
private constructor InternalClassPrivateConstructor()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public companion object Companion {
private constructor Companion()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
internal final inline operator fun invoke(): InternalClassPrivateConstructor
internal final inline operator fun invoke(/*0*/ i: kotlin.Int): InternalClassPrivateConstructor
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@kotlin.PublishedApi internal open class InternalClassProtectedConstructor {
protected constructor InternalClassProtectedConstructor()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public companion object Companion {
private constructor Companion()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
internal final inline operator fun invoke(): InternalClassProtectedConstructor
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
public open class OpenClass {
public constructor OpenClass()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final inline fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
protected final operator fun invoke(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
private final class PrivateClass {
public constructor PrivateClass()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final operator fun invoke(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -375,6 +375,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/initializedAfterRethrow.kt");
}
@Test
@TestMetadata("inlineDeprecationsOnImplicitCalls.kt")
public void testInlineDeprecationsOnImplicitCalls() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineDeprecationsOnImplicitCalls.kt");
}
@Test
@TestMetadata("InvokeAndRecursiveResolve.kt")
public void testInvokeAndRecursiveResolve() throws Exception {