[FIR] Add NON_FINAL_JVM_RECORD diagnostic
This commit is contained in:
+1
@@ -63,6 +63,7 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") {
|
|||||||
|
|
||||||
val RECORDS by object : DiagnosticGroup("JVM Records") {
|
val RECORDS by object : DiagnosticGroup("JVM Records") {
|
||||||
val LOCAL_JVM_RECORD by error<PsiElement>()
|
val LOCAL_JVM_RECORD by error<PsiElement>()
|
||||||
|
val NON_FINAL_JVM_RECORD by error<PsiElement>(PositioningStrategy.NON_FINAL_MODIFIER_OR_NAME)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -104,6 +104,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
|
|||||||
LABEL,
|
LABEL,
|
||||||
COMMAS,
|
COMMAS,
|
||||||
OPERATOR_MODIFIER,
|
OPERATOR_MODIFIER,
|
||||||
|
NON_FINAL_MODIFIER_OR_NAME,
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
+2
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics.jvm
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses
|
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.SourceElementPositioningStrategies
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||||
@@ -51,5 +52,6 @@ object FirJvmErrors {
|
|||||||
|
|
||||||
// JVM Records
|
// JVM Records
|
||||||
val LOCAL_JVM_RECORD by error0<PsiElement>()
|
val LOCAL_JVM_RECORD by error0<PsiElement>()
|
||||||
|
val NON_FINAL_JVM_RECORD by error0<PsiElement>(SourceElementPositioningStrategies.NON_FINAL_MODIFIER_OR_NAME)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.getAnnotationByFqName
|
import org.jetbrains.kotlin.fir.declarations.getAnnotationByFqName
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
@@ -24,6 +25,11 @@ object FirJvmRecordChecker : FirRegularClassChecker() {
|
|||||||
|
|
||||||
if (declaration.isLocal) {
|
if (declaration.isLocal) {
|
||||||
reporter.reportOn(annotationSource, FirJvmErrors.LOCAL_JVM_RECORD, context)
|
reporter.reportOn(annotationSource, FirJvmErrors.LOCAL_JVM_RECORD, context)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!declaration.isFinal) {
|
||||||
|
reporter.reportOn(declaration.source, FirJvmErrors.NON_FINAL_JVM_RECORD, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+8
@@ -933,6 +933,14 @@ object LightTreePositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val NON_FINAL_MODIFIER_OR_NAME: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(
|
||||||
|
TokenSet.create(
|
||||||
|
KtTokens.ABSTRACT_KEYWORD,
|
||||||
|
KtTokens.OPEN_KEYWORD,
|
||||||
|
KtTokens.SEALED_KEYWORD
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FirSourceElement.hasValOrVar(): Boolean =
|
fun FirSourceElement.hasValOrVar(): Boolean =
|
||||||
|
|||||||
+5
@@ -309,4 +309,9 @@ object SourceElementPositioningStrategies {
|
|||||||
LightTreePositioningStrategies.OPERATOR_MODIFIER,
|
LightTreePositioningStrategies.OPERATOR_MODIFIER,
|
||||||
PositioningStrategies.OPERATOR_MODIFIER
|
PositioningStrategies.OPERATOR_MODIFIER
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val NON_FINAL_MODIFIER_OR_NAME = SourceElementPositioningStrategy(
|
||||||
|
LightTreePositioningStrategies.NON_FINAL_MODIFIER_OR_NAME,
|
||||||
|
PositioningStrategies.NON_FINAL_MODIFIER_OR_NAME
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -961,6 +961,9 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val NON_FINAL_MODIFIER_OR_NAME: PositioningStrategy<KtModifierListOwner> =
|
||||||
|
ModifierSetBasedPositioningStrategy(TokenSet.create(KtTokens.ABSTRACT_KEYWORD, KtTokens.OPEN_KEYWORD, KtTokens.SEALED_KEYWORD))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param locateReferencedName whether to remove any nested parentheses while locating the reference element. This is useful for
|
* @param locateReferencedName whether to remove any nested parentheses while locating the reference element. This is useful for
|
||||||
* diagnostics on super and unresolved references. For example, with the following, only the part inside the parentheses should be
|
* diagnostics on super and unresolved references. For example, with the following, only the part inside the parentheses should be
|
||||||
|
|||||||
+3
-3
@@ -25,13 +25,13 @@ class A4(var name: String)
|
|||||||
class A5(vararg val name: String, y: Int)
|
class A5(vararg val name: String, y: Int)
|
||||||
|
|
||||||
@JvmRecord
|
@JvmRecord
|
||||||
open class A6(val x: String)
|
<!NON_FINAL_JVM_RECORD!>open<!> class A6(val x: String)
|
||||||
|
|
||||||
@JvmRecord
|
@JvmRecord
|
||||||
abstract class A7(val x: String)
|
<!NON_FINAL_JVM_RECORD!>abstract<!> class A7(val x: String)
|
||||||
|
|
||||||
@JvmRecord
|
@JvmRecord
|
||||||
sealed class A8(val x: String)
|
<!NON_FINAL_JVM_RECORD!>sealed<!> class A8(val x: String)
|
||||||
|
|
||||||
@JvmRecord
|
@JvmRecord
|
||||||
enum class A9(val x: String) {
|
enum class A9(val x: String) {
|
||||||
|
|||||||
+6
@@ -3544,4 +3544,10 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirJvmErrors.NON_FINAL_JVM_RECORD) { firDiagnostic ->
|
||||||
|
NonFinalJvmRecordImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -2469,4 +2469,8 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = LocalJvmRecord::class
|
override val diagnosticClass get() = LocalJvmRecord::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class NonFinalJvmRecord : KtFirDiagnostic<PsiElement>() {
|
||||||
|
override val diagnosticClass get() = NonFinalJvmRecord::class
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -4000,3 +4000,10 @@ internal class LocalJvmRecordImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class NonFinalJvmRecordImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.NonFinalJvmRecord(), KtAbstractFirDiagnostic<PsiElement> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user