Add @JvmRecord diagnostics for open and enums
^KT-43677 In Progress
This commit is contained in:
+29
@@ -5,14 +5,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.isFinalClass
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtModifierList
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
@@ -22,6 +27,7 @@ import org.jetbrains.kotlin.resolve.jvm.JAVA_LANG_RECORD_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_RECORD_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.isJvmRecord
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
object JvmRecordApplicabilityChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
@@ -46,6 +52,26 @@ object JvmRecordApplicabilityChecker : DeclarationChecker {
|
||||
return
|
||||
}
|
||||
|
||||
if (descriptor.kind == ClassKind.ENUM_CLASS) {
|
||||
val modifierOrName =
|
||||
declaration.modifierList?.getModifier(KtTokens.ENUM_KEYWORD)
|
||||
?: declaration.nameIdentifier
|
||||
?: declaration
|
||||
|
||||
context.trace.report(ErrorsJvm.ENUM_JVM_RECORD.on(modifierOrName))
|
||||
return
|
||||
}
|
||||
|
||||
if (!descriptor.isFinalClass) {
|
||||
val modifierOrName =
|
||||
declaration.modifierList?.findOneOfModifiers(KtTokens.ABSTRACT_KEYWORD, KtTokens.OPEN_KEYWORD, KtTokens.SEALED_KEYWORD)
|
||||
?: declaration.nameIdentifier
|
||||
?: declaration
|
||||
|
||||
context.trace.report(ErrorsJvm.NON_FINAL_JVM_RECORD.on(modifierOrName))
|
||||
return
|
||||
}
|
||||
|
||||
if (DescriptorUtils.isLocal(descriptor)) {
|
||||
context.trace.report(ErrorsJvm.LOCAL_JVM_RECORD.on(reportOn))
|
||||
return
|
||||
@@ -84,3 +110,6 @@ object JvmRecordApplicabilityChecker : DeclarationChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtModifierList.findOneOfModifiers(vararg modifierTokens: KtModifierKeywordToken): PsiElement? =
|
||||
modifierTokens.firstNotNullResult(this::getModifier)
|
||||
|
||||
+2
@@ -153,6 +153,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
MAP.put(SUSPENSION_POINT_INSIDE_CRITICAL_SECTION, "The ''{0}'' suspension point is inside a critical section", NAME);
|
||||
|
||||
MAP.put(LOCAL_JVM_RECORD, "Local @JvmRecord classes are not allowed");
|
||||
MAP.put(NON_FINAL_JVM_RECORD, "@JvmRecord class should be final");
|
||||
MAP.put(ENUM_JVM_RECORD, "@JvmRecord class should not be an enum");
|
||||
MAP.put(JVM_RECORD_WITHOUT_PRIMARY_CONSTRUCTOR_PARAMETERS, "Primary constructor with parameters is required for @JvmRecord class");
|
||||
MAP.put(JVM_RECORD_NOT_VAL_PARAMETER, "Constructor parameter of @JvmRecord class should be a val");
|
||||
MAP.put(JVM_RECORD_NOT_LAST_VARARG_PARAMETER, "Only the last constructor parameter of @JvmRecord may be a vararg");
|
||||
|
||||
@@ -116,6 +116,8 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory0<PsiElement> USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<PsiElement> LOCAL_JVM_RECORD = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> NON_FINAL_JVM_RECORD = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> ENUM_JVM_RECORD = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> JVM_RECORD_WITHOUT_PRIMARY_CONSTRUCTOR_PARAMETERS = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> JVM_RECORD_NOT_VAL_PARAMETER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> JVM_RECORD_NOT_LAST_VARARG_PARAMETER = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
@@ -22,7 +22,21 @@ class A4(<!JVM_RECORD_NOT_VAL_PARAMETER!>var name: String<!>)
|
||||
class A5(vararg val name: String, <!JVM_RECORD_NOT_VAL_PARAMETER!><!UNUSED_PARAMETER!>y<!>: Int<!>)
|
||||
|
||||
@JvmRecord
|
||||
class A6(
|
||||
<!NON_FINAL_JVM_RECORD!>open<!> class A6(val x: String)
|
||||
|
||||
@JvmRecord
|
||||
<!NON_FINAL_JVM_RECORD!>abstract<!> class A7(val x: String)
|
||||
|
||||
@JvmRecord
|
||||
<!NON_FINAL_JVM_RECORD!>sealed<!> class A8(val x: String)
|
||||
|
||||
@JvmRecord
|
||||
<!ENUM_JVM_RECORD!>enum<!> class A9(val x: String) {
|
||||
X("");
|
||||
}
|
||||
|
||||
@JvmRecord
|
||||
class A10(
|
||||
val x: String,
|
||||
val y: Int,
|
||||
vararg val z: Double,
|
||||
|
||||
Reference in New Issue
Block a user