Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,12 @@ private fun KaDiagnosticConverterBuilder.addConversions20() {
token,
)
}
add(FirJvmErrors.JAVA_CLASS_PROPERTY_REFERENCE.warningFactory) { firDiagnostic ->
JavaClassPropertyReferenceWarningImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirWebCommonErrors.NESTED_JS_EXPORT) { firDiagnostic ->
NestedJsExportImpl(
firDiagnostic as KtPsiDiagnostic,
Expand Down Expand Up @@ -6580,6 +6586,12 @@ private fun KaDiagnosticConverterBuilder.addConversions144() {
token,
)
}
add(FirJvmErrors.JAVA_CLASS_PROPERTY_REFERENCE.errorFactory) { firDiagnostic ->
JavaClassPropertyReferenceErrorImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
}

private fun KaDiagnosticConverterBuilder.addConversions145() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4985,6 +4985,14 @@ sealed interface KaFirDiagnostic<PSI : PsiElement> : KaDiagnosticWithPsi<PSI> {
val expectedType: KaType
}

interface JavaClassPropertyReferenceError : KaFirDiagnostic<PsiElement> {
override val diagnosticClass get() = JavaClassPropertyReferenceError::class
}

interface JavaClassPropertyReferenceWarning : KaFirDiagnostic<PsiElement> {
override val diagnosticClass get() = JavaClassPropertyReferenceWarning::class
}

interface UnexhaustiveWhenBasedOnJavaAnnotations : KaFirDiagnostic<PsiElement> {
override val diagnosticClass get() = UnexhaustiveWhenBasedOnJavaAnnotations::class
val subjectType: KaType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5986,6 +5986,16 @@ internal class JavaClassOnCompanionImpl(
token: KaLifetimeToken,
) : KaAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KaFirDiagnostic.JavaClassOnCompanion

internal class JavaClassPropertyReferenceErrorImpl(
firDiagnostic: KtPsiDiagnostic,
token: KaLifetimeToken,
) : KaAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KaFirDiagnostic.JavaClassPropertyReferenceError

internal class JavaClassPropertyReferenceWarningImpl(
firDiagnostic: KtPsiDiagnostic,
token: KaLifetimeToken,
) : KaAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KaFirDiagnostic.JavaClassPropertyReferenceWarning

internal class UnexhaustiveWhenBasedOnJavaAnnotationsImpl(
override val subjectType: KaType,
firDiagnostic: KtPsiDiagnostic,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") {
parameter<ConeKotlinType>("actualType")
parameter<ConeKotlinType>("expectedType")
}
val JAVA_CLASS_PROPERTY_REFERENCE by deprecationError<PsiElement>(
featureForError = ForbidJavaClassPropertyReferences,
positioningStrategy = PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED,
)

val UNEXHAUSTIVE_WHEN_BASED_ON_JAVA_ANNOTATIONS by warning<PsiElement>(PositioningStrategy.WHEN_EXPRESSION) {
parameter<ConeKotlinType>("subjectType")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics.jvm

import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature.ForbidImplementationByDelegationWithDifferentGenericSignature
import org.jetbrains.kotlin.config.LanguageFeature.ForbidJavaClassPropertyReferences
import org.jetbrains.kotlin.config.LanguageFeature.ForbidJvmAnnotationsOnAnnotationParameters
import org.jetbrains.kotlin.config.LanguageFeature.ForbidJvmSerializableLambdaOnInlinedFunctionLiterals
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitSynchronizationByValueClassesAndPrimitives
Expand Down Expand Up @@ -86,6 +87,7 @@ object FirJvmErrors : KtDiagnosticsContainer() {
val NULLABILITY_MISMATCH_BASED_ON_EXPLICIT_TYPE_ARGUMENTS_FOR_JAVA: KtDiagnosticFactory3<ConeKotlinType, ConeKotlinType, String> = KtDiagnosticFactory3("NULLABILITY_MISMATCH_BASED_ON_EXPLICIT_TYPE_ARGUMENTS_FOR_JAVA", WARNING, SourceElementPositioningStrategies.DEFAULT, PsiElement::class, getRendererFactory())
val TYPE_MISMATCH_WHEN_FLEXIBILITY_CHANGES: KtDiagnosticFactory2<ConeKotlinType, ConeKotlinType> = KtDiagnosticFactory2("TYPE_MISMATCH_WHEN_FLEXIBILITY_CHANGES", WARNING, SourceElementPositioningStrategies.DEFAULT, PsiElement::class, getRendererFactory())
val JAVA_CLASS_ON_COMPANION: KtDiagnosticFactory2<ConeKotlinType, ConeKotlinType> = KtDiagnosticFactory2("JAVA_CLASS_ON_COMPANION", WARNING, SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED, PsiElement::class, getRendererFactory())
val JAVA_CLASS_PROPERTY_REFERENCE: KtDiagnosticFactoryForDeprecation0 = KtDiagnosticFactoryForDeprecation0("JAVA_CLASS_PROPERTY_REFERENCE", ForbidJavaClassPropertyReferences, SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED, PsiElement::class, getRendererFactory())
val UNEXHAUSTIVE_WHEN_BASED_ON_JAVA_ANNOTATIONS: KtDiagnosticFactory1<ConeKotlinType> = KtDiagnosticFactory1("UNEXHAUSTIVE_WHEN_BASED_ON_JAVA_ANNOTATIONS", WARNING, SourceElementPositioningStrategies.WHEN_EXPRESSION, PsiElement::class, getRendererFactory())

// Type parameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INNER_JVM_
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_CLASS_INHERITS_KT_PRIVATE_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_CLASS_ON_COMPANION
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_CLASS_PROPERTY_REFERENCE
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_FIELD_SHADOWED_BY_KOTLIN_PROPERTY
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_MODULE_DOES_NOT_DEPEND_ON_MODULE
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE
Expand Down Expand Up @@ -185,6 +186,10 @@ object FirJvmErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
RENDER_TYPE,
RENDER_TYPE,
)
map.put(
JAVA_CLASS_PROPERTY_REFERENCE,
"Property references to 'javaClass' are error-prone: '::javaClass' creates a property reference, not the Java class of the receiver. Use '.javaClass' or '::class.java' instead.",
)

map.put(
UNEXHAUSTIVE_WHEN_BASED_ON_JAVA_ANNOTATIONS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ object JvmExpressionCheckers : ExpressionCheckers() {
FirUnsupportedSyntheticCallableReferenceChecker,
FirFieldReferenceShadowedByInvisibleKotlinProperty,
FirJavaSamInterfaceConstructorReferenceChecker,
FirJavaClassPropertyReferenceChecker,
)

override val functionCallCheckers: Set<FirFunctionCallChecker>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2026 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.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirCallableReferenceAccessChecker
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableReference
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.name.JvmStandardClassIds

object FirJavaClassPropertyReferenceChecker : FirCallableReferenceAccessChecker(MppCheckerKind.Common) {
context(context: CheckerContext, reporter: DiagnosticReporter)
override fun check(expression: FirCallableReferenceAccess) {
val resolvedSymbol = expression.toResolvedCallableReference()?.resolvedSymbol as? FirCallableSymbol<*> ?: return
if (resolvedSymbol.callableId != JvmStandardClassIds.Callables.JavaClass) return

reporter.reportOn(expression.calleeReference.source, FirJvmErrors.JAVA_CLASS_PROPERTY_REFERENCE)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set<String> = setOf(
"IMPLEMENTATION_BY_DELEGATION_WITH_DIFFERENT_GENERIC_SIGNATURE_ERROR",
"NOT_YET_SUPPORTED_LOCAL_INLINE_FUNCTION",
"JAVA_TYPE_MISMATCH",
"JAVA_CLASS_PROPERTY_REFERENCE_ERROR",
"UPPER_BOUND_CANNOT_BE_ARRAY",
"STRICTFP_ON_CLASS",
"SYNCHRONIZED_ON_ABSTRACT",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// RUN_PIPELINE_TILL: FRONTEND
// ISSUE: KTLC-375, KT-81931
// LATEST_LV_DIFFERENCE

fun test(x: Any) {
val a = x::<!JAVA_CLASS_PROPERTY_REFERENCE_WARNING!>javaClass<!>
val b = Any()::<!JAVA_CLASS_PROPERTY_REFERENCE_WARNING!>javaClass<!>
val c = 2::<!JAVA_CLASS_PROPERTY_REFERENCE_WARNING!>javaClass<!>
val d = x::<!JAVA_CLASS_PROPERTY_REFERENCE_WARNING!>javaClass<!>.get()

val direct = x.javaClass
val literal = Any::class.java
}

/* GENERATED_FIR_TAGS: callableReference, classReference, functionDeclaration, integerLiteral, localProperty,
propertyDeclaration */
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// RUN_PIPELINE_TILL: FRONTEND
// ISSUE: KTLC-375, KT-81931
// LATEST_LV_DIFFERENCE

fun test(x: Any) {
val a = x::<!JAVA_CLASS_PROPERTY_REFERENCE_ERROR!>javaClass<!>
val b = Any()::<!JAVA_CLASS_PROPERTY_REFERENCE_ERROR!>javaClass<!>
val c = 2::<!JAVA_CLASS_PROPERTY_REFERENCE_ERROR!>javaClass<!>
val d = x::<!JAVA_CLASS_PROPERTY_REFERENCE_ERROR!>javaClass<!>.get()

val direct = x.javaClass
val literal = Any::class.java
}

/* GENERATED_FIR_TAGS: callableReference, classReference, functionDeclaration, integerLiteral, localProperty,
propertyDeclaration */
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,7 @@ enum class LanguageFeature(
// 2.6

ReportReificationProblemsInDnnAndFlexible(sinceVersion = KOTLIN_2_6, enabledInProgressiveMode = true, "KTLC-399"),
ForbidJavaClassPropertyReferences(sinceVersion = KOTLIN_2_6, enabledInProgressiveMode = true, "KTLC-375"),

// End of 2.* language features --------------------------------------------------

Expand Down