Commit 7b1b9271 authored by Andrei Klunnyi's avatar Andrei Klunnyi Committed by intellij-monorepo-bot
Browse files

KTIJ-18979 Quickfix for INTEGER_OPERATOR_RESOLVE_WILL_CHANGE

^KTIJ-18979 fixed

(cherry picked from commit d7200bfc68da15080a449e631c414686e3e6e34e)

GitOrigin-RevId: 96228eff0e4f43df012be157ba9a7b0028e4962d
parent a63b3c2c
Showing with 181 additions and 1 deletion
+181 -1
......@@ -2124,6 +2124,7 @@ inspection.do.not.propagate.method.deprecation.through.overrides=Do not propagat
inspection.non.exhaustive.when.statement.migration.display.name=Non-exhaustive 'when' statements will be prohibited since 1.7
inspection.prohibit.use.site.target.annotations.on.super.types.migration.display.name=Meaningless annotations targets on superclass
inspection.redundant.label.migration.display.name=Redundant label
inspection.add.conversion.call.display.name=Explicit conversion from `Int` needed since 1.9
inspection.deprecated.inline.classes.migration.display.name=Inline classes are deprecated since 1.5
inspection.deprecated.inline.class.text=Deprecated inline class
inspection.restrict.return.statement.target.migration.display.name=Target label does not denote a function since 1.4
......
<html>
<body>
<p>Reports expressions that will be of type <code>Int</code>, thus causing compilation errors in Kotlin 1.9 and later.</p>
<p>Example:</p>
<pre><code>
fun takeByte(x: Byte) {}
fun foo() {
takeByte(1 + 1) // will be resolved to Int in 1.9
}
</code></pre>
<p>After the quick-fix is applied:</p>
<pre><code>
fun takeByte(x: Byte) {}
fun foo() {
takeByte((1 + 1).toByte()) // will be resolved to Int in 1.9
}
</code></pre>
<p>Inspection is available for Kotlin language level starting from 1.7.</p>
</body>
</html>
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.kotlin.idea.inspections.migration
import com.intellij.codeInspection.CleanupLocalInspectionTool
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.diagnostics.DiagnosticFactoryWithPsiElement
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.configuration.MigrationInfo
import org.jetbrains.kotlin.idea.configuration.isLanguageVersionUpdate
import org.jetbrains.kotlin.idea.quickfix.migration.MigrationFix
import org.jetbrains.kotlin.psi.KtExpression
class AddConversionCallMigrationInspection :
AbstractDiagnosticBasedMigrationInspection<KtExpression>(KtExpression::class.java),
MigrationFix,
CleanupLocalInspectionTool {
override fun isApplicable(migrationInfo: MigrationInfo): Boolean {
return migrationInfo.isLanguageVersionUpdate(LanguageVersion.KOTLIN_1_6, LanguageVersion.KOTLIN_1_7)
}
override fun descriptionMessage(): String = KotlinBundle.message("inspection.add.conversion.call.display.name")
override val diagnosticFactory: DiagnosticFactoryWithPsiElement<KtExpression, *>
get() = Errors.INTEGER_OPERATOR_RESOLVE_WILL_CHANGE
}
\ No newline at end of file
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.quickfix
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.resolve.calls.util.getParameterForArgument
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class AddConversionCallFix(element: KtExpression, val targetType: String) : KotlinQuickFixAction<KtExpression>(element) {
companion object : QuickFixesPsiBasedFactory<PsiElement>(PsiElement::class, PsiElementSuitabilityCheckers.ALWAYS_SUITABLE) {
override fun doCreateQuickFix(psiElement: PsiElement): List<IntentionAction> {
val expression = psiElement.safeAs<KtExpression>() ?: return emptyList()
val targetType = calculateTargetType(expression) ?: return emptyList()
return listOf(AddConversionCallFix(expression, targetType))
}
private fun calculateTargetType(expression: KtExpression): String? {
val valueArgument = expression.getParentOfType<KtValueArgument>(false) ?: return null
val callExpression = valueArgument.getParentOfType<KtCallExpression>(false) ?: return null
val resolvedCall = callExpression.resolveToCall() ?: return null
val parameterDescriptor = resolvedCall.getParameterForArgument(valueArgument) ?: return null
val type = parameterDescriptor.type
return IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_NO_ANNOTATIONS.renderType(type)
}
}
override fun isAvailable(project: Project, editor: Editor?, file: KtFile): Boolean = element != null
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val expression = element ?: return
val convertExpression = KtPsiFactory(file).createExpressionByPattern("($0).to$1()", expression, targetType)
expression.replace(convertExpression)
}
override fun getText(): String {
return KotlinBundle.message("convert.expression.to.0", targetType)
}
override fun getFamilyName(): String = text
}
\ No newline at end of file
......@@ -298,6 +298,8 @@ class QuickFixRegistrar : QuickFixContributor {
INVALID_IF_AS_EXPRESSION.registerFactory(AddIfElseBranchFix)
INVALID_IF_AS_EXPRESSION_WARNING.registerFactory(AddIfElseBranchFix)
INTEGER_OPERATOR_RESOLVE_WILL_CHANGE.registerFactory(AddConversionCallFix)
NO_TYPE_ARGUMENTS_ON_RHS.registerFactory(AddStarProjectionsFixFactory)
TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER.registerFactory(RemovePsiElementSimpleFix.RemoveTypeArgumentsFactory)
......
......@@ -439,6 +439,29 @@ public abstract class QuickFixTestGenerated extends AbstractQuickFixTest {
}
}
 
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("testData/quickfix/addConversionCall")
public static class AddConversionCall extends AbstractQuickFixTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
@TestMetadata("toByte.kt")
public void testToByte() throws Exception {
runTest("testData/quickfix/addConversionCall/toByte.kt");
}
@TestMetadata("toByteExtraParenthesis.kt")
public void testToByteExtraParenthesis() throws Exception {
runTest("testData/quickfix/addConversionCall/toByteExtraParenthesis.kt");
}
@TestMetadata("toShort.kt")
public void testToShort() throws Exception {
runTest("testData/quickfix/addConversionCall/toShort.kt");
}
}
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("testData/quickfix/addCrossinline")
public static class AddCrossinline extends AbstractQuickFixTest {
......
// "Convert expression to 'Byte'" "true"
fun takeByte(x: Byte) {}
fun foo() {
takeByte(1 + 1<caret>)
}
\ No newline at end of file
// "Convert expression to 'Byte'" "true"
fun takeByte(x: Byte) {}
fun foo() {
takeByte((1 + 1).toByte()<caret>)
}
\ No newline at end of file
// "Convert expression to 'Byte'" "true"
fun takeByte(x: Byte) {}
fun foo() {
takeByte(1 + (1 + 1)<caret>)
}
\ No newline at end of file
// "Convert expression to 'Byte'" "true"
fun takeByte(x: Byte) {}
fun foo() {
takeByte((1 + (1 + 1)).toByte()<caret>)
}
\ No newline at end of file
// "Convert expression to 'Short'" "true"
fun takeShort(x: Short) {}
fun foo() {
takeShort(1 + 1<caret>)
}
\ No newline at end of file
// "Convert expression to 'Short'" "true"
fun takeShort(x: Short) {}
fun foo() {
takeShort((1 + 1).toShort())
}
\ No newline at end of file
......@@ -77,4 +77,5 @@ org.jetbrains.kotlin.idea.quickfix.SpecifyTypeExplicitlyFix
org.jetbrains.kotlin.idea.quickfix.SuperClassNotInitialized$AddParenthesisFix
org.jetbrains.kotlin.idea.quickfix.WrapWithSafeLetCallFix
com.intellij.spring.model.highlighting.autowire.SpringUastInjectionPointsAutowiringInspection$AddSpringBeanQualifierFix
org.jetbrains.kotlin.idea.compilerPlugin.parcelize.quickfixes.ParcelMigrateToParcelizeQuickFix
\ No newline at end of file
org.jetbrains.kotlin.idea.compilerPlugin.parcelize.quickfixes.ParcelMigrateToParcelizeQuickFix
org.jetbrains.kotlin.idea.quickfix.AddConversionCallFix
\ No newline at end of file
......@@ -2397,6 +2397,15 @@
language="kotlin"
key="inspection.redundant.label.migration.display.name" bundle="messages.KotlinBundle"/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.migration.AddConversionCallMigrationInspection"
groupPath="Kotlin"
groupBundle="messages.KotlinBundle" groupKey="group.names.migration"
enabledByDefault="false"
cleanupTool="true"
level="WARNING"
language="kotlin"
key="inspection.add.conversion.call.display.name" bundle="messages.KotlinBundle"/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.migration.ProhibitUseSiteTargetAnnotationsOnSuperTypesMigrationInspection"
groupPath="Kotlin"
groupBundle="messages.KotlinBundle" groupKey="group.names.migration"
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment