FIR: Fix positioning of ENUM_ENTRY_AS_TYPE
The current SELECTOR_BY_QUALIFIED positioning strategy is closely related what should be done here. But it only works on qualified access expressions. This change also makes it work for type references.
This commit is contained in:
committed by
Mikhail Glukhikh
parent
c648356887
commit
a8e379a025
+1
-1
@@ -967,7 +967,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
parameter<Boolean>("compileTimeCheckResult")
|
parameter<Boolean>("compileTimeCheckResult")
|
||||||
}
|
}
|
||||||
val IS_ENUM_ENTRY by error<KtTypeReference>()
|
val IS_ENUM_ENTRY by error<KtTypeReference>()
|
||||||
val ENUM_ENTRY_AS_TYPE by error<KtTypeReference>()
|
val ENUM_ENTRY_AS_TYPE by error<KtTypeReference>(PositioningStrategy.SELECTOR_BY_QUALIFIED)
|
||||||
}
|
}
|
||||||
|
|
||||||
val WHEN_EXPRESSIONS by object : DiagnosticGroup("When expressions") {
|
val WHEN_EXPRESSIONS by object : DiagnosticGroup("When expressions") {
|
||||||
|
|||||||
+1
-1
@@ -510,7 +510,7 @@ object FirErrors {
|
|||||||
val USELESS_CAST by warning0<KtBinaryExpressionWithTypeRHS>(SourceElementPositioningStrategies.AS_TYPE)
|
val USELESS_CAST by warning0<KtBinaryExpressionWithTypeRHS>(SourceElementPositioningStrategies.AS_TYPE)
|
||||||
val USELESS_IS_CHECK by warning1<KtElement, Boolean>()
|
val USELESS_IS_CHECK by warning1<KtElement, Boolean>()
|
||||||
val IS_ENUM_ENTRY by error0<KtTypeReference>()
|
val IS_ENUM_ENTRY by error0<KtTypeReference>()
|
||||||
val ENUM_ENTRY_AS_TYPE by error0<KtTypeReference>()
|
val ENUM_ENTRY_AS_TYPE by error0<KtTypeReference>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
|
||||||
|
|
||||||
// When expressions
|
// When expressions
|
||||||
val EXPECTED_CONDITION by error0<KtWhenCondition>()
|
val EXPECTED_CONDITION by error0<KtWhenCondition>()
|
||||||
|
|||||||
+24
-6
@@ -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.KtParameter.VAL_VAR_TOKEN_SET
|
||||||
import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType
|
import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType
|
||||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStringTemplateExpressionElementType
|
import org.jetbrains.kotlin.psi.stubs.elements.KtStringTemplateExpressionElementType
|
||||||
import org.jetbrains.kotlin.psi.stubs.elements.KtValueArgumentElementType
|
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||||
import org.jetbrains.kotlin.psi.stubs.elements.KtValueArgumentListElementType
|
|
||||||
|
|
||||||
object LightTreePositioningStrategies {
|
object LightTreePositioningStrategies {
|
||||||
val DEFAULT = object : LightTreePositioningStrategy() {
|
val DEFAULT = object : LightTreePositioningStrategy() {
|
||||||
@@ -462,17 +461,36 @@ object LightTreePositioningStrategies {
|
|||||||
return markElement(it, startOffset, endOffset, tree, node)
|
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)
|
return super.mark(node, startOffset, endOffset, tree)
|
||||||
}
|
}
|
||||||
val selector = tree.selector(node)
|
if (node.tokenType == KtNodeTypes.TYPE_REFERENCE) {
|
||||||
if (selector != null) {
|
val typeElement = tree.findChildByType(node, KtStubElementTypes.TYPE_ELEMENT_TYPES)
|
||||||
return markElement(selector, startOffset, endOffset, tree, node)
|
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)
|
return super.mark(node, startOffset, endOffset, tree)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FlyweightCapableTreeStructure<LighterASTNode>.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() {
|
val FUN_INTERFACE: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
|
||||||
override fun mark(
|
override fun mark(
|
||||||
node: LighterASTNode,
|
node: LighterASTNode,
|
||||||
|
|||||||
@@ -821,10 +821,22 @@ object PositioningStrategies {
|
|||||||
is KtElement -> return mark(selectorExpression)
|
is KtElement -> return mark(selectorExpression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (element is KtTypeReference) {
|
||||||
|
element.typeElement?.getReferencedTypeExpression()?.let { return mark(it) }
|
||||||
|
}
|
||||||
return super.mark(element)
|
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<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
val RESERVED_UNDERSCORE: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
||||||
override fun mark(element: PsiElement): List<TextRange> {
|
override fun mark(element: PsiElement): List<TextRange> {
|
||||||
if (element is PsiNameIdentifierOwner) {
|
if (element is PsiNameIdentifierOwner) {
|
||||||
|
|||||||
+20
-20
@@ -6,22 +6,22 @@ enum class Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyColor(val x: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>, y: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>) : <!ENUM_ENTRY_AS_TYPE!>Color.RED<!> {
|
class MyColor(val x: Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>, y: Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>) : Color.<!ENUM_ENTRY_AS_TYPE!>RED<!> {
|
||||||
|
|
||||||
var z: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!> = Color.RED
|
var z: Color.<!ENUM_ENTRY_AS_TYPE!>RED<!> = Color.RED
|
||||||
set(arg: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>) { z = arg }
|
set(arg: Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>) { z = arg }
|
||||||
|
|
||||||
fun foo(arg: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>): <!ENUM_ENTRY_AS_TYPE!>Color.RED<!> = arg
|
fun foo(arg: Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>): Color.<!ENUM_ENTRY_AS_TYPE!>RED<!> = arg
|
||||||
|
|
||||||
fun bar(): <!ENUM_ENTRY_AS_TYPE!>Color.RED<!> {
|
fun bar(): Color.<!ENUM_ENTRY_AS_TYPE!>RED<!> {
|
||||||
class Local : <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>
|
class Local : Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>
|
||||||
fun local(arg: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>): <!ENUM_ENTRY_AS_TYPE!>Color.RED<!> = arg
|
fun local(arg: Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>): Color.<!ENUM_ENTRY_AS_TYPE!>RED<!> = arg
|
||||||
val temp: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!> = Color.RED
|
val temp: Color.<!ENUM_ENTRY_AS_TYPE!>RED<!> = Color.RED
|
||||||
temp as? <!ENUM_ENTRY_AS_TYPE, ENUM_ENTRY_AS_TYPE!>Color.RED<!>
|
temp as? Color.<!ENUM_ENTRY_AS_TYPE, ENUM_ENTRY_AS_TYPE!>RED<!>
|
||||||
if (temp is <!IS_ENUM_ENTRY!>Color.RED<!>) {
|
if (temp is <!IS_ENUM_ENTRY!>Color.RED<!>) {
|
||||||
return temp as <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>
|
return temp as Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>
|
||||||
}
|
}
|
||||||
val obj = object : <!ENUM_ENTRY_AS_TYPE!>Color.RED<!> {}
|
val obj = object : Color.<!ENUM_ENTRY_AS_TYPE!>RED<!> {}
|
||||||
if (obj is <!IS_ENUM_ENTRY!>Color.RED<!>) {
|
if (obj is <!IS_ENUM_ENTRY!>Color.RED<!>) {
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
@@ -29,26 +29,26 @@ class MyColor(val x: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>, y: <!ENUM_ENTRY_AS_TYPE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun create(): Array<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>? = null
|
fun create(): Array<Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>>? = null
|
||||||
|
|
||||||
interface Your<T : <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>
|
interface Your<T : Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>>
|
||||||
|
|
||||||
class His : Your<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>
|
class His : Your<Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>>
|
||||||
|
|
||||||
fun <T : <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>> otherCreate(): Array<T>? = null
|
fun <T : Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>> otherCreate(): Array<T>? = null
|
||||||
|
|
||||||
typealias RedAlias = <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>
|
typealias RedAlias = Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>
|
||||||
|
|
||||||
typealias ArrayOfEnumEntry = Array<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>
|
typealias ArrayOfEnumEntry = Array<Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>>
|
||||||
|
|
||||||
typealias ArrayOfEnumEntryAlias = Array<RedAlias>
|
typealias ArrayOfEnumEntryAlias = Array<RedAlias>
|
||||||
|
|
||||||
fun <T> bar(a: Any): T = a as T
|
fun <T> bar(a: Any): T = a as T
|
||||||
|
|
||||||
fun <T> foo() {
|
fun <T> foo() {
|
||||||
foo<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>()
|
foo<Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>>()
|
||||||
foo<<!CANNOT_INFER_PARAMETER_TYPE!>RedAlias<!>>()
|
foo<<!CANNOT_INFER_PARAMETER_TYPE!>RedAlias<!>>()
|
||||||
bar<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>(<!ARGUMENT_TYPE_MISMATCH!>Color.RED<!>)
|
bar<Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>>(<!ARGUMENT_TYPE_MISMATCH!>Color.RED<!>)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Array<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>.foo(entries: Array<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>): Array<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>> = null!!
|
fun Array<Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>>.foo(entries: Array<Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>>): Array<Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>> = null!!
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
enum class E {
|
|
||||||
ENTRY
|
|
||||||
}
|
|
||||||
|
|
||||||
class A : <!ENUM_ENTRY_AS_TYPE!>E.ENTRY<!>
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
enum class E {
|
enum class E {
|
||||||
ENTRY
|
ENTRY
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user