diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 9a852cb09c1..aff70cb1591 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -967,7 +967,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { parameter("compileTimeCheckResult") } val IS_ENUM_ENTRY by error() - val ENUM_ENTRY_AS_TYPE by error() + val ENUM_ENTRY_AS_TYPE by error(PositioningStrategy.SELECTOR_BY_QUALIFIED) } val WHEN_EXPRESSIONS by object : DiagnosticGroup("When expressions") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index bd290c11ff4..ab67385f725 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -510,7 +510,7 @@ object FirErrors { val USELESS_CAST by warning0(SourceElementPositioningStrategies.AS_TYPE) val USELESS_IS_CHECK by warning1() val IS_ENUM_ENTRY by error0() - val ENUM_ENTRY_AS_TYPE by error0() + val ENUM_ENTRY_AS_TYPE by error0(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) // When expressions val EXPECTED_CONDITION by error0() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt index 347df422052..51296b0fb67 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt @@ -20,8 +20,7 @@ import org.jetbrains.kotlin.lexer.KtTokens.VISIBILITY_MODIFIERS import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType import org.jetbrains.kotlin.psi.stubs.elements.KtStringTemplateExpressionElementType -import org.jetbrains.kotlin.psi.stubs.elements.KtValueArgumentElementType -import org.jetbrains.kotlin.psi.stubs.elements.KtValueArgumentListElementType +import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes object LightTreePositioningStrategies { val DEFAULT = object : LightTreePositioningStrategy() { @@ -462,17 +461,36 @@ object LightTreePositioningStrategies { return markElement(it, startOffset, endOffset, tree, node) } } - if (node.tokenType !in KtTokens.QUALIFIED_ACCESS) { + if (node.tokenType in KtTokens.QUALIFIED_ACCESS) { + val selector = tree.selector(node) + if (selector != null) { + return markElement(selector, startOffset, endOffset, tree, node) + } return super.mark(node, startOffset, endOffset, tree) } - val selector = tree.selector(node) - if (selector != null) { - return markElement(selector, startOffset, endOffset, tree, node) + if (node.tokenType == KtNodeTypes.TYPE_REFERENCE) { + val typeElement = tree.findChildByType(node, KtStubElementTypes.TYPE_ELEMENT_TYPES) + if (typeElement != null) { + val referencedTypeExpression = tree.referencedTypeExpression(typeElement) + if (referencedTypeExpression != null) { + return markElement(referencedTypeExpression, startOffset, endOffset, tree, node) + } + } } return super.mark(node, startOffset, endOffset, tree) } } + private fun FlyweightCapableTreeStructure.referencedTypeExpression(node: LighterASTNode): LighterASTNode? { + return when (node.tokenType) { + KtNodeTypes.USER_TYPE -> findChildByType(node, KtNodeTypes.REFERENCE_EXPRESSION) + ?: findChildByType(node, KtNodeTypes.ENUM_ENTRY_SUPERCLASS_REFERENCE_EXPRESSION) + KtNodeTypes.NULLABLE_TYPE, KtNodeTypes.DEFINITELY_NOT_NULL_TYPE -> findChildByType(node, KtStubElementTypes.TYPE_ELEMENT_TYPES) + ?.let { referencedTypeExpression(it) } + else -> null + } + } + val FUN_INTERFACE: LightTreePositioningStrategy = object : LightTreePositioningStrategy() { override fun mark( node: LighterASTNode, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index 3056e6d57f7..f9937c1d6fa 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -821,10 +821,22 @@ object PositioningStrategies { is KtElement -> return mark(selectorExpression) } } + if (element is KtTypeReference) { + element.typeElement?.getReferencedTypeExpression()?.let { return mark(it) } + } return super.mark(element) } } + private fun KtTypeElement.getReferencedTypeExpression(): KtElement? { + return when (this) { + is KtUserType -> referenceExpression + is KtNullableType -> innerType?.getReferencedTypeExpression() + is KtDefinitelyNotNullType -> innerType?.getReferencedTypeExpression() + else -> null + } + } + val RESERVED_UNDERSCORE: PositioningStrategy = object : PositioningStrategy() { override fun mark(element: PsiElement): List { if (element is PsiNameIdentifierOwner) { diff --git a/compiler/testData/diagnostics/tests/EnumEntryAsType.fir.kt b/compiler/testData/diagnostics/tests/EnumEntryAsType.fir.kt index f5d3ac33d74..af2e47a62bb 100644 --- a/compiler/testData/diagnostics/tests/EnumEntryAsType.fir.kt +++ b/compiler/testData/diagnostics/tests/EnumEntryAsType.fir.kt @@ -6,22 +6,22 @@ enum class Color { } } -class MyColor(val x: Color.RED, y: Color.RED) : Color.RED { +class MyColor(val x: Color.RED, y: Color.RED) : Color.RED { - var z: Color.RED = Color.RED - set(arg: Color.RED) { z = arg } + var z: Color.RED = Color.RED + set(arg: Color.RED) { z = arg } - fun foo(arg: Color.RED): Color.RED = arg + fun foo(arg: Color.RED): Color.RED = arg - fun bar(): Color.RED { - class Local : Color.RED - fun local(arg: Color.RED): Color.RED = arg - val temp: Color.RED = Color.RED - temp as? Color.RED + fun bar(): Color.RED { + class Local : Color.RED + fun local(arg: Color.RED): Color.RED = arg + val temp: Color.RED = Color.RED + temp as? Color.RED if (temp is Color.RED) { - return temp as Color.RED + return temp as Color.RED } - val obj = object : Color.RED {} + val obj = object : Color.RED {} if (obj is Color.RED) { return obj } @@ -29,26 +29,26 @@ class MyColor(val x: Color.RED, y: Color.RED>? = null +fun create(): ArrayRED>? = null -interface YourColor.RED> +interface YourRED> -class His : Your<Color.RED> +class His : YourRED> -fun Color.RED> otherCreate(): Array? = null +fun RED> otherCreate(): Array? = null -typealias RedAlias = Color.RED +typealias RedAlias = Color.RED -typealias ArrayOfEnumEntry = Array<Color.RED> +typealias ArrayOfEnumEntry = ArrayRED> typealias ArrayOfEnumEntryAlias = Array fun bar(a: Any): T = a as T fun foo() { - foo<Color.RED>() + fooRED>() foo<RedAlias>() - bar<Color.RED>(Color.RED) + barRED>(Color.RED) } -fun Array<Color.RED>.foo(entries: Array<Color.RED>): Array<Color.RED> = null!! +fun ArrayRED>.foo(entries: ArrayRED>): ArrayRED> = null!! diff --git a/compiler/testData/diagnostics/tests/enum/inheritFromEnumEntry.fir.kt b/compiler/testData/diagnostics/tests/enum/inheritFromEnumEntry.fir.kt deleted file mode 100644 index f5634e0fe77..00000000000 --- a/compiler/testData/diagnostics/tests/enum/inheritFromEnumEntry.fir.kt +++ /dev/null @@ -1,5 +0,0 @@ -enum class E { - ENTRY -} - -class A : E.ENTRY diff --git a/compiler/testData/diagnostics/tests/enum/inheritFromEnumEntry.kt b/compiler/testData/diagnostics/tests/enum/inheritFromEnumEntry.kt index 0c24077e5e0..ccbdeae2112 100644 --- a/compiler/testData/diagnostics/tests/enum/inheritFromEnumEntry.kt +++ b/compiler/testData/diagnostics/tests/enum/inheritFromEnumEntry.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL enum class E { ENTRY }