Type hints: don't show hint for qualified constructor calls or enum cases

#KT-29196 fixed
This commit is contained in:
Max Medvedev
2019-01-12 09:56:35 +03:00
parent 2a156fe90c
commit 99ffcda5fc
2 changed files with 62 additions and 16 deletions
@@ -127,28 +127,51 @@ private fun isUnclearType(type: KotlinType, element: KtCallableDeclaration): Boo
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 (isConstructorCall(initializer)) {
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 (initializer is KtDotQualifiedExpression) {
val selectorExpression = initializer.selectorExpression
if (type.isEnum()) {
// Do not show type for enums if initializer has enum entry with explicit enum name: val p = Enum.ENTRY
val enumEntryDescriptor: DeclarationDescriptor? = selectorExpression?.resolveMainReferenceToDescriptors()?.singleOrNull()
if (enumEntryDescriptor != null && DescriptorUtils.isEnumEntry(enumEntryDescriptor)) {
if (enumEntryDescriptor != null && DescriptorUtils.isEnumEntry(enumEntryDescriptor)) {
return false
}
}
if (initializer.receiverExpression.isClassOrPackageReference() && isConstructorCall(selectorExpression)) {
return false
}
}
return true
}
private fun isConstructorCall(initializer: KtExpression?): Boolean {
if (initializer is KtCallExpression) {
val resolvedCall = initializer.resolveToCall(BodyResolveMode.FULL)
val resolvedDescriptor = resolvedCall?.candidateDescriptor
if (resolvedDescriptor is SamConstructorDescriptor) {
return true
}
if (resolvedDescriptor is ConstructorDescriptor &&
(resolvedDescriptor.constructedClass.declaredTypeParameters.isEmpty() || initializer.typeArgumentList != null)
) {
return true
}
return false
}
return false
}
private fun KtExpression.isClassOrPackageReference(): Boolean =
when (this) {
is KtNameReferenceExpression -> this.resolveMainReferenceToDescriptors().singleOrNull().let { it is ClassDescriptor || it is PackageViewDescriptor }
is KtDotQualifiedExpression -> this.selectorExpression?.isClassOrPackageReference() ?: false
else -> false
}
@@ -33,6 +33,29 @@ class InlayTypeHintsTest : KotlinLightCodeInsightFixtureTestCase() {
checkLocalVariable("""fun foo() { val (i<hint text=": Int" />, s<hint text=": String" />) = 1 to "" }""")
}
fun testQualifiedReferences() {
checkLocalVariable("""
package p
class A {
class B {
class C {
class D
}
}
inner class E
enum class F { enumCase }
}
fun foo() {
val v1 = A.B.C.D()
val v2 = p.A.B.C.D()
val v3<hint text=": A.E"/> = A().E()
val v4 = p.A.F.enumCase
val v5 = A.F.enumCase
val v6 = p.A()
}
""")
}
fun testPropertyType() {
checkPropertyHint("""val a<hint text=": List<String>" /> = listOf("a")""")
}