Fix INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER diagnostic in IDE

This commit is contained in:
Mikhael Bogdanov
2021-10-30 16:53:46 +02:00
parent 40158d1ce6
commit 2258e26799
2 changed files with 21 additions and 11 deletions
@@ -16,10 +16,10 @@
package org.jetbrains.kotlin.resolve.jvm.checkers
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.JvmAnalysisFlags
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
@@ -32,14 +32,16 @@ import org.jetbrains.kotlin.psi.KtSuperExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils.*
import org.jetbrains.kotlin.resolve.LanguageVersionSettingsProvider
import org.jetbrains.kotlin.resolve.calls.util.getSuperCallExpression
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.jvm.annotations.isCompiledToJvmDefault
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.*
class InterfaceDefaultMethodCallChecker(val jvmTarget: JvmTarget) : CallChecker {
class InterfaceDefaultMethodCallChecker(val jvmTarget: JvmTarget, private val project: Project) : CallChecker {
private val ideService = LanguageVersionSettingsProvider.getInstance(project)
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
val supportDefaults = jvmTarget >= JvmTarget.JVM_1_8
@@ -62,13 +64,15 @@ class InterfaceDefaultMethodCallChecker(val jvmTarget: JvmTarget) : CallChecker
val realDescriptorOwner = realDescriptor.containingDeclaration as? ClassDescriptor ?: return
val jvmDefaultMode = context.languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode)
if (isInterface(realDescriptorOwner) && (realDescriptor is JavaCallableMemberDescriptor || realDescriptor.isCompiledToJvmDefault(jvmDefaultMode))) {
if (isInterface(realDescriptorOwner) && (realDescriptor is JavaCallableMemberDescriptor ||
realDescriptor.isCompiledToJvmDefaultWithProperMode(ideService, jvmDefaultMode))
) {
val bindingContext = context.trace.bindingContext
val thisForSuperCall = getSuperCallLabelTarget(bindingContext, superCallExpression)
if (thisForSuperCall != null && DescriptorUtils.isInterface(thisForSuperCall)) {
val declarationWithCall = findInterfaceMember(thisForSuperCall, superCallExpression, bindingContext)
if (declarationWithCall?.isCompiledToJvmDefault(jvmDefaultMode) == false) {
if (declarationWithCall?.isCompiledToJvmDefaultWithProperMode(ideService, jvmDefaultMode) == false) {
context.trace.report(INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER.on(reportOn))
return
}
@@ -232,11 +232,17 @@ class JvmDefaultChecker(private val jvmTarget: JvmTarget, private val project: P
}
}
private fun CallableMemberDescriptor.isCompiledToJvmDefaultWithProperMode(compilationDefaultMode: JvmDefaultMode): Boolean {
val jvmDefault =
if (this is DeserializedDescriptor) compilationDefaultMode/*doesn't matter*/ else ideService?.getModuleLanguageVersionSettings(module)
?.getFlag(JvmAnalysisFlags.jvmDefaultMode) ?: compilationDefaultMode
return isCompiledToJvmDefault(jvmDefault)
}
private fun CallableMemberDescriptor.isCompiledToJvmDefaultWithProperMode(compilationDefaultMode: JvmDefaultMode) =
isCompiledToJvmDefaultWithProperMode(ideService, compilationDefaultMode)
}
internal fun CallableMemberDescriptor.isCompiledToJvmDefaultWithProperMode(
ideService: LanguageVersionSettingsProvider?,
compilationDefaultMode: JvmDefaultMode
): Boolean {
val jvmDefault =
if (this is DeserializedDescriptor) compilationDefaultMode/*doesn't matter*/ else ideService?.getModuleLanguageVersionSettings(module)
?.getFlag(JvmAnalysisFlags.jvmDefaultMode) ?: compilationDefaultMode
return isCompiledToJvmDefault(jvmDefault)
}