Skip to content

Commit d84c303

Browse files
committed
Do not report 'const' inapplicability on property of error type
#KT-12477 Fixed
1 parent e7ea076 commit d84c303

File tree

4 files changed

+37
-16
lines changed

4 files changed

+37
-16
lines changed

compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ConstModifierChecker.kt

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2016 JetBrains s.r.o.
2+
* Copyright 2010-2017 JetBrains s.r.o.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -37,46 +37,59 @@ object ConstModifierChecker : SimpleDeclarationChecker {
3737

3838
val constModifierPsiElement = declaration.modifierList!!.getModifier(KtTokens.CONST_KEYWORD)!!
3939

40-
val diagnostic = checkCanBeConst(declaration, constModifierPsiElement, descriptor)
40+
val diagnostic = checkCanBeConst(declaration, constModifierPsiElement, descriptor).diagnostic
4141
if (diagnostic != null) {
4242
diagnosticHolder.report(diagnostic)
4343
}
4444
}
4545

46-
fun checkCanBeConst(declaration: KtDeclaration,
46+
fun canBeConst(declaration: KtDeclaration, constModifierPsiElement: PsiElement, descriptor: VariableDescriptor): Boolean =
47+
checkCanBeConst(declaration, constModifierPsiElement, descriptor).canBeConst
48+
49+
private fun checkCanBeConst(declaration: KtDeclaration,
4750
constModifierPsiElement: PsiElement,
48-
descriptor: VariableDescriptor): Diagnostic? {
51+
descriptor: VariableDescriptor): ConstApplicability {
4952
if (descriptor.isVar) {
50-
return Errors.WRONG_MODIFIER_TARGET.on(constModifierPsiElement, KtTokens.CONST_KEYWORD, "vars")
53+
return Errors.WRONG_MODIFIER_TARGET.on(constModifierPsiElement, KtTokens.CONST_KEYWORD, "vars").nonApplicable()
5154
}
5255

5356
val containingDeclaration = descriptor.containingDeclaration
5457
if (containingDeclaration is ClassDescriptor && containingDeclaration.kind != ClassKind.OBJECT) {
55-
return Errors.CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT.on(constModifierPsiElement)
58+
return Errors.CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT.on(constModifierPsiElement).nonApplicable()
5659
}
5760

58-
if (declaration !is KtProperty || descriptor !is PropertyDescriptor) return null
61+
if (declaration !is KtProperty || descriptor !is PropertyDescriptor) return ConstApplicability.NonApplicable()
5962

6063
if (declaration.hasDelegate()) {
61-
return Errors.CONST_VAL_WITH_DELEGATE.on(declaration.delegate!!)
64+
return Errors.CONST_VAL_WITH_DELEGATE.on(declaration.delegate!!).nonApplicable()
6265
}
6366

6467
if (descriptor is PropertyDescriptor && !descriptor.getter!!.isDefault) {
65-
return Errors.CONST_VAL_WITH_GETTER.on(declaration.getter!!)
68+
return Errors.CONST_VAL_WITH_GETTER.on(declaration.getter!!).nonApplicable()
6669
}
6770

71+
if (descriptor.type.isError) return ConstApplicability.NonApplicable()
72+
73+
// Report errors about const initializer only on property of resolved types
6874
if (!descriptor.type.canBeUsedForConstVal()) {
69-
return Errors.TYPE_CANT_BE_USED_FOR_CONST_VAL.on(constModifierPsiElement, descriptor.type)
75+
return Errors.TYPE_CANT_BE_USED_FOR_CONST_VAL.on(constModifierPsiElement, descriptor.type).nonApplicable()
7076
}
7177

7278
if (declaration.initializer == null) {
73-
return Errors.CONST_VAL_WITHOUT_INITIALIZER.on(constModifierPsiElement)
79+
return Errors.CONST_VAL_WITHOUT_INITIALIZER.on(constModifierPsiElement).nonApplicable()
7480
}
7581

7682
if (descriptor.compileTimeInitializer == null) {
77-
return Errors.CONST_VAL_WITH_NON_CONST_INITIALIZER.on(declaration.initializer!!)
83+
return Errors.CONST_VAL_WITH_NON_CONST_INITIALIZER.on(declaration.initializer!!).nonApplicable()
7884
}
7985

80-
return null
86+
return ConstApplicability.Applicable
8187
}
8288
}
89+
90+
sealed class ConstApplicability(val canBeConst: Boolean, val diagnostic: Diagnostic?) {
91+
object Applicable : ConstApplicability(true, null)
92+
class NonApplicable(diagnostic: Diagnostic? = null) : ConstApplicability(false, diagnostic)
93+
}
94+
95+
private fun Diagnostic.nonApplicable() = ConstApplicability.NonApplicable(this)

compiler/testData/diagnostics/tests/modifiers/const/types.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,8 @@ enum class MyEnum { A }
1010
<!TYPE_CANT_BE_USED_FOR_CONST_VAL!>const<!> val enumConst: MyEnum = MyEnum.A
1111
<!TYPE_CANT_BE_USED_FOR_CONST_VAL!>const<!> val arrayConst: Array<String> = arrayOf("1")
1212
<!TYPE_CANT_BE_USED_FOR_CONST_VAL!>const<!> val intArrayConst: IntArray = intArrayOf()
13+
14+
const val unresolvedConst1 = <!UNRESOLVED_REFERENCE!>Unresolved<!>
15+
<!WRONG_MODIFIER_TARGET!>const<!> var unresolvedConst2 = <!UNRESOLVED_REFERENCE!>Unresolved<!>
16+
const val unresolvedConst3 = <!UNRESOLVED_REFERENCE, PROPERTY_INITIALIZER_NO_BACKING_FIELD!>Unresolved<!>
17+
<!CONST_VAL_WITH_GETTER!>get() = 10<!>

compiler/testData/diagnostics/tests/modifiers/const/types.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ public const val intArrayConst: kotlin.IntArray
77
public const val intConst: kotlin.Int = 1
88
public const val longConst: kotlin.Long = 1.toLong()
99
public const val stringConst: kotlin.String = "empty"
10+
public const val unresolvedConst1: [ERROR : Type for Unresolved]
11+
public const var unresolvedConst2: [ERROR : Type for Unresolved]
12+
public const val unresolvedConst3: [ERROR : Type for Unresolved]
1013

1114
public final enum class MyEnum : kotlin.Enum<MyEnum> {
1215
enum entry A

idea/src/org/jetbrains/kotlin/idea/quickfix/AddConstModifierFix.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2015 JetBrains s.r.o.
2+
* Copyright 2010-2017 JetBrains s.r.o.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -77,7 +77,7 @@ class AddConstModifierIntention : SelfTargetingIntention<KtProperty>(KtProperty:
7777
return false
7878
}
7979
val propertyDescriptor = element.descriptor as? VariableDescriptor ?: return false
80-
return ConstModifierChecker.checkCanBeConst(element, element, propertyDescriptor) == null
80+
return ConstModifierChecker.canBeConst(element, element, propertyDescriptor)
8181
}
8282
}
8383
}
@@ -89,7 +89,7 @@ object ConstFixFactory : KotlinSingleIntentionActionFactory() {
8989
val bindingContext = expr.analyze(BodyResolveMode.PARTIAL)
9090
val targetDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expr) as? VariableDescriptor ?: return null
9191
val declaration = (targetDescriptor.source as? PsiSourceElement)?.psi as? KtProperty ?: return null
92-
if (ConstModifierChecker.checkCanBeConst(declaration, declaration, targetDescriptor) == null) {
92+
if (ConstModifierChecker.canBeConst(declaration, declaration, targetDescriptor)) {
9393
return AddConstModifierFix(declaration)
9494
}
9595
return null

0 commit comments

Comments
 (0)