Don't report "Unsafe call with ? extension receiver" with smart-cast

#KT-29499 Fixed
This commit is contained in:
Mikhail Glukhikh
2019-03-01 17:08:20 +03:00
parent 4d19120d84
commit c714e599ea
2 changed files with 20 additions and 3 deletions
@@ -16,12 +16,17 @@ import com.intellij.ui.EditorTextField
import org.intellij.lang.regexp.RegExpFileType import org.intellij.lang.regexp.RegExpFileType
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.quickfix.AddExclExclCallFix import org.jetbrains.kotlin.idea.quickfix.AddExclExclCallFix
import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
import org.jetbrains.kotlin.psi.KtVisitorVoid import org.jetbrains.kotlin.psi.KtVisitorVoid
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.isNullabilityFlexible import org.jetbrains.kotlin.types.isNullabilityFlexible
import java.awt.BorderLayout import java.awt.BorderLayout
import java.util.regex.PatternSyntaxException import java.util.regex.PatternSyntaxException
@@ -46,7 +51,8 @@ class PlatformExtensionReceiverOfInlineInspection : AbstractKotlinInspection() {
override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression) { override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression) {
super.visitDotQualifiedExpression(expression) super.visitDotQualifiedExpression(expression)
if (!expression.languageVersionSettings.supportsFeature(LanguageFeature.NullabilityAssertionOnExtensionReceiver)) { val languageVersionSettings = expression.languageVersionSettings
if (!languageVersionSettings.supportsFeature(LanguageFeature.NullabilityAssertionOnExtensionReceiver)) {
return return
} }
val nameRegex = nameRegex val nameRegex = nameRegex
@@ -56,13 +62,19 @@ class PlatformExtensionReceiverOfInlineInspection : AbstractKotlinInspection() {
return return
} }
val resolvedCall = expression.resolveToCall() ?: return val context = expression.analyze(BodyResolveMode.PARTIAL)
val resolvedCall = expression.getResolvedCall(context) ?: return
val extensionReceiverType = resolvedCall.extensionReceiver?.type ?: return val extensionReceiverType = resolvedCall.extensionReceiver?.type ?: return
if (!extensionReceiverType.isNullabilityFlexible()) return if (!extensionReceiverType.isNullabilityFlexible()) return
val descriptor = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return val descriptor = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return
if (!descriptor.isInline) return if (!descriptor.isInline) return
val receiverExpression = expression.receiverExpression val receiverExpression = expression.receiverExpression
val dataFlowValueFactory = receiverExpression.getResolutionFacade().getFrontendService(DataFlowValueFactory::class.java)
val dataFlow = dataFlowValueFactory.createDataFlowValue(receiverExpression, extensionReceiverType, context, descriptor)
val stableNullability = context.getDataFlowInfoBefore(receiverExpression).getStableNullability(dataFlow)
if (!stableNullability.canBeNull()) return
holder.registerProblem( holder.registerProblem(
receiverExpression, receiverExpression,
"Call of inline function with nullable extension receiver can provoke NPE in Kotlin 1.2+", "Call of inline function with nullable extension receiver can provoke NPE in Kotlin 1.2+",
@@ -6,6 +6,11 @@ fun test() {
JavaClass.getNull().contentNotInline() // OK JavaClass.getNull().contentNotInline() // OK
JavaClass.getMy().contentNonExtensionInlineFun() // OK JavaClass.getMy().contentNonExtensionInlineFun() // OK
val res = JavaClass.getNull()
if (res != null) {
res.toBoolean() // OK: KT-29499
}
} }
fun String.contentNotInline() {} fun String.contentNotInline() {}