SLC: force boxed return type when needed
e.g., when overriding a function whose return type is not primitive ^KT-57579 Fixed
This commit is contained in:
committed by
Dmitrii Gridin
parent
19dbe69651
commit
1b3b554084
+1
@@ -62,6 +62,7 @@ internal class KtFe10PsiTypeProvider(
|
|||||||
KtTypeMappingMode.GENERIC_ARGUMENT -> TypeMappingMode.GENERIC_ARGUMENT
|
KtTypeMappingMode.GENERIC_ARGUMENT -> TypeMappingMode.GENERIC_ARGUMENT
|
||||||
KtTypeMappingMode.SUPER_TYPE -> TypeMappingMode.SUPER_TYPE
|
KtTypeMappingMode.SUPER_TYPE -> TypeMappingMode.SUPER_TYPE
|
||||||
KtTypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS -> TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS
|
KtTypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS -> TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS
|
||||||
|
KtTypeMappingMode.RETURN_TYPE_BOXED -> TypeMappingMode.RETURN_TYPE_BOXED
|
||||||
KtTypeMappingMode.RETURN_TYPE ->
|
KtTypeMappingMode.RETURN_TYPE ->
|
||||||
typeMapper.typeContext.getOptimalModeForReturnType(type.fe10Type, isAnnotationMethod)
|
typeMapper.typeContext.getOptimalModeForReturnType(type.fe10Type, isAnnotationMethod)
|
||||||
KtTypeMappingMode.VALUE_PARAMETER ->
|
KtTypeMappingMode.VALUE_PARAMETER ->
|
||||||
|
|||||||
+1
@@ -76,6 +76,7 @@ internal class KtFirPsiTypeProvider(
|
|||||||
KtTypeMappingMode.GENERIC_ARGUMENT -> TypeMappingMode.GENERIC_ARGUMENT
|
KtTypeMappingMode.GENERIC_ARGUMENT -> TypeMappingMode.GENERIC_ARGUMENT
|
||||||
KtTypeMappingMode.SUPER_TYPE -> TypeMappingMode.SUPER_TYPE
|
KtTypeMappingMode.SUPER_TYPE -> TypeMappingMode.SUPER_TYPE
|
||||||
KtTypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS -> TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS
|
KtTypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS -> TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS
|
||||||
|
KtTypeMappingMode.RETURN_TYPE_BOXED -> TypeMappingMode.RETURN_TYPE_BOXED
|
||||||
KtTypeMappingMode.RETURN_TYPE ->
|
KtTypeMappingMode.RETURN_TYPE ->
|
||||||
rootModuleSession.jvmTypeMapper.typeContext.getOptimalModeForReturnType(type.coneType, isAnnotationMethod)
|
rootModuleSession.jvmTypeMapper.typeContext.getOptimalModeForReturnType(type.coneType, isAnnotationMethod)
|
||||||
KtTypeMappingMode.VALUE_PARAMETER ->
|
KtTypeMappingMode.VALUE_PARAMETER ->
|
||||||
|
|||||||
@@ -33,6 +33,11 @@ public enum class KtTypeMappingMode {
|
|||||||
*/
|
*/
|
||||||
SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS,
|
SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When method return type should be boxed (e.g., kotlin.Int to Ljava/lang/Integer;)
|
||||||
|
*/
|
||||||
|
RETURN_TYPE_BOXED,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimal mode to convert the return type of declarations if it's part of signature.
|
* Optimal mode to convert the return type of declarations if it's part of signature.
|
||||||
*/
|
*/
|
||||||
|
|||||||
+11
-2
@@ -238,10 +238,19 @@ internal class SymbolLightAccessorMethod private constructor(
|
|||||||
if (!isGetter) return@lazyPub PsiType.VOID
|
if (!isGetter) return@lazyPub PsiType.VOID
|
||||||
|
|
||||||
containingPropertySymbolPointer.withSymbol(ktModule) { propertySymbol ->
|
containingPropertySymbolPointer.withSymbol(ktModule) { propertySymbol ->
|
||||||
propertySymbol.returnType.asPsiType(
|
val ktType = propertySymbol.returnType
|
||||||
|
|
||||||
|
val forceBoxedReturnType = ktType.isPrimitive &&
|
||||||
|
propertySymbol.getAllOverriddenSymbols().any { overriddenSymbol ->
|
||||||
|
!overriddenSymbol.returnType.isPrimitive
|
||||||
|
}
|
||||||
|
|
||||||
|
val typeMappingMode = if (forceBoxedReturnType) KtTypeMappingMode.RETURN_TYPE_BOXED else KtTypeMappingMode.RETURN_TYPE
|
||||||
|
|
||||||
|
ktType.asPsiType(
|
||||||
this@SymbolLightAccessorMethod,
|
this@SymbolLightAccessorMethod,
|
||||||
allowErrorTypes = true,
|
allowErrorTypes = true,
|
||||||
KtTypeMappingMode.RETURN_TYPE,
|
typeMappingMode,
|
||||||
containingClass.isAnnotationType,
|
containingClass.isAnnotationType,
|
||||||
)
|
)
|
||||||
} ?: nonExistentType()
|
} ?: nonExistentType()
|
||||||
|
|||||||
+24
-1
@@ -11,6 +11,8 @@ import kotlinx.collections.immutable.mutate
|
|||||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.analysis.api.annotations.hasAnnotation
|
import org.jetbrains.kotlin.analysis.api.annotations.hasAnnotation
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
|
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
|
||||||
|
import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType
|
||||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode
|
import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
|
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
|
||||||
@@ -177,6 +179,25 @@ internal class SymbolLightSimpleMethod(
|
|||||||
if (isTopLevel) false else withFunctionSymbol { it.isOverride }
|
if (isTopLevel) false else withFunctionSymbol { it.isOverride }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inspired by KotlinTypeMapper#forceBoxedReturnType
|
||||||
|
private fun forceBoxedReturnType(): Boolean {
|
||||||
|
return withFunctionSymbol { functionSymbol ->
|
||||||
|
val returnType = functionSymbol.returnType
|
||||||
|
// 'invoke' methods for lambdas, function literals, and callable references
|
||||||
|
// implicitly override generic 'invoke' from a corresponding base class.
|
||||||
|
if (functionSymbol.isBuiltinFunctionInvoke && returnType.isInlineClassType)
|
||||||
|
return@withFunctionSymbol true
|
||||||
|
|
||||||
|
returnType.isPrimitive &&
|
||||||
|
functionSymbol.getAllOverriddenSymbols().any { overriddenSymbol ->
|
||||||
|
!overriddenSymbol.returnType.isPrimitive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val KtType.isInlineClassType: Boolean
|
||||||
|
get() = ((this as? KtNonErrorClassType)?.classSymbol as? KtNamedClassOrObjectSymbol)?.isInline == true
|
||||||
|
|
||||||
private val KtType.isVoidType: Boolean get() = isUnit && nullabilityType != NullabilityType.Nullable
|
private val KtType.isVoidType: Boolean get() = isUnit && nullabilityType != NullabilityType.Nullable
|
||||||
|
|
||||||
private val _returnedType: PsiType by lazyPub {
|
private val _returnedType: PsiType by lazyPub {
|
||||||
@@ -187,10 +208,12 @@ internal class SymbolLightSimpleMethod(
|
|||||||
functionSymbol.returnType.takeUnless { it.isVoidType } ?: return@withFunctionSymbol PsiType.VOID
|
functionSymbol.returnType.takeUnless { it.isVoidType } ?: return@withFunctionSymbol PsiType.VOID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val typeMappingMode = if (forceBoxedReturnType()) KtTypeMappingMode.RETURN_TYPE_BOXED else KtTypeMappingMode.RETURN_TYPE
|
||||||
|
|
||||||
ktType.asPsiTypeElement(
|
ktType.asPsiTypeElement(
|
||||||
this@SymbolLightSimpleMethod,
|
this@SymbolLightSimpleMethod,
|
||||||
allowErrorTypes = true,
|
allowErrorTypes = true,
|
||||||
KtTypeMappingMode.RETURN_TYPE,
|
typeMappingMode,
|
||||||
this@SymbolLightSimpleMethod.containingClass.isAnnotationType,
|
this@SymbolLightSimpleMethod.containingClass.isAnnotationType,
|
||||||
)?.let {
|
)?.let {
|
||||||
annotateByKtType(it.type, ktType, it, modifierList)
|
annotateByKtType(it.type, ktType, it, modifierList)
|
||||||
|
|||||||
+2
-2
@@ -2,10 +2,10 @@ public final class C /* C*/ implements Tr {
|
|||||||
private final int v;
|
private final int v;
|
||||||
|
|
||||||
@java.lang.Override()
|
@java.lang.Override()
|
||||||
public int foo();// foo()
|
public java.lang.Integer foo();// foo()
|
||||||
|
|
||||||
@java.lang.Override()
|
@java.lang.Override()
|
||||||
public int getV();// getV()
|
public java.lang.Integer getV();// getV()
|
||||||
|
|
||||||
public C();// .ctor()
|
public C();// .ctor()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user