K2: report INCOMPATIBLE_CLASS in JVM

#KT-60795
This commit is contained in:
Alexander Udalov
2023-08-01 01:12:34 +02:00
committed by Space Team
parent db8fb30343
commit 7d60b5df43
19 changed files with 262 additions and 29 deletions
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
/*
* This file was generated automatically
@@ -120,6 +121,7 @@ object FirJvmErrors {
val SPREAD_ON_SIGNATURE_POLYMORPHIC_CALL by deprecationError0<PsiElement>(ProhibitSpreadOnSignaturePolymorphicCall, SourceElementPositioningStrategies.SPREAD_OPERATOR)
val JAVA_SAM_INTERFACE_CONSTRUCTOR_REFERENCE by error0<PsiElement>()
val NO_REFLECTION_IN_CLASS_PATH by warning0<PsiElement>()
val INCOMPATIBLE_CLASS by error2<PsiElement, String, IncompatibleVersionErrorData<*>>()
init {
RootDiagnosticRendererFactory.registerFactory(FirJvmErrorsDefaultMessages)
@@ -5,10 +5,12 @@
package org.jetbrains.kotlin.fir.analysis.diagnostics.jvm
import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
import org.jetbrains.kotlin.diagnostics.KtDiagnosticRenderers.TO_STRING
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
import org.jetbrains.kotlin.diagnostics.rendering.Renderer
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOL
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.CONCURRENT_HASH_MAP_CONTAINS_OPERATOR
@@ -27,6 +29,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.ILLEGAL_JV
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INAPPLICABLE_JVM_FIELD
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INAPPLICABLE_JVM_FIELD_WARNING
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INAPPLICABLE_JVM_NAME
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INCOMPATIBLE_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INNER_JVM_RECORD
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_SAM_INTERFACE_CONSTRUCTOR_REFERENCE
@@ -79,6 +82,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZ
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_ON_SUSPEND
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.UPPER_BOUND_CANNOT_BE_ARRAY
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
object FirJvmErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
@@ -263,5 +267,17 @@ object FirJvmErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
"Call uses reflection API which is not found in compilation classpath. " +
"Make sure you have kotlin-reflect.jar in the classpath."
)
map.put(
INCOMPATIBLE_CLASS,
"{0} was compiled with an incompatible version of Kotlin. {1}",
STRING,
Renderer { incompatibility: IncompatibleVersionErrorData<*> ->
"The actual metadata version is ${incompatibility.actualVersion}, " +
"but the compiler version ${incompatibility.compilerVersion}" +
(if (incompatibility.languageVersion == incompatibility.compilerVersion) "" else " [with language version " + incompatibility.languageVersion + "]") +
" can read versions up to ${incompatibility.expectedVersion}.\n" +
"The class is loaded from ${FileUtil.toSystemIndependentName(incompatibility.filePath)}"
}
)
}
}
@@ -19,6 +19,7 @@ object JvmExpressionCheckers : ExpressionCheckers() {
get() = setOf(
FirInterfaceDefaultMethodCallChecker,
FirJavaSamInterfaceConstructorReferenceChecker,
FirIncompatibleClassExpressionChecker,
)
override val callableReferenceAccessCheckers: Set<FirCallableReferenceAccessChecker>
@@ -8,10 +8,12 @@ package org.jetbrains.kotlin.fir.analysis.jvm.checkers
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirDynamicUnsupportedChecker
import org.jetbrains.kotlin.fir.analysis.checkers.type.*
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.type.FirFunctionalTypeParameterNameChecker
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.type.FirJvmIncompatibleClassTypeChecker
object JvmTypeCheckers : TypeCheckers() {
override val typeRefCheckers: Set<FirTypeRefChecker> = setOf(
FirDynamicUnsupportedChecker,
FirFunctionalTypeParameterNameChecker,
FirJvmIncompatibleClassTypeChecker,
)
}
@@ -0,0 +1,54 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirQualifiedAccessExpressionChecker
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
import org.jetbrains.kotlin.fir.declarations.utils.sourceElement
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
object FirIncompatibleClassExpressionChecker : FirQualifiedAccessExpressionChecker() {
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
val symbol = expression.calleeReference.toResolvedCallableSymbol() ?: return
checkType(symbol.resolvedReturnType, expression, context, reporter)
checkType(symbol.receiverParameter?.typeRef?.coneType, expression, context, reporter)
if (symbol is FirFunctionSymbol) {
for (parameter in symbol.valueParameterSymbols) {
checkType(parameter.resolvedReturnTypeRef.type, expression, context, reporter)
}
}
@OptIn(SymbolInternals::class)
checkSourceElement(symbol.fir.containerSource, expression, context, reporter)
}
internal fun checkType(type: ConeKotlinType?, element: FirElement, context: CheckerContext, reporter: DiagnosticReporter) {
val classSymbol = type?.toRegularClassSymbol(context.session)
checkSourceElement(classSymbol?.sourceElement, element, context, reporter)
}
private fun checkSourceElement(source: SourceElement?, element: FirElement, context: CheckerContext, reporter: DiagnosticReporter) {
if (source !is DeserializedContainerSource) return
val incompatibility = source.incompatibility
if (incompatibility != null) {
reporter.reportOn(element.source, FirJvmErrors.INCOMPATIBLE_CLASS, source.presentableString, incompatibility, context)
}
}
}
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.type
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.type.FirTypeRefChecker
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression.FirIncompatibleClassExpressionChecker
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeOrNull
object FirJvmIncompatibleClassTypeChecker : FirTypeRefChecker() {
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
FirIncompatibleClassExpressionChecker.checkType(typeRef.coneTypeOrNull, typeRef, context, reporter)
}
}