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.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 {
|
||||
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.psi.PsiElement
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
|
||||
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.incremental.components.NoLookupLocation
|
||||
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.renderFqName
|
||||
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.parentsWithSelf
|
||||
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.typeUtil.containsError
|
||||
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||
import org.jetbrains.kotlin.types.typeUtil.isEnum
|
||||
|
||||
//hack to separate type presentation from param info presentation
|
||||
const val TYPE_INFO_PREFIX = "@TYPE@"
|
||||
@@ -106,11 +106,13 @@ fun provideTypeHint(element: KtCallableDeclaration, offset: Int): List<InlayInfo
|
||||
|
||||
val declString = buildString {
|
||||
append(TYPE_INFO_PREFIX)
|
||||
if (settings.SPACE_BEFORE_TYPE_COLON)
|
||||
if (settings.SPACE_BEFORE_TYPE_COLON) {
|
||||
append(" ")
|
||||
}
|
||||
append(":")
|
||||
if (settings.SPACE_AFTER_TYPE_COLON)
|
||||
if (settings.SPACE_AFTER_TYPE_COLON) {
|
||||
append(" ")
|
||||
}
|
||||
append(getInlayHintsTypeRenderer(element.analyze(), element).renderType(type))
|
||||
}
|
||||
listOf(InlayInfo(declString, offset))
|
||||
@@ -120,21 +122,32 @@ fun provideTypeHint(element: KtCallableDeclaration, offset: Int): List<InlayInfo
|
||||
}
|
||||
|
||||
private fun isUnclearType(type: KotlinType, element: KtCallableDeclaration): Boolean {
|
||||
if (element is KtProperty) {
|
||||
val initializer = element.initializer ?: return true
|
||||
if (initializer is KtConstantExpression || initializer is KtStringTemplateExpression) return false
|
||||
if (initializer is KtUnaryExpression && initializer.baseExpression is KtConstantExpression) return false
|
||||
if (initializer is KtCallExpression) {
|
||||
val resolvedCall = initializer.resolveToCall(BodyResolveMode.FULL)
|
||||
val resolvedDescriptor = resolvedCall?.candidateDescriptor
|
||||
if (resolvedDescriptor is SamConstructorDescriptor) {
|
||||
return false
|
||||
}
|
||||
if (resolvedDescriptor is ConstructorDescriptor &&
|
||||
(resolvedDescriptor.constructedClass.declaredTypeParameters.isEmpty() || initializer.typeArgumentList != null)) {
|
||||
return false
|
||||
}
|
||||
if (element !is KtProperty) return true
|
||||
|
||||
val initializer = element.initializer ?: return true
|
||||
if (initializer is KtConstantExpression || initializer is KtStringTemplateExpression) return false
|
||||
if (initializer is KtUnaryExpression && initializer.baseExpression is KtConstantExpression) return false
|
||||
if (initializer is KtCallExpression) {
|
||||
val resolvedCall = initializer.resolveToCall(BodyResolveMode.FULL)
|
||||
val resolvedDescriptor = resolvedCall?.candidateDescriptor
|
||||
if (resolvedDescriptor is SamConstructorDescriptor) {
|
||||
return false
|
||||
}
|
||||
if (resolvedDescriptor is ConstructorDescriptor &&
|
||||
(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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
checkLocalVariable(
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user