FIR: Introduce CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT diagnostic
This commit is contained in:
+18
@@ -894,6 +894,24 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/constVal")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class ConstVal extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInConstVal() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/constVal"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("constValNotTopLevelOrObject.kt")
|
||||
public void testConstValNotTopLevelOrObject() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/constVal/constValNotTopLevelOrObject.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/constructors")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
FILE: constValNotTopLevelOrObject.kt
|
||||
public final const val a: R|kotlin/Int| = Int(1)
|
||||
public get(): R|kotlin/Int|
|
||||
public final object B : R|kotlin/Any| {
|
||||
private constructor(): R|B| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final const val b: R|kotlin/Int| = Int(2)
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
}
|
||||
public final class C : R|kotlin/Any| {
|
||||
public constructor(): R|C| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final const val c: R|kotlin/Int| = Int(3)
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
}
|
||||
public final class D : R|kotlin/Any| {
|
||||
public constructor(): R|D| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final object E : R|kotlin/Any| {
|
||||
private constructor(): R|D.E| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final const val e: R|kotlin/Int| = Int(4)
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
}
|
||||
|
||||
public final companion object K : R|kotlin/Any| {
|
||||
private constructor(): R|D.K| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final const val k: R|kotlin/Int| = Int(4)
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
}
|
||||
|
||||
public final val M: R|kotlin/Any| = object : R|kotlin/Any| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final const val m: R|kotlin/Int| = Int(3)
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
}
|
||||
|
||||
public get(): R|kotlin/Any|
|
||||
|
||||
public open class O : R|kotlin/Any| {
|
||||
public constructor(): R|D.O| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public open val y: R|kotlin/Int| = Int(8)
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
}
|
||||
|
||||
public final val t: R|D.O| = object : R|D.O| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|D.O|>()
|
||||
}
|
||||
|
||||
public final const val x: R|kotlin/Int| = Int(15)
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
}
|
||||
|
||||
public get(): R|D.O|
|
||||
|
||||
}
|
||||
public final object F : R|kotlin/Any| {
|
||||
private constructor(): R|F| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final class G : R|kotlin/Any| {
|
||||
public constructor(): R|F.G| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final const val e: R|kotlin/Int| = Int(4)
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lval a: R|kotlin/String| = String(2)
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
const val a = 1
|
||||
|
||||
object B {
|
||||
const val b = 2
|
||||
}
|
||||
|
||||
class C {
|
||||
<!CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT!>const<!> val c = 3
|
||||
}
|
||||
|
||||
class D {
|
||||
object E {
|
||||
const val e = 4
|
||||
}
|
||||
|
||||
companion object K {
|
||||
const val k = 4
|
||||
}
|
||||
|
||||
val M = object {
|
||||
<!CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT!>const<!> val m = 3
|
||||
}
|
||||
|
||||
open class O {
|
||||
open val y: Int = 8
|
||||
}
|
||||
|
||||
val t: O = object : O() {
|
||||
<!CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT!>const<!> val x = 15
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object F {
|
||||
class G {
|
||||
<!CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT!>const<!> val e = 4
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
<!CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT!>const<!> val a = "2"
|
||||
}
|
||||
+16
@@ -1036,6 +1036,22 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/constVal")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class ConstVal {
|
||||
@Test
|
||||
public void testAllFilesPresentInConstVal() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/constVal"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constValNotTopLevelOrObject.kt")
|
||||
public void testConstValNotTopLevelOrObject() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/constVal/constValNotTopLevelOrObject.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/constructors")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+17
@@ -1044,6 +1044,23 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/constVal")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@Execution(ExecutionMode.SAME_THREAD)
|
||||
public class ConstVal {
|
||||
@Test
|
||||
public void testAllFilesPresentInConstVal() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/constVal"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constValNotTopLevelOrObject.kt")
|
||||
public void testConstValNotTopLevelOrObject() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/constVal/constValNotTopLevelOrObject.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/constructors")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+1
@@ -46,6 +46,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
|
||||
REFERENCE_BY_QUALIFIED,
|
||||
PRIVATE_MODIFIER,
|
||||
COMPANION_OBJECT,
|
||||
CONST_MODIFIER,
|
||||
|
||||
;
|
||||
|
||||
|
||||
+1
@@ -328,6 +328,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
val PRIVATE_SETTER_FOR_OPEN_PROPERTY by error<FirSourceElement, KtModifierListOwner>(PositioningStrategy.PRIVATE_MODIFIER)
|
||||
val EXPECTED_PRIVATE_DECLARATION by error<FirSourceElement, KtModifierListOwner>(PositioningStrategy.VISIBILITY_MODIFIER)
|
||||
val VAL_WITH_SETTER by error<FirSourceElement, KtPropertyAccessor>()
|
||||
val CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT by error<FirSourceElement, KtProperty>(PositioningStrategy.CONST_MODIFIER)
|
||||
}
|
||||
|
||||
val MPP_PROJECTS by object : DiagnosticGroup("Multi-platform projects") {
|
||||
|
||||
@@ -222,6 +222,7 @@ object FirErrors {
|
||||
val PRIVATE_SETTER_FOR_OPEN_PROPERTY by error0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.PRIVATE_MODIFIER)
|
||||
val EXPECTED_PRIVATE_DECLARATION by error0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
||||
val VAL_WITH_SETTER by error0<FirSourceElement, KtPropertyAccessor>()
|
||||
val CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.CONST_MODIFIER)
|
||||
|
||||
// Multi-platform projects
|
||||
val EXPECTED_DECLARATION_WITH_BODY by error0<FirSourceElement, KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
|
||||
object FirConstPropertyChecker : FirPropertyChecker() {
|
||||
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val modifierList = with(FirModifierList) { declaration.source.getModifierList() }
|
||||
if (modifierList?.modifiers?.any { it.token == KtTokens.CONST_KEYWORD } != true)
|
||||
return
|
||||
val classKind = (context.containingDeclarations.lastOrNull() as? FirRegularClass)?.classKind
|
||||
if (classKind != ClassKind.OBJECT && context.containingDeclarations.size > 1)
|
||||
reporter.reportOn(declaration.source, FirErrors.CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT, context)
|
||||
}
|
||||
}
|
||||
+3
@@ -292,6 +292,9 @@ object LightTreePositioningStrategies {
|
||||
val VARIANCE_MODIFIER: LightTreePositioningStrategy =
|
||||
ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.IN_KEYWORD, KtTokens.OUT_KEYWORD))
|
||||
|
||||
val CONST_MODIFIER: LightTreePositioningStrategy =
|
||||
ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.CONST_KEYWORD))
|
||||
|
||||
val OPERATOR: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
|
||||
override fun mark(
|
||||
node: LighterASTNode,
|
||||
|
||||
+5
@@ -127,4 +127,9 @@ object SourceElementPositioningStrategies {
|
||||
LightTreePositioningStrategies.IF_EXPRESSION,
|
||||
PositioningStrategies.IF_EXPRESSION
|
||||
)
|
||||
|
||||
val CONST_MODIFIER = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.CONST_MODIFIER,
|
||||
PositioningStrategies.CONST_MODIFIER
|
||||
)
|
||||
}
|
||||
|
||||
+1
@@ -35,6 +35,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
override val propertyCheckers: Set<FirPropertyChecker> = setOf(
|
||||
FirInapplicableLateinitChecker,
|
||||
FirDestructuringDeclarationChecker,
|
||||
FirConstPropertyChecker,
|
||||
)
|
||||
|
||||
override val classCheckers: Set<FirClassChecker> = setOf(
|
||||
|
||||
@@ -353,6 +353,9 @@ object PositioningStrategies {
|
||||
@JvmField
|
||||
val VARIANCE_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.IN_KEYWORD, KtTokens.OUT_KEYWORD)
|
||||
|
||||
@JvmField
|
||||
val CONST_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.CONST_KEYWORD)
|
||||
|
||||
@JvmField
|
||||
val FOR_REDECLARATION: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
||||
override fun mark(element: PsiElement): List<TextRange> {
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@ fun test() {
|
||||
val <T> a0 = 0
|
||||
val <T : __UNRESOLVED__> a1 = ""
|
||||
val <T : String> a2 = 0
|
||||
const val <T> a3 = 0
|
||||
<!CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT!>const<!> val <T> a3 = 0
|
||||
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val <T> a4 = 0
|
||||
val <T> a5 by Delegate<Int>()
|
||||
val <T> a6 by <!INAPPLICABLE_CANDIDATE!>Delegate<!><<!UNRESOLVED_REFERENCE!>T<!>>()
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@ fun test() {
|
||||
val <T> a0 = 0
|
||||
val <T : __UNRESOLVED__> a1 = ""
|
||||
val <T : String> a2 = 0
|
||||
const val <T> a3 = 0
|
||||
<!CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT!>const<!> val <T> a3 = 0
|
||||
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val <T> a4 = 0
|
||||
val <T> a5 by Delegate<Int>()
|
||||
val <T> a6 by <!INAPPLICABLE_CANDIDATE!>Delegate<!><<!UNRESOLVED_REFERENCE!>T<!>>()
|
||||
|
||||
@@ -12,12 +12,12 @@ object A {
|
||||
const val inObject: Int = 4
|
||||
}
|
||||
|
||||
class B(const val constructor: Int = 5)
|
||||
class B(<!CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT!>const<!> val constructor: Int = 5)
|
||||
|
||||
abstract class C {
|
||||
<!INCOMPATIBLE_MODIFIERS!>open<!> <!INCOMPATIBLE_MODIFIERS!>const<!> val x: Int = 6
|
||||
<!INCOMPATIBLE_MODIFIERS!>open<!> <!CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT, INCOMPATIBLE_MODIFIERS!>const<!> val x: Int = 6
|
||||
|
||||
<!INCOMPATIBLE_MODIFIERS!>abstract<!> <!INCOMPATIBLE_MODIFIERS!>const<!> val y: Int = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>7<!>
|
||||
<!INCOMPATIBLE_MODIFIERS!>abstract<!> <!CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT, INCOMPATIBLE_MODIFIERS!>const<!> val y: Int = <!ABSTRACT_PROPERTY_WITH_INITIALIZER!>7<!>
|
||||
|
||||
companion object {
|
||||
const val inCompaionObject = 8
|
||||
@@ -48,15 +48,15 @@ const val withExplicitDefaultGetter: Int = 1
|
||||
get
|
||||
|
||||
fun foo(): Int {
|
||||
const val local: Int = 14
|
||||
<!CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT!>const<!> val local: Int = 14
|
||||
return 15
|
||||
}
|
||||
|
||||
enum class MyEnum {
|
||||
A {
|
||||
const val inEnumEntry = 16
|
||||
<!CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT!>const<!> val inEnumEntry = 16
|
||||
};
|
||||
const val inEnum = 17
|
||||
<!CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT!>const<!> val inEnum = 17
|
||||
}
|
||||
|
||||
class Outer {
|
||||
|
||||
Reference in New Issue
Block a user