KAPT: Fix error types for receivers and property setters in stubs

When using correct error types and there is a property setter or
receiver for an unknown type then the parameter type would be `Object` instead
of the error type.

This fixes KT-46965 and KT-46966
This commit is contained in:
Nicklas Ansman Giertz
2022-09-16 17:06:35 -04:00
committed by Alexander Udalov
parent dd051c1556
commit 3c69a0493e
5 changed files with 182 additions and 29 deletions
@@ -1017,39 +1017,103 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati
val genericSignature = signatureParser.parseMethodSignature(
method.signature, parameters, exceptionTypes, jcReturnType,
nonErrorParameterTypeProvider = { index, lazyType ->
if (descriptor is PropertySetterDescriptor && valueParametersFromDescriptor.size == 1 && index == 0) {
getNonErrorType(descriptor.correspondingProperty.returnType, METHOD_PARAMETER_TYPE,
ktTypeProvider = {
val setterOrigin = (psiElement as? KtCallableDeclaration)
?.takeIf { it !is KtFunction }
setterOrigin?.typeReference
},
ifNonError = { lazyType() })
} else if (descriptor is FunctionDescriptor && valueParametersFromDescriptor.size == parameters.size) {
val parameterDescriptor = valueParametersFromDescriptor[index]
val sourceElement = when {
psiElement is KtFunction -> psiElement
descriptor is ConstructorDescriptor && descriptor.isPrimary -> (psiElement as? KtClassOrObject)?.primaryConstructor
else -> null
when (descriptor) {
is PropertyGetterDescriptor -> {
if (valueParametersFromDescriptor.isEmpty() && index == 0) {
getNonErrorType(
type = descriptor.correspondingProperty.returnType,
kind = METHOD_PARAMETER_TYPE,
ktTypeProvider = {
when (psiElement) {
is KtCallableDeclaration -> psiElement.takeIf { it !is KtFunction }?.receiverTypeReference
is KtPropertyAccessor -> psiElement.property.receiverTypeReference
else -> null
}
},
ifNonError = lazyType
)
} else {
lazyType()
}
}
getNonErrorType(
parameterDescriptor.type, METHOD_PARAMETER_TYPE,
ktTypeProvider = {
if (sourceElement == null) return@getNonErrorType null
is PropertySetterDescriptor -> when {
valueParametersFromDescriptor.size != 1 -> lazyType()
if (sourceElement.hasDeclaredReturnType() && isContinuationParameter(parameterDescriptor)) {
val continuationTypeFqName = StandardNames.CONTINUATION_INTERFACE_FQ_NAME
val functionReturnType = sourceElement.typeReference!!.text
KtPsiFactory(kaptContext.project).createType("$continuationTypeFqName<$functionReturnType>")
} else {
sourceElement.valueParameters.getOrNull(index)?.typeReference
index == 0 && descriptor.extensionReceiverParameter != null -> {
getNonErrorType(
type = descriptor.extensionReceiverParameter?.type,
kind = METHOD_PARAMETER_TYPE,
ktTypeProvider = {
when (psiElement) {
is KtCallableDeclaration -> psiElement.takeIf { it !is KtFunction }?.receiverTypeReference
is KtPropertyAccessor -> psiElement.property.receiverTypeReference
else -> null
}
},
ifNonError = lazyType
)
}
index == (if (descriptor.extensionReceiverParameter == null) 0 else 1) -> {
getNonErrorType(
type = valueParametersFromDescriptor[0].type,
kind = METHOD_PARAMETER_TYPE,
ktTypeProvider = {
when (psiElement) {
is KtCallableDeclaration -> psiElement.takeIf { it !is KtFunction }?.typeReference
is KtPropertyAccessor -> psiElement.property.typeReference
else -> null
}
},
ifNonError = lazyType
)
}
else -> lazyType()
}
is FunctionDescriptor -> {
val extensionReceiverParameter = descriptor.extensionReceiverParameter
val offset = if (extensionReceiverParameter == null) 0 else 1
if (extensionReceiverParameter != null && index == 0) {
getNonErrorType(
extensionReceiverParameter.type,
METHOD_PARAMETER_TYPE,
ktTypeProvider = {
(psiElement as? KtCallableDeclaration)?.receiverTypeReference
},
ifNonError = lazyType
)
} else if (valueParametersFromDescriptor.size + offset == parameters.size) {
val parameterDescriptor = valueParametersFromDescriptor[index - offset]
val sourceElement = when {
psiElement is KtFunction -> psiElement
descriptor is ConstructorDescriptor && descriptor.isPrimary -> (psiElement as? KtClassOrObject)?.primaryConstructor
else -> null
}
},
ifNonError = { lazyType() })
} else {
lazyType()
getNonErrorType(
parameterDescriptor.type,
METHOD_PARAMETER_TYPE,
ktTypeProvider = {
if (sourceElement == null) return@getNonErrorType null
if (sourceElement.hasDeclaredReturnType() && isContinuationParameter(parameterDescriptor)) {
val continuationTypeFqName = StandardNames.CONTINUATION_INTERFACE_FQ_NAME
val functionReturnType = sourceElement.typeReference!!.text
KtPsiFactory(kaptContext.project).createType("$continuationTypeFqName<$functionReturnType>")
} else {
sourceElement.valueParameters.getOrNull(index)?.typeReference
}
},
ifNonError = lazyType
)
} else {
lazyType()
}
}
else -> lazyType()
}
})
@@ -0,0 +1,20 @@
// CORRECT_ERROR_TYPES
@Suppress("UNRESOLVED_REFERENCE")
class TypeHook {
var customProperty: UnknownType
get() = UnknownType()
set(value) {}
var UnknownType.receiverProperty: UnknownType
get() = UnknownType()
set(value) {}
fun UnknownType.receiverFunction(): UnknownType = UnknownType()
companion object {
var UnknownType.extensionProperty: UnknownType
get() = UnknownType()
set(value) {}
}
}
@@ -0,0 +1,57 @@
import java.lang.System;
@kotlin.Metadata()
@kotlin.Suppress(names = {"UNRESOLVED_REFERENCE"})
public final class TypeHook {
@org.jetbrains.annotations.NotNull()
public static final TypeHook.Companion Companion = null;
public TypeHook() {
super();
}
@org.jetbrains.annotations.NotNull()
public final UnknownType getCustomProperty() {
return null;
}
public final void setCustomProperty(@org.jetbrains.annotations.NotNull()
UnknownType value) {
}
@org.jetbrains.annotations.NotNull()
public final UnknownType getReceiverProperty(@org.jetbrains.annotations.NotNull()
UnknownType $this$receiverProperty) {
return null;
}
public final void setReceiverProperty(@org.jetbrains.annotations.NotNull()
UnknownType $this$receiverProperty, @org.jetbrains.annotations.NotNull()
UnknownType value) {
}
@org.jetbrains.annotations.NotNull()
public final UnknownType receiverFunction(@org.jetbrains.annotations.NotNull()
UnknownType $this$receiverFunction) {
return null;
}
@kotlin.Metadata()
public static final class Companion {
private Companion() {
super();
}
@org.jetbrains.annotations.NotNull()
public final UnknownType getExtensionProperty(@org.jetbrains.annotations.NotNull()
UnknownType $this$extensionProperty) {
return null;
}
public final void setExtensionProperty(@org.jetbrains.annotations.NotNull()
UnknownType $this$extensionProperty, @org.jetbrains.annotations.NotNull()
UnknownType value) {
}
}
}
@@ -181,6 +181,12 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi
runTest("plugins/kapt3/kapt3-compiler/testData/converter/enums.kt");
}
@Test
@TestMetadata("errorExtensionReceiver.kt")
public void testErrorExtensionReceiver() throws Exception {
runTest("plugins/kapt3/kapt3-compiler/testData/converter/errorExtensionReceiver.kt");
}
@Test
@TestMetadata("errorLocationMapping.kt")
public void testErrorLocationMapping() throws Exception {
@@ -181,6 +181,12 @@ public class IrClassFileToSourceStubConverterTestGenerated extends AbstractIrCla
runTest("plugins/kapt3/kapt3-compiler/testData/converter/enums.kt");
}
@Test
@TestMetadata("errorExtensionReceiver.kt")
public void testErrorExtensionReceiver() throws Exception {
runTest("plugins/kapt3/kapt3-compiler/testData/converter/errorExtensionReceiver.kt");
}
@Test
@TestMetadata("errorLocationMapping.kt")
public void testErrorLocationMapping() throws Exception {