FIR IDE: Add quickfix for INAPPLICABLE_LATEINIT_MODIFIER.

Also changed FE1.0 checker and all related fix factories to report error
on the declaration instead of the lateinit modifier. This is consistent
with the direction of all checkers in FIR (no reporting on modifiers).
This commit is contained in:
Mark Punzalan
2021-02-12 21:56:39 +00:00
committed by Ilya Kirillov
parent b1ab64e854
commit 4e44804c77
18 changed files with 78 additions and 32 deletions
@@ -590,7 +590,7 @@ public interface Errors {
DiagnosticFactory0<KtProperty> PRIVATE_PROPERTY_IN_INTERFACE = DiagnosticFactory0.create(ERROR, PRIVATE_MODIFIER);
DiagnosticFactory0<KtProperty> BACKING_FIELD_IN_INTERFACE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
DiagnosticFactory1<PsiElement, String> INAPPLICABLE_LATEINIT_MODIFIER = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtModifierListOwner, String> INAPPLICABLE_LATEINIT_MODIFIER = DiagnosticFactory1.create(ERROR, LATEINIT_MODIFIER);
DiagnosticFactory0<PsiElement> LATEINIT_INTRINSIC_CALL_ON_NON_LITERAL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> LATEINIT_INTRINSIC_CALL_ON_NON_LATEINIT = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> LATEINIT_INTRINSIC_CALL_IN_INLINE_FUNCTION = DiagnosticFactory0.create(ERROR);
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.types.TypeUtils
object LateinitModifierApplicabilityChecker {
fun checkLateinitModifierApplicability(trace: BindingTrace, ktDeclaration: KtCallableDeclaration, descriptor: VariableDescriptor) {
val modifier = ktDeclaration.modifierList?.getModifier(KtTokens.LATEINIT_KEYWORD) ?: return
if (!ktDeclaration.hasModifier(KtTokens.LATEINIT_KEYWORD)) return
val variables = when (descriptor) {
is PropertyDescriptor -> "properties"
@@ -43,37 +43,37 @@ object LateinitModifierApplicabilityChecker {
val type = descriptor.type
if (!descriptor.isVar) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is allowed only on mutable $variables"))
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(ktDeclaration, "is allowed only on mutable $variables"))
}
if (type.isInlineClassType()) {
if (UnsignedTypes.isUnsignedType(type)) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on $variables of unsigned types"))
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(ktDeclaration, "is not allowed on $variables of unsigned types"))
} else {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on $variables of inline class types"))
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(ktDeclaration, "is not allowed on $variables of inline class types"))
}
}
if (type.isMarkedNullable) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on $variables of nullable types"))
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(ktDeclaration, "is not allowed on $variables of nullable types"))
} else if (TypeUtils.isNullableType(type)) {
trace.report(
Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(
modifier,
ktDeclaration,
"is not allowed on $variables of a type with nullable upper bound"
)
)
}
if (KotlinBuiltIns.isPrimitiveType(type)) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on $variables of primitive types"))
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(ktDeclaration, "is not allowed on $variables of primitive types"))
}
if (ktDeclaration is KtProperty) {
if (ktDeclaration.hasDelegateExpression()) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on delegated properties"))
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(ktDeclaration, "is not allowed on delegated properties"))
} else if (ktDeclaration.hasInitializer()) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on $variables with initializer"))
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(ktDeclaration, "is not allowed on $variables with initializer"))
}
}
@@ -84,28 +84,28 @@ object LateinitModifierApplicabilityChecker {
val hasBackingField = trace.bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor) ?: false
if (ktDeclaration is KtParameter) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on primary constructor parameters"))
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(ktDeclaration, "is not allowed on primary constructor parameters"))
}
if (isAbstract) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on abstract properties"))
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(ktDeclaration, "is not allowed on abstract properties"))
}
if (!hasDelegateExpressionOrInitializer) {
if (hasAccessorImplementation) {
trace.report(
Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(
modifier,
ktDeclaration,
"is not allowed on properties with a custom getter or setter"
)
)
} else if (!isAbstract && !hasBackingField) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on properties without backing field"))
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(ktDeclaration, "is not allowed on properties without backing field"))
}
}
if (descriptor.extensionReceiverParameter != null) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on extension properties"))
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(ktDeclaration, "is not allowed on extension properties"))
}
}
}