Fix parameters nullability for generated overloads in light classes

When making KtLightNullabilityAnnotation after test org.jetbrains.kotlin.idea.caches.resolve.IdeLightClassTestGenerated.NullabilityAnnotations#testJvmOverloads
started failing the wrong assumption was made that for
@JvmOverloads-generated overloads their last parameter is always nullable
(see removed isNullableInJvmOverloads function) and that lead to a bug,
namely KT-28556.

The actual problem of this test started failing was incorrect definition
of kotlinOrigin in KtLightParameter for case of JvmOverloads:
wrong KtParameter was being chosen before

This commit fixes the issue by propagating how actually generated
parameters in codegen relate to source KtParameters'

^KT-28556 Fixed
This commit is contained in:
Denis Zharkov
2018-11-30 15:17:35 +03:00
parent ac19cc9376
commit d7d0407afb
9 changed files with 40 additions and 31 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.asJava.builder
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
@@ -41,7 +42,7 @@ fun JvmDeclarationOrigin.toLightMemberOrigin(): LightElementOrigin {
val originalElement = element
return when (originalElement) {
is KtAnnotationEntry -> DefaultLightElementOrigin(originalElement)
is KtDeclaration -> LightMemberOriginForDeclaration(originalElement, originKind)
is KtDeclaration -> LightMemberOriginForDeclaration(originalElement, originKind, parametersForJvmOverload)
else -> LightElementOrigin.None
}
}
@@ -49,19 +50,24 @@ fun JvmDeclarationOrigin.toLightMemberOrigin(): LightElementOrigin {
interface LightMemberOrigin : LightElementOrigin {
override val originalElement: KtDeclaration?
override val originKind: JvmDeclarationOriginKind
val parametersForJvmOverloads: List<KtParameter?>? get() = null
fun isEquivalentTo(other: LightMemberOrigin?): Boolean
fun copy(): LightMemberOrigin
}
data class LightMemberOriginForDeclaration(override val originalElement: KtDeclaration, override val originKind: JvmDeclarationOriginKind) : LightMemberOrigin {
data class LightMemberOriginForDeclaration(
override val originalElement: KtDeclaration,
override val originKind: JvmDeclarationOriginKind,
override val parametersForJvmOverloads: List<KtParameter?>? = null
) : LightMemberOrigin {
override fun isEquivalentTo(other: LightMemberOrigin?): Boolean {
if (other !is LightMemberOriginForDeclaration) return false
return originalElement.isEquivalentTo(other.originalElement)
}
override fun copy(): LightMemberOrigin {
return LightMemberOriginForDeclaration(originalElement.copy() as KtDeclaration, originKind)
return LightMemberOriginForDeclaration(originalElement.copy() as KtDeclaration, originKind, parametersForJvmOverloads)
}
}
@@ -71,4 +77,4 @@ data class DefaultLightElementOrigin(override val originalElement: PsiElement?)
fun PsiElement?.toLightClassOrigin(): LightElementOrigin {
return if (this != null) DefaultLightElementOrigin(this) else LightElementOrigin.None
}
}
@@ -41,7 +41,7 @@ class KtLightParameter(
if (jetIndex < 0) return null
if (declaration is KtFunction) {
val paramList = declaration.valueParameters
val paramList = method.lightMemberOrigin?.parametersForJvmOverloads ?: declaration.valueParameters
return if (jetIndex < paramList.size) paramList[jetIndex] else null
}
@@ -44,7 +44,6 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getType
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
@@ -260,7 +259,6 @@ class KtLightNullabilityAnnotation(val member: KtLightElement<*, PsiModifierList
if (annotatedElement is KtParameter) {
if (annotatedElement.containingClassOrObject?.isAnnotation() == true) return null
if (isNullableInJvmOverloads(annotatedElement)) return Nullable::class.java.name
}
// don't annotate property setters
@@ -289,13 +287,6 @@ class KtLightNullabilityAnnotation(val member: KtLightElement<*, PsiModifierList
}
}
private fun isNullableInJvmOverloads(annotatedElement: KtParameter): Boolean {
if (annotatedElement.ownerFunction?.let { it.analyze()[BindingContext.DECLARATION_TO_DESCRIPTOR, it]?.findJvmOverloadsAnnotation() } == null) return false
val lightParameterList = (member as? PsiParameter)?.parent as? PsiParameterList ?: return false
val lastParameter = (lightParameterList.parameters.lastOrNull() as? KtLightElement<*, *>)?.kotlinOrigin
return lastParameter == annotatedElement
}
internal fun KtTypeReference.getType(): KotlinType? = analyze()[BindingContext.TYPE, this]
private fun getTargetType(annotatedElement: PsiElement): KotlinType? {
@@ -430,4 +421,4 @@ fun <T> withAllowedAnnotationsClsDelegate(body: () -> T): T {
} finally {
accessAnnotationsClsDelegateIsAllowed = prev
}
}
}
@@ -43,7 +43,6 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getType
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
@@ -261,7 +260,6 @@ class KtLightNullabilityAnnotation(val member: KtLightElement<*, PsiModifierList
if (annotatedElement is KtParameter) {
if (annotatedElement.containingClassOrObject?.isAnnotation() == true) return null
if (isNullableInJvmOverloads(annotatedElement)) return Nullable::class.java.name
}
// don't annotate property setters
@@ -290,13 +288,6 @@ class KtLightNullabilityAnnotation(val member: KtLightElement<*, PsiModifierList
}
}
private fun isNullableInJvmOverloads(annotatedElement: KtParameter): Boolean {
if (annotatedElement.ownerFunction?.let { it.analyze()[BindingContext.DECLARATION_TO_DESCRIPTOR, it]?.findJvmOverloadsAnnotation() } == null) return false
val lightParameterList = (member as? PsiParameter)?.parent as? PsiParameterList ?: return false
val lastParameter = (lightParameterList.parameters.lastOrNull() as? KtLightElement<*, *>)?.kotlinOrigin
return lastParameter == annotatedElement
}
internal fun KtTypeReference.getType(): KotlinType? = analyze()[BindingContext.TYPE, this]
private fun getTargetType(annotatedElement: PsiElement): KotlinType? {
@@ -427,4 +418,4 @@ fun <T> withAllowedAnnotationsClsDelegate(body: () -> T): T {
} finally {
accessAnnotationsClsDelegateIsAllowed = prev
}
}
}