Suggest quick-fixes for SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED
#KT-27590 Fixed
This commit is contained in:
@@ -138,6 +138,20 @@ class IntegerValueTypeConstant(
|
|||||||
|
|
||||||
return IntegerValueTypeConstant(value, module, newParameters, convertedFromSigned = true)
|
return IntegerValueTypeConstant(value, module, newParameters, convertedFromSigned = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun IntegerValueTypeConstant.convertToSignedConstant(module: ModuleDescriptor): IntegerValueTypeConstant {
|
||||||
|
val newParameters = CompileTimeConstant.Parameters(
|
||||||
|
parameters.canBeUsedInAnnotation,
|
||||||
|
parameters.isPure,
|
||||||
|
isUnsignedNumberLiteral = false,
|
||||||
|
isUnsignedLongNumberLiteral = parameters.isUnsignedLongNumberLiteral,
|
||||||
|
usesVariableAsConstant = parameters.usesVariableAsConstant,
|
||||||
|
usesNonConstValAsConstant = parameters.usesNonConstValAsConstant,
|
||||||
|
isConvertableConstVal = parameters.isConvertableConstVal
|
||||||
|
)
|
||||||
|
|
||||||
|
return IntegerValueTypeConstant(value, module, newParameters, convertedFromSigned = true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val typeConstructor = IntegerValueTypeConstructor(value.toLong(), module, parameters)
|
private val typeConstructor = IntegerValueTypeConstructor(value.toLong(), module, parameters)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic
|
|||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
|
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
|
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil
|
import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil
|
||||||
import org.jetbrains.kotlin.idea.util.approximateWithResolvableType
|
import org.jetbrains.kotlin.idea.util.approximateWithResolvableType
|
||||||
@@ -34,6 +35,7 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getTargetFunction
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.getTargetFunction
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument
|
||||||
@@ -41,10 +43,12 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getParentResolvedCall
|
|||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentForExpression
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentForExpression
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
|
||||||
import org.jetbrains.kotlin.types.typeUtil.*
|
import org.jetbrains.kotlin.types.typeUtil.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -90,16 +94,28 @@ class QuickFixFactoryForTypeMismatchError : KotlinIntentionActionsFactory() {
|
|||||||
val diagnosticWithParameters = Errors.CONSTANT_EXPECTED_TYPE_MISMATCH.cast(diagnostic)
|
val diagnosticWithParameters = Errors.CONSTANT_EXPECTED_TYPE_MISMATCH.cast(diagnostic)
|
||||||
expectedType = diagnosticWithParameters.b
|
expectedType = diagnosticWithParameters.b
|
||||||
expressionType = context.getType(diagnosticElement)
|
expressionType = context.getType(diagnosticElement)
|
||||||
if (expressionType == null) {
|
}
|
||||||
LOG.error("No type inferred: " + diagnosticElement.text)
|
Errors.SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED -> {
|
||||||
return emptyList()
|
val constantValue = context[BindingContext.COMPILE_TIME_VALUE, diagnosticElement]
|
||||||
}
|
if (constantValue is IntegerValueTypeConstant) {
|
||||||
|
// Here we have unsigned type (despite really constant is signed)
|
||||||
|
expectedType = constantValue.getType(NO_EXPECTED_TYPE)
|
||||||
|
val signedConstantValue = with(IntegerValueTypeConstant) {
|
||||||
|
constantValue.convertToSignedConstant(diagnosticElement.findModuleDescriptor())
|
||||||
|
}
|
||||||
|
// And here we have signed type
|
||||||
|
expressionType = signedConstantValue.getType(NO_EXPECTED_TYPE)
|
||||||
|
} else return emptyList()
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
LOG.error("Unexpected diagnostic: " + DefaultErrorMessages.render(diagnostic))
|
LOG.error("Unexpected diagnostic: " + DefaultErrorMessages.render(diagnostic))
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (expressionType == null) {
|
||||||
|
LOG.error("No type inferred: " + diagnosticElement.text)
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
if (expressionType.isPrimitiveNumberType() && expectedType.isPrimitiveNumberType()) {
|
if (expressionType.isPrimitiveNumberType() && expectedType.isPrimitiveNumberType()) {
|
||||||
var wrongPrimitiveLiteralFix: WrongPrimitiveLiteralFix? = null
|
var wrongPrimitiveLiteralFix: WrongPrimitiveLiteralFix? = null
|
||||||
@@ -240,10 +256,10 @@ class QuickFixFactoryForTypeMismatchError : KotlinIntentionActionsFactory() {
|
|||||||
val correspondingParameterDescriptor = resolvedCall.getParameterForArgument(valueArgument)
|
val correspondingParameterDescriptor = resolvedCall.getParameterForArgument(valueArgument)
|
||||||
val correspondingParameter = QuickFixUtil.safeGetDeclaration(correspondingParameterDescriptor) as? KtParameter
|
val correspondingParameter = QuickFixUtil.safeGetDeclaration(correspondingParameterDescriptor) as? KtParameter
|
||||||
val expressionFromArgument = valueArgument.getArgumentExpression()
|
val expressionFromArgument = valueArgument.getArgumentExpression()
|
||||||
val valueArgumentType = if (diagnostic.factory === Errors.NULL_FOR_NONNULL_TYPE)
|
val valueArgumentType = when (diagnostic.factory) {
|
||||||
expressionType
|
Errors.NULL_FOR_NONNULL_TYPE, Errors.SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED -> expressionType
|
||||||
else
|
else -> expressionFromArgument?.let { context.getType(it) }
|
||||||
expressionFromArgument?.let { context.getType(it) }
|
}
|
||||||
if (valueArgumentType != null) {
|
if (valueArgumentType != null) {
|
||||||
if (correspondingParameter != null) {
|
if (correspondingParameter != null) {
|
||||||
val callable = PsiTreeUtil.getParentOfType(correspondingParameter, KtCallableDeclaration::class.java, true)
|
val callable = PsiTreeUtil.getParentOfType(correspondingParameter, KtCallableDeclaration::class.java, true)
|
||||||
|
|||||||
@@ -370,6 +370,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
|||||||
NULL_FOR_NONNULL_TYPE.registerFactory(factoryForTypeMismatchError)
|
NULL_FOR_NONNULL_TYPE.registerFactory(factoryForTypeMismatchError)
|
||||||
CONSTANT_EXPECTED_TYPE_MISMATCH.registerFactory(factoryForTypeMismatchError)
|
CONSTANT_EXPECTED_TYPE_MISMATCH.registerFactory(factoryForTypeMismatchError)
|
||||||
TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.registerFactory(factoryForTypeMismatchError)
|
TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.registerFactory(factoryForTypeMismatchError)
|
||||||
|
SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED.registerFactory(factoryForTypeMismatchError)
|
||||||
|
|
||||||
SMARTCAST_IMPOSSIBLE.registerFactory(SmartCastImpossibleExclExclFixFactory)
|
SMARTCAST_IMPOSSIBLE.registerFactory(SmartCastImpossibleExclExclFixFactory)
|
||||||
SMARTCAST_IMPOSSIBLE.registerFactory(CastExpressionFix.SmartCastImpossibleFactory)
|
SMARTCAST_IMPOSSIBLE.registerFactory(CastExpressionFix.SmartCastImpossibleFactory)
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// "Change parameter 'u' type of function 'takeUInt' to 'Int'" "true"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun takeUInt(u: UInt) = 0
|
||||||
|
|
||||||
|
val b = takeUInt(<caret>1)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// "Change parameter 'u' type of function 'takeUInt' to 'Int'" "true"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun takeUInt(u: Int) = 0
|
||||||
|
|
||||||
|
val b = takeUInt(1)
|
||||||
@@ -12531,6 +12531,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
|||||||
public void testMultiFakeOverride() throws Exception {
|
public void testMultiFakeOverride() throws Exception {
|
||||||
runTest("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/multiFakeOverride.kt");
|
runTest("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/multiFakeOverride.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsigned.kt")
|
||||||
|
public void testUnsigned() throws Exception {
|
||||||
|
runTest("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/unsigned.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression")
|
@TestMetadata("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression")
|
||||||
|
|||||||
Reference in New Issue
Block a user