[kotlin] Port ConvertKClassToClassFix to K2

^KTIJ-29627

GitOrigin-RevId: 50d35d65b15bf4500450601530ca3fef5f1c4cc8
This commit is contained in:
Andrey Cherkasov
2024-09-17 02:19:04 +04:00
committed by intellij-monorepo-bot
parent 6cffe49c44
commit 629f68c3f2
18 changed files with 229 additions and 54 deletions

View File

@@ -33,10 +33,10 @@ internal object ConvertClassToKClassFixFactories {
private fun KaSession.createFixIfAvailable(element: PsiElement?, expectedType: KaType): ConvertClassToKClassFix? {
val dotQualifiedExpression = element as? KtDotQualifiedExpression ?: return null
if (!expectedType.isKClass()) return null
if (!isKClass(expectedType)) return null
val expressionType = dotQualifiedExpression.expressionType ?: return null
if (!expressionType.isJavaClass()) return null
if (!isJavaClass(expressionType)) return null
val children = dotQualifiedExpression.children
if (children.size != 2) return null
@@ -48,10 +48,7 @@ internal object ConvertClassToKClassFixFactories {
return ConvertClassToKClassFix(dotQualifiedExpression)
}
context(KaSession)
private fun KaType.isKClass(): Boolean = isClassType(StandardClassIds.KClass)
context(KaSession)
private fun KaType.isJavaClass(): Boolean = isClassType(ClassId.fromString("java/lang/Class"))
}
internal fun KaSession.isKClass(type: KaType): Boolean = type.isClassType(StandardClassIds.KClass)
internal fun KaSession.isJavaClass(type: KaType): Boolean = type.isClassType(ClassId.fromString("java/lang/Class"))

View File

@@ -0,0 +1,53 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.k2.codeinsight.fixes
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.KaSession
import org.jetbrains.kotlin.analysis.api.fir.diagnostics.KaFirDiagnostic
import org.jetbrains.kotlin.analysis.api.types.KaType
import org.jetbrains.kotlin.idea.codeinsight.api.applicators.fixes.KotlinQuickFixFactory
import org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPsiFactory
internal object ConvertKClassToClassFixFactories {
val argumentTypeMismatchFixFactory = KotlinQuickFixFactory.ModCommandBased { diagnostic: KaFirDiagnostic.ArgumentTypeMismatch ->
listOfNotNull(
createFixIfAvailable(diagnostic.psi, diagnostic.expectedType, diagnostic.actualType)
)
}
val returnTypeMismatchFixFactory = KotlinQuickFixFactory.ModCommandBased { diagnostic: KaFirDiagnostic.ReturnTypeMismatch ->
listOfNotNull(
createFixIfAvailable(diagnostic.psi, diagnostic.expectedType, diagnostic.actualType)
)
}
val initializerTypeMismatchFixFactory = KotlinQuickFixFactory.ModCommandBased { diagnostic: KaFirDiagnostic.InitializerTypeMismatch ->
listOfNotNull(
createFixIfAvailable((diagnostic.psi as? KtProperty)?.initializer, diagnostic.expectedType, diagnostic.actualType)
)
}
val assignmentTypeMismatchFixFactory = KotlinQuickFixFactory.ModCommandBased { diagnostic: KaFirDiagnostic.AssignmentTypeMismatch ->
listOfNotNull(
createFixIfAvailable(diagnostic.psi, diagnostic.expectedType, diagnostic.actualType)
)
}
private fun KaSession.createFixIfAvailable(
element: PsiElement?,
expectedType: KaType,
actualType: KaType,
): ConvertKClassToClassFix? {
if (element !is KtExpression) return null
if (!isKClass(actualType) || !isJavaClass(expectedType)) return null
val codeFragment = KtPsiFactory(element.project).createExpressionCodeFragment(element.text + ".java", element)
val contentElement = codeFragment.getContentElement() ?: return null
val javaLangClassType = contentElement.expressionType ?: return null
if (!javaLangClassType.isSubtypeOf(expectedType)) return null
return ConvertKClassToClassFix(element)
}
}

View File

@@ -175,6 +175,10 @@ class KotlinK2QuickFixRegistrar : KotlinQuickFixRegistrar() {
registerFactory(DeclarationCantBeInlinedFixFactories.removeOpenModifierFixFactory)
registerFactory(WrongAnnotationTargetFixFactories.addAnnotationUseSiteTargetFixFactory)
registerFactory(FinalUpperBoundFixFactories.inlineTypeParameterFixFactory)
registerFactory(ConvertKClassToClassFixFactories.argumentTypeMismatchFixFactory)
registerFactory(ConvertKClassToClassFixFactories.assignmentTypeMismatchFixFactory)
registerFactory(ConvertKClassToClassFixFactories.initializerTypeMismatchFixFactory)
registerFactory(ConvertKClassToClassFixFactories.returnTypeMismatchFixFactory)
}
private val addAbstract = KtQuickFixesListBuilder.registerPsiQuickFix {

View File

@@ -4159,6 +4159,55 @@ public abstract class HighLevelQuickFixTestGenerated extends AbstractHighLevelQu
}
}
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("../../../idea/tests/testData/quickfix/typeMismatch/convertKClassToJavaClass")
public static class ConvertKClassToJavaClass extends AbstractHighLevelQuickFixTest {
@java.lang.Override
@org.jetbrains.annotations.NotNull
public final KotlinPluginMode getPluginMode() {
return KotlinPluginMode.K2;
}
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
@TestMetadata("argument.kt")
public void testArgument() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/convertKClassToJavaClass/argument.kt");
}
@TestMetadata("argumentVariable.kt")
public void testArgumentVariable() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/convertKClassToJavaClass/argumentVariable.kt");
}
@TestMetadata("assignment.kt")
public void testAssignment() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/convertKClassToJavaClass/assignment.kt");
}
@TestMetadata("initializer.kt")
public void testInitializer() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/convertKClassToJavaClass/initializer.kt");
}
@TestMetadata("return.kt")
public void testReturn() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/convertKClassToJavaClass/return.kt");
}
@TestMetadata("subtype.kt")
public void testSubtype() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/convertKClassToJavaClass/subtype.kt");
}
@TestMetadata("typeMismatch.kt")
public void testTypeMismatch() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/convertKClassToJavaClass/typeMismatch.kt");
}
}
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("../../../idea/tests/testData/quickfix/typeMismatch/incompatibleTypes")
public static class IncompatibleTypes extends AbstractHighLevelQuickFixTest {
@@ -4495,26 +4544,6 @@ public abstract class HighLevelQuickFixTestGenerated extends AbstractHighLevelQu
runTest("../../../idea/tests/testData/quickfix/typeMismatch/parameterTypeMismatch/char.kt");
}
@TestMetadata("convertKClassToJavaClass.kt")
public void testConvertKClassToJavaClass() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/parameterTypeMismatch/convertKClassToJavaClass.kt");
}
@TestMetadata("convertKClassToJavaClassSubtype.kt")
public void testConvertKClassToJavaClassSubtype() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/parameterTypeMismatch/convertKClassToJavaClassSubtype.kt");
}
@TestMetadata("convertKClassToJavaClassTypeMismatch.kt")
public void testConvertKClassToJavaClassTypeMismatch() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/parameterTypeMismatch/convertKClassToJavaClassTypeMismatch.kt");
}
@TestMetadata("convertKClassToJavaClassVariable.kt")
public void testConvertKClassToJavaClassVariable() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/parameterTypeMismatch/convertKClassToJavaClassVariable.kt");
}
@TestMetadata("genericType.kt")
public void testGenericType() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/parameterTypeMismatch/genericType.kt");

View File

@@ -17887,6 +17887,55 @@ public abstract class K1QuickFixTestGenerated extends AbstractK1QuickFixTest {
}
}
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("testData/quickfix/typeMismatch/convertKClassToJavaClass")
public static class ConvertKClassToJavaClass extends AbstractK1QuickFixTest {
@java.lang.Override
@org.jetbrains.annotations.NotNull
public final KotlinPluginMode getPluginMode() {
return KotlinPluginMode.K1;
}
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
@TestMetadata("argument.kt")
public void testArgument() throws Exception {
runTest("testData/quickfix/typeMismatch/convertKClassToJavaClass/argument.kt");
}
@TestMetadata("argumentVariable.kt")
public void testArgumentVariable() throws Exception {
runTest("testData/quickfix/typeMismatch/convertKClassToJavaClass/argumentVariable.kt");
}
@TestMetadata("assignment.kt")
public void testAssignment() throws Exception {
runTest("testData/quickfix/typeMismatch/convertKClassToJavaClass/assignment.kt");
}
@TestMetadata("initializer.kt")
public void testInitializer() throws Exception {
runTest("testData/quickfix/typeMismatch/convertKClassToJavaClass/initializer.kt");
}
@TestMetadata("return.kt")
public void testReturn() throws Exception {
runTest("testData/quickfix/typeMismatch/convertKClassToJavaClass/return.kt");
}
@TestMetadata("subtype.kt")
public void testSubtype() throws Exception {
runTest("testData/quickfix/typeMismatch/convertKClassToJavaClass/subtype.kt");
}
@TestMetadata("typeMismatch.kt")
public void testTypeMismatch() throws Exception {
runTest("testData/quickfix/typeMismatch/convertKClassToJavaClass/typeMismatch.kt");
}
}
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("testData/quickfix/typeMismatch/definitelyNonNullableTypes")
public static class DefinitelyNonNullableTypes extends AbstractK1QuickFixTest {
@@ -18301,26 +18350,6 @@ public abstract class K1QuickFixTestGenerated extends AbstractK1QuickFixTest {
runTest("testData/quickfix/typeMismatch/parameterTypeMismatch/char.kt");
}
@TestMetadata("convertKClassToJavaClass.kt")
public void testConvertKClassToJavaClass() throws Exception {
runTest("testData/quickfix/typeMismatch/parameterTypeMismatch/convertKClassToJavaClass.kt");
}
@TestMetadata("convertKClassToJavaClassSubtype.kt")
public void testConvertKClassToJavaClassSubtype() throws Exception {
runTest("testData/quickfix/typeMismatch/parameterTypeMismatch/convertKClassToJavaClassSubtype.kt");
}
@TestMetadata("convertKClassToJavaClassTypeMismatch.kt")
public void testConvertKClassToJavaClassTypeMismatch() throws Exception {
runTest("testData/quickfix/typeMismatch/parameterTypeMismatch/convertKClassToJavaClassTypeMismatch.kt");
}
@TestMetadata("convertKClassToJavaClassVariable.kt")
public void testConvertKClassToJavaClassVariable() throws Exception {
runTest("testData/quickfix/typeMismatch/parameterTypeMismatch/convertKClassToJavaClassVariable.kt");
}
@TestMetadata("genericType.kt")
public void testGenericType() throws Exception {
runTest("testData/quickfix/typeMismatch/parameterTypeMismatch/genericType.kt");

View File

@@ -6,5 +6,5 @@ fun main() {
}
fun acceptClass(cls: Class<*>) = Unit
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix

View File

@@ -6,5 +6,5 @@ fun main() {
}
fun acceptClass(cls: Class<*>) = Unit
/* IGNORE_K2 */
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix

View File

@@ -9,4 +9,4 @@ fun main() {
fun acceptClass(cls: Class<*>) = Unit
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix
/* IGNORE_K2 */
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix

View File

@@ -9,4 +9,4 @@ fun main() {
fun acceptClass(cls: Class<*>) = Unit
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix
/* IGNORE_K2 */
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix

View File

@@ -0,0 +1,11 @@
// "Convert 'KClass' to 'Class'" "true"
// WITH_STDLIB
fun foo() {
val clazz = String::class
val cls: Class<*>
cls = clazz<caret>
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix

View File

@@ -0,0 +1,11 @@
// "Convert 'KClass' to 'Class'" "true"
// WITH_STDLIB
fun foo() {
val clazz = String::class
val cls: Class<*>
cls = clazz.java
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix

View File

@@ -0,0 +1,9 @@
// "Convert 'KClass' to 'Class'" "true"
// WITH_STDLIB
fun foo() {
val cls: Class<*> = String::class<caret>
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix

View File

@@ -0,0 +1,9 @@
// "Convert 'KClass' to 'Class'" "true"
// WITH_STDLIB
fun foo() {
val cls: Class<*> = String::class.java
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix

View File

@@ -0,0 +1,11 @@
// "Convert 'KClass' to 'Class'" "true"
// WITH_STDLIB
fun foo(): Class<*> {
return Foo::class<caret>
}
class Foo
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix

View File

@@ -0,0 +1,11 @@
// "Convert 'KClass' to 'Class'" "true"
// WITH_STDLIB
fun foo(): Class<*> {
return Foo::class.java
}
class Foo
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.ConvertKClassToClassFix

View File

@@ -49,6 +49,7 @@ internal fun MutableTWorkspace.generateK2FixTests() {
model("$idea/quickfix/typeAddition", pattern = pattern)
model("$idea/quickfix/typeMismatch/casts", pattern = pattern)
model("$idea/quickfix/typeMismatch/componentFunctionReturnTypeMismatch", pattern = pattern)
model("$idea/quickfix/typeMismatch/convertKClassToJavaClass", pattern = pattern)
model("$idea/quickfix/typeMismatch/incompatibleTypes", pattern = pattern)
model("$idea/quickfix/typeMismatch/numberConversion", pattern = pattern)
model("$idea/quickfix/typeMismatch/parameterTypeMismatch", pattern = pattern)