Reports warning on super calls in public-api inline functions
This commit is contained in:
@@ -1139,6 +1139,7 @@ public interface Errors {
|
||||
DiagnosticFactory1<PsiElement, CallableDescriptor> PROTECTED_CALL_FROM_PUBLIC_INLINE = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory1<PsiElement, CallableDescriptor> PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory1<PsiElement, CallableDescriptor> PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, CallableDescriptor> SUPER_CALL_FROM_PUBLIC_INLINE = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory2<KtElement, KtExpression, DeclarationDescriptor> INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory2<KtElement, KtExpression, DeclarationDescriptor> NOT_SUPPORTED_INLINE_PARAMETER_IN_INLINE_PARAMETER_DEFAULT_VALUE = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> PRIVATE_INLINE_FUNCTIONS_RETURNING_ANONYMOUS_OBJECTS = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
+1
@@ -1028,6 +1028,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(PROTECTED_CALL_FROM_PUBLIC_INLINE, "Protected function call from public-API inline function is deprecated", NAME);
|
||||
MAP.put(PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE, "Protected constructor call from public-API inline function is deprecated", NAME);
|
||||
MAP.put(PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR, "Protected function call from public-API inline function is prohibited", NAME);
|
||||
MAP.put(SUPER_CALL_FROM_PUBLIC_INLINE, "Accessing super members from public-API inline function is deprecated", NAME);
|
||||
MAP.put(INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE, "Invalid default value for inline parameter: ''{0}''. Only lambdas, anonymous functions, and callable references are supported", ELEMENT_TEXT, SHORT_NAMES_IN_TYPES);
|
||||
MAP.put(NOT_SUPPORTED_INLINE_PARAMETER_IN_INLINE_PARAMETER_DEFAULT_VALUE, "Usage of inline parameter ''{0}'' in default value for another inline parameter is not supported", ELEMENT_TEXT, SHORT_NAMES_IN_TYPES);
|
||||
MAP.put(PRIVATE_INLINE_FUNCTIONS_RETURNING_ANONYMOUS_OBJECTS, "Return type of the private inline function can't be anonymous. It will be approximated to Any in a future release. See KT-33917 for more details");
|
||||
|
||||
@@ -25,7 +25,9 @@ import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getSuperCallExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
@@ -39,6 +41,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
@@ -60,7 +63,8 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
|
||||
private var prohibitProtectedCallFromInline by Delegates.notNull<Boolean>()
|
||||
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val expression = resolvedCall.call.calleeExpression ?: return
|
||||
val call = resolvedCall.call
|
||||
val expression = call.calleeExpression ?: return
|
||||
|
||||
supportDefaultValueInline = context.languageVersionSettings.supportsFeature(LanguageFeature.InlineDefaultFunctionalParameters)
|
||||
prohibitProtectedCallFromInline = context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitProtectedCallFromInline)
|
||||
@@ -90,7 +94,7 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
|
||||
}
|
||||
}
|
||||
|
||||
checkVisibilityAndAccess(targetDescriptor, expression, context)
|
||||
checkVisibilityAndAccess(targetDescriptor, expression, context, call)
|
||||
checkRecursion(context, targetDescriptor, expression)
|
||||
}
|
||||
|
||||
@@ -248,7 +252,8 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
|
||||
private fun checkVisibilityAndAccess(
|
||||
calledDescriptor: CallableDescriptor,
|
||||
expression: KtElement,
|
||||
context: CallCheckerContext
|
||||
context: CallCheckerContext,
|
||||
call: Call
|
||||
) {
|
||||
val calledFunEffectiveVisibility = if (isDefinedInInlineFunction(calledDescriptor))
|
||||
EffectiveVisibility.Public
|
||||
@@ -263,6 +268,9 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
|
||||
context.trace.report(NON_PUBLIC_CALL_FROM_PUBLIC_INLINE.on(expression, calledDescriptor, descriptor))
|
||||
} else {
|
||||
checkPrivateClassMemberAccess(calledDescriptor, expression, context)
|
||||
if (isInlineFunPublicOrPublishedApi) {
|
||||
checkSuperCalls(calledDescriptor, call, expression, context)
|
||||
}
|
||||
}
|
||||
|
||||
val isConstructorCall = calledDescriptor is ConstructorDescriptor
|
||||
@@ -296,6 +304,27 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkSuperCalls(
|
||||
callableDescriptor: CallableDescriptor,
|
||||
call: Call,
|
||||
expression: KtElement,
|
||||
context: CallCheckerContext
|
||||
) {
|
||||
val superCall = getSuperCallExpression(call)
|
||||
if (superCall != null) {
|
||||
val thisTypeForSuperCall: KotlinType =
|
||||
context.trace.get(
|
||||
BindingContext.THIS_TYPE_FOR_SUPER_EXPRESSION,
|
||||
superCall
|
||||
) ?: return
|
||||
val descriptor = thisTypeForSuperCall.constructor.declarationDescriptor as? DeclarationDescriptorWithVisibility ?: return
|
||||
|
||||
if (!isDefinedInInlineFunction(descriptor)) {
|
||||
context.trace.report(SUPER_CALL_FROM_PUBLIC_INLINE.on(expression.parent.parent ?: superCall, callableDescriptor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isDefinedInInlineFunction(startDescriptor: DeclarationDescriptorWithVisibility): Boolean {
|
||||
var parent: DeclarationDescriptorWithVisibility? = startDescriptor
|
||||
|
||||
|
||||
Reference in New Issue
Block a user