From f4259c5f8268c945562bd87c001511af5555261f Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Fri, 2 Dec 2016 16:37:37 +0100 Subject: [PATCH] Added deprecation for protected call within inline functions --- .../jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../resolve/calls/checkers/InlineChecker.java | 5 +- .../tests/inline/protectedDepecation.kt | 57 +++++++++++++++++++ .../tests/inline/protectedDepecation.txt | 40 +++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 ++ 6 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/diagnostics/tests/inline/protectedDepecation.kt create mode 100644 compiler/testData/diagnostics/tests/inline/protectedDepecation.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 992e67b35ec..22ab0815a55 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -866,6 +866,7 @@ public interface Errors { DiagnosticFactory0 NON_LOCAL_RETURN_IN_DISABLED_INLINE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INLINE_PROPERTY_WITH_BACKING_FIELD = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); DiagnosticFactory0 NON_INTERNAL_PUBLISHED_API = DiagnosticFactory0.create(ERROR); + DiagnosticFactory1 PROTECTED_CALL_FROM_PUBLIC_INLINE = DiagnosticFactory1.create(WARNING); DiagnosticFactory0 NON_LOCAL_SUSPENSION_POINT = DiagnosticFactory0.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 1b1287788b2..2958237f1bd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -832,6 +832,7 @@ public class DefaultErrorMessages { MAP.put(RECURSION_IN_INLINE, "Inline function ''{1}'' cannot be recursive", ELEMENT_TEXT, SHORT_NAMES_IN_TYPES); MAP.put(INLINE_PROPERTY_WITH_BACKING_FIELD, "Inline property cannot have backing field"); MAP.put(NON_INTERNAL_PUBLISHED_API, "@PublishedApi annotation is only applicable for internal declaration"); + MAP.put(PROTECTED_CALL_FROM_PUBLIC_INLINE, "Protected function call from public-API inline function is deprecated", NAME); //Inline non locals MAP.put(NON_LOCAL_RETURN_NOT_ALLOWED, "Can''t inline ''{0}'' here: it may contain non-local returns. Add ''crossinline'' modifier to parameter declaration ''{0}''", ELEMENT_TEXT); MAP.put(INLINE_CALL_CYCLE, "The ''{0}'' invocation is a part of inline cycle", NAME); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java index 9b14338be36..eee41141faa 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.resolve.calls.checkers; import com.intellij.psi.PsiElement; -import com.sun.mirror.declaration.PackageDeclaration; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.FunctionTypesKt; @@ -254,6 +253,10 @@ class InlineChecker implements CallChecker { else { checkPrivateClassMemberAccess(declarationDescriptor, expression, context); } + + if (isEffectivelyPublicOrPublishedApiFunction && declarationDescriptor.getVisibility() == Visibilities.PROTECTED) { + context.getTrace().report(Errors.PROTECTED_CALL_FROM_PUBLIC_INLINE.on(expression, declarationDescriptor)); + } } private static boolean isEffectivelyPublicOrPublishedApi(@NotNull CallableDescriptor descriptor) { diff --git a/compiler/testData/diagnostics/tests/inline/protectedDepecation.kt b/compiler/testData/diagnostics/tests/inline/protectedDepecation.kt new file mode 100644 index 00000000000..8c9f031ffc2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inline/protectedDepecation.kt @@ -0,0 +1,57 @@ +// !DIAGNOSTICS: -EXPOSED_PARAMETER_TYPE -NOTHING_TO_INLINE + +open class A { + protected fun test() {} + + protected val z: String = "1" + + public var zVar: String = "1" + protected set(value) {} + + inline fun call() { + test() + z + zVar + zVar = "123" + } + + internal inline fun callFromInternal() { + test() + zVar + zVar = "123" + } + + @PublishedApi + internal inline fun callFromPublished() { + test() + z + zVar + zVar = "123" + } +} + +class B : A() { + inline fun testB() { + test() + } +} + + +internal class AInternal { + protected fun test() {} + + protected val z: String = "1" + + public var zVar: String = "1" + protected set(value) {} + + + inline fun call() { + test() + } + + @PublishedApi + internal inline fun call2() { + test() + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inline/protectedDepecation.txt b/compiler/testData/diagnostics/tests/inline/protectedDepecation.txt new file mode 100644 index 00000000000..8a3b53cf962 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inline/protectedDepecation.txt @@ -0,0 +1,40 @@ +package + +public open class A { + public constructor A() + protected final val z: kotlin.String = "1" + public final var zVar: kotlin.String + public final inline fun call(): kotlin.Unit + internal final inline fun callFromInternal(): kotlin.Unit + @kotlin.PublishedApi internal final inline fun callFromPublished(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + protected final fun test(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal final class AInternal { + public constructor AInternal() + protected final val z: kotlin.String = "1" + public final var zVar: kotlin.String + public final inline fun call(): kotlin.Unit + @kotlin.PublishedApi internal final inline fun call2(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + protected final fun test(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class B : A { + public constructor B() + protected final override /*1*/ /*fake_override*/ val z: kotlin.String + public final override /*1*/ /*fake_override*/ var zVar: kotlin.String + public final inline override /*1*/ /*fake_override*/ fun call(): kotlin.Unit + internal final inline override /*1*/ /*fake_override*/ fun callFromInternal(): kotlin.Unit + @kotlin.PublishedApi internal final inline override /*1*/ /*fake_override*/ fun callFromPublished(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + protected final override /*1*/ /*fake_override*/ fun test(): kotlin.Unit + public final inline fun testB(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index ee8439452b2..0d67fcca864 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10618,6 +10618,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("protectedDepecation.kt") + public void testProtectedDepecation() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/protectedDepecation.kt"); + doTest(fileName); + } + @TestMetadata("publishedApi.kt") public void testPublishedApi() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/publishedApi.kt");