Don't show types for enum entries with enum name is present in initializer (KT-26057)
#KT-26057 Fixed
This commit is contained in:
@@ -77,6 +77,7 @@ fun KotlinType.isPrimitiveNumberOrNullableType(): Boolean =
|
|||||||
fun KotlinType.isTypeParameter(): Boolean = TypeUtils.isTypeParameter(this)
|
fun KotlinType.isTypeParameter(): Boolean = TypeUtils.isTypeParameter(this)
|
||||||
|
|
||||||
fun KotlinType.isInterface(): Boolean = (constructor.declarationDescriptor as? ClassDescriptor)?.kind == ClassKind.INTERFACE
|
fun KotlinType.isInterface(): Boolean = (constructor.declarationDescriptor as? ClassDescriptor)?.kind == ClassKind.INTERFACE
|
||||||
|
fun KotlinType.isEnum(): Boolean = (constructor.declarationDescriptor as? ClassDescriptor)?.kind == ClassKind.ENUM_CLASS
|
||||||
|
|
||||||
fun KotlinType?.isArrayOfNothing(): Boolean {
|
fun KotlinType?.isArrayOfNothing(): Boolean {
|
||||||
if (this == null || !KotlinBuiltIns.isArray(this)) return false
|
if (this == null || !KotlinBuiltIns.isArray(this)) return false
|
||||||
|
|||||||
@@ -8,15 +8,13 @@ package org.jetbrains.kotlin.idea.parameterInfo
|
|||||||
import com.intellij.codeInsight.hints.InlayInfo
|
import com.intellij.codeInsight.hints.InlayInfo
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||||
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
|
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
|
||||||
import org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention
|
import org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention
|
||||||
|
import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors
|
||||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor
|
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor
|
||||||
@@ -28,6 +26,7 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
|||||||
import org.jetbrains.kotlin.renderer.RenderingFormat
|
import org.jetbrains.kotlin.renderer.RenderingFormat
|
||||||
import org.jetbrains.kotlin.renderer.renderFqName
|
import org.jetbrains.kotlin.renderer.renderFqName
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
@@ -35,6 +34,7 @@ import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
|
|||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.containsError
|
import org.jetbrains.kotlin.types.typeUtil.containsError
|
||||||
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.isEnum
|
||||||
|
|
||||||
//hack to separate type presentation from param info presentation
|
//hack to separate type presentation from param info presentation
|
||||||
const val TYPE_INFO_PREFIX = "@TYPE@"
|
const val TYPE_INFO_PREFIX = "@TYPE@"
|
||||||
@@ -106,11 +106,13 @@ fun provideTypeHint(element: KtCallableDeclaration, offset: Int): List<InlayInfo
|
|||||||
|
|
||||||
val declString = buildString {
|
val declString = buildString {
|
||||||
append(TYPE_INFO_PREFIX)
|
append(TYPE_INFO_PREFIX)
|
||||||
if (settings.SPACE_BEFORE_TYPE_COLON)
|
if (settings.SPACE_BEFORE_TYPE_COLON) {
|
||||||
append(" ")
|
append(" ")
|
||||||
|
}
|
||||||
append(":")
|
append(":")
|
||||||
if (settings.SPACE_AFTER_TYPE_COLON)
|
if (settings.SPACE_AFTER_TYPE_COLON) {
|
||||||
append(" ")
|
append(" ")
|
||||||
|
}
|
||||||
append(getInlayHintsTypeRenderer(element.analyze(), element).renderType(type))
|
append(getInlayHintsTypeRenderer(element.analyze(), element).renderType(type))
|
||||||
}
|
}
|
||||||
listOf(InlayInfo(declString, offset))
|
listOf(InlayInfo(declString, offset))
|
||||||
@@ -120,21 +122,32 @@ fun provideTypeHint(element: KtCallableDeclaration, offset: Int): List<InlayInfo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun isUnclearType(type: KotlinType, element: KtCallableDeclaration): Boolean {
|
private fun isUnclearType(type: KotlinType, element: KtCallableDeclaration): Boolean {
|
||||||
if (element is KtProperty) {
|
if (element !is KtProperty) return true
|
||||||
val initializer = element.initializer ?: return true
|
|
||||||
if (initializer is KtConstantExpression || initializer is KtStringTemplateExpression) return false
|
val initializer = element.initializer ?: return true
|
||||||
if (initializer is KtUnaryExpression && initializer.baseExpression is KtConstantExpression) return false
|
if (initializer is KtConstantExpression || initializer is KtStringTemplateExpression) return false
|
||||||
if (initializer is KtCallExpression) {
|
if (initializer is KtUnaryExpression && initializer.baseExpression is KtConstantExpression) return false
|
||||||
val resolvedCall = initializer.resolveToCall(BodyResolveMode.FULL)
|
if (initializer is KtCallExpression) {
|
||||||
val resolvedDescriptor = resolvedCall?.candidateDescriptor
|
val resolvedCall = initializer.resolveToCall(BodyResolveMode.FULL)
|
||||||
if (resolvedDescriptor is SamConstructorDescriptor) {
|
val resolvedDescriptor = resolvedCall?.candidateDescriptor
|
||||||
return false
|
if (resolvedDescriptor is SamConstructorDescriptor) {
|
||||||
}
|
return false
|
||||||
if (resolvedDescriptor is ConstructorDescriptor &&
|
}
|
||||||
(resolvedDescriptor.constructedClass.declaredTypeParameters.isEmpty() || initializer.typeArgumentList != null)) {
|
if (resolvedDescriptor is ConstructorDescriptor &&
|
||||||
return false
|
(resolvedDescriptor.constructedClass.declaredTypeParameters.isEmpty() || initializer.typeArgumentList != null)) {
|
||||||
}
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type.isEnum() && initializer is KtDotQualifiedExpression) {
|
||||||
|
// Do not show type for enums if initializer has enum entry with explicit enum name: val p = Enum.ENTRY
|
||||||
|
val enumEntrySelector = initializer.selectorExpression
|
||||||
|
val enumEntryDescriptor: DeclarationDescriptor? = enumEntrySelector?.resolveMainReferenceToDescriptors()?.singleOrNull()
|
||||||
|
|
||||||
|
if (enumEntryDescriptor != null && DescriptorUtils.isEnumEntry(enumEntryDescriptor)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,6 +98,76 @@ class InlayTypeHintsTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testEnumEntry() {
|
||||||
|
checkPropertyHint(
|
||||||
|
"""
|
||||||
|
enum class E { ENTRY }
|
||||||
|
val test = E.ENTRY
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testEnumEntryLikeProperty() {
|
||||||
|
checkPropertyHint(
|
||||||
|
"""
|
||||||
|
enum class E {
|
||||||
|
ENTRY;
|
||||||
|
companion object {
|
||||||
|
val test: E = ENTRY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val test<hint text=": E"/> = E.test
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testEnumEntryLikeFunction() {
|
||||||
|
checkPropertyHint(
|
||||||
|
"""
|
||||||
|
enum class E { ENTRY;
|
||||||
|
companion object {
|
||||||
|
fun test(): E = ENTRY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val test<hint text=": E"/> = E.test()
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testImportedEnumEntry() {
|
||||||
|
checkPropertyHint(
|
||||||
|
"""
|
||||||
|
import E.ENTRY
|
||||||
|
enum class E { ENTRY }
|
||||||
|
val test<hint text=": E"/> = ENTRY
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testEnumEntryCompanion() {
|
||||||
|
checkPropertyHint(
|
||||||
|
"""
|
||||||
|
enum class E {
|
||||||
|
ENTRY;
|
||||||
|
companion object {}
|
||||||
|
}
|
||||||
|
val test<hint text=": E"/> = E.Companion
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testEnumEntryQualified() {
|
||||||
|
checkPropertyHint(
|
||||||
|
"""
|
||||||
|
package a
|
||||||
|
enum class E { ENTRY }
|
||||||
|
val test = a.E.ENTRY
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun testDestructuring() {
|
fun testDestructuring() {
|
||||||
checkLocalVariable(
|
checkLocalVariable(
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user