provide correct context for method return type

to fix generics in

class A<E> {
   fun foo(): E = null!!
}

public class B {
   public static void main(String[] args) {
       A<String> a = new A<>();
       a.foo().length(); // Unresolved length, because it thinks that `a.foo()` returns E
   }
}
This commit is contained in:
peter
2018-10-26 18:42:41 +02:00
parent 23d2269aac
commit cd1560e0b4
2 changed files with 7 additions and 7 deletions
@@ -63,7 +63,7 @@ class KtUltraLightClass(classOrObject: KtClassOrObject, private val support: Ult
private fun allSuperTypes() = private fun allSuperTypes() =
getDescriptor()?.typeConstructor?.supertypes?.mapNotNull { getDescriptor()?.typeConstructor?.supertypes?.mapNotNull {
it.asPsiType(classOrObject, support, TypeMappingMode.SUPER_TYPE) as? PsiClassType it.asPsiType(classOrObject, support, TypeMappingMode.SUPER_TYPE, this) as? PsiClassType
}.orEmpty() }.orEmpty()
override fun createExtendsList(): PsiReferenceList? = override fun createExtendsList(): PsiReferenceList? =
@@ -290,7 +290,7 @@ class KtUltraLightClass(classOrObject: KtClassOrObject, private val support: Ult
} }
val returnType: PsiType? by lazyPub { val returnType: PsiType? by lazyPub {
if (isConstructor) null if (isConstructor) null
else methodReturnType(f) else methodReturnType(f, wrapper)
} }
method.setMethodReturnType { returnType } method.setMethodReturnType { returnType }
return wrapper return wrapper
@@ -303,14 +303,14 @@ class KtUltraLightClass(classOrObject: KtClassOrObject, private val support: Ult
} }
} }
private fun methodReturnType(f: KtDeclaration): PsiType { private fun methodReturnType(f: KtDeclaration, wrapper: KtUltraLightMethod): PsiType {
val desc = f.resolve()?.let { if (it is PropertyDescriptor) it.getter else it } val desc = f.resolve()?.let { if (it is PropertyDescriptor) it.getter else it }
val kotlinType = (desc as? FunctionDescriptor)?.returnType ?: return PsiType.NULL val kotlinType = (desc as? FunctionDescriptor)?.returnType ?: return PsiType.NULL
val mode = when { val mode = when {
typeMapper(support).forceBoxedReturnType(desc) -> TypeMappingMode.RETURN_TYPE_BOXED typeMapper(support).forceBoxedReturnType(desc) -> TypeMappingMode.RETURN_TYPE_BOXED
else -> TypeMappingMode.getOptimalModeForReturnType(kotlinType, false) else -> TypeMappingMode.getOptimalModeForReturnType(kotlinType, false)
} }
return kotlinType.asPsiType(f, support, mode) return kotlinType.asPsiType(f, support, mode, wrapper)
} }
private fun lightMethod(name: String, declaration: KtDeclaration, forceStatic: Boolean): LightMethodBuilder { private fun lightMethod(name: String, declaration: KtDeclaration, forceStatic: Boolean): LightMethodBuilder {
@@ -413,10 +413,10 @@ class KtUltraLightClass(classOrObject: KtClassOrObject, private val support: Ult
if (needsAccessor(ktGetter)) { if (needsAccessor(ktGetter)) {
val getterName = mangleIfNeeded(listOfNotNull(ktGetter, declaration), JvmAbi.getterName(propertyName)) val getterName = mangleIfNeeded(listOfNotNull(ktGetter, declaration), JvmAbi.getterName(propertyName))
val getterType: PsiType by lazyPub { methodReturnType(declaration) }
val getterPrototype = lightMethod(getterName, ktGetter ?: declaration, onlyJvmStatic) val getterPrototype = lightMethod(getterName, ktGetter ?: declaration, onlyJvmStatic)
.setMethodReturnType { getterType }
val getterWrapper = KtUltraLightMethod(getterPrototype, declaration, support, this) val getterWrapper = KtUltraLightMethod(getterPrototype, declaration, support, this)
val getterType: PsiType by lazyPub { methodReturnType(declaration, getterWrapper) }
getterPrototype.setMethodReturnType { getterType }
addReceiverParameter(declaration, getterWrapper) addReceiverParameter(declaration, getterWrapper)
result.add(getterWrapper) result.add(getterWrapper)
} }
@@ -77,7 +77,7 @@ internal fun KotlinType.asPsiType(
declaration: KtDeclaration, declaration: KtDeclaration,
support: UltraLightSupport, support: UltraLightSupport,
mode: TypeMappingMode, mode: TypeMappingMode,
psiContext: PsiElement = declaration psiContext: PsiElement
): PsiType { ): PsiType {
val typeFqName = constructor.declarationDescriptor?.fqNameSafe?.asString() val typeFqName = constructor.declarationDescriptor?.fqNameSafe?.asString()
if (typeFqName == "kotlin.Unit" && declaration is KtFunction) return PsiType.VOID if (typeFqName == "kotlin.Unit" && declaration is KtFunction) return PsiType.VOID