From 9bad113cabe27f97219c54aae618a9d6a3bd4e17 Mon Sep 17 00:00:00 2001 From: Daniil Tsarev Date: Wed, 22 Oct 2025 12:52:33 +0200 Subject: [PATCH] [spring] IDEA-380087 API versioning: provide an inspection and a quick-fix to configure API versioning in tests Relates to IDEA-381232 (cherry picked from commit 8b6e24472a4cbe1362e52e9124d48e5feac6c64e) IJ-MR-179458 GitOrigin-RevId: 1e744850bd2833e0280fedd0ea6d957859736b19 --- .../KotlinUastBaseCodeGenerationPlugin.kt | 31 +++++++++++++ .../uast/generate/UastCodeGenerationPlugin.kt | 15 +++++++ .../generate/JavaUastCodeGenerationPlugin.kt | 44 +++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/plugins/kotlin/uast/uast-kotlin-idea-base/src/org/jetbrains/uast/kotlin/generate/KotlinUastBaseCodeGenerationPlugin.kt b/plugins/kotlin/uast/uast-kotlin-idea-base/src/org/jetbrains/uast/kotlin/generate/KotlinUastBaseCodeGenerationPlugin.kt index 18a7cecdfd6a..9cf90ec54f7d 100644 --- a/plugins/kotlin/uast/uast-kotlin-idea-base/src/org/jetbrains/uast/kotlin/generate/KotlinUastBaseCodeGenerationPlugin.kt +++ b/plugins/kotlin/uast/uast-kotlin-idea-base/src/org/jetbrains/uast/kotlin/generate/KotlinUastBaseCodeGenerationPlugin.kt @@ -79,6 +79,12 @@ abstract class KotlinUastBaseCodeGenerationPlugin : UastCodeGenerationPlugin { return shortenReference(sourcePsi).toUElementOfType() } + override fun shortenReference(uDeclaration: UDeclaration): UDeclaration? { + val sourcePsi = uDeclaration.sourcePsi ?: return null + if (sourcePsi !is KtElement) return null + return shortenReference(sourcePsi).toUElementOfType() + } + abstract fun shortenReference(sourcePsi: KtElement): PsiElement? override fun importMemberOnDemand(reference: UQualifiedReferenceExpression): UExpression? { @@ -296,6 +302,16 @@ abstract class KotlinUastElementFactory(project: Project) : UastElementFactory { return stringBuilder.toString() } + override fun createIntegerConstantExpression( + integer: Int, + context: PsiElement? + ): UExpression? { + return when (val literalExpr = psiFactory(context).createExpression("$integer")) { + is KtConstantExpression -> KotlinULiteralExpression(literalExpr, null) + else -> null + } + } + override fun createLongConstantExpression(long: Long, context: PsiElement?): UExpression? { return when (val literalExpr = psiFactory(context).createExpression(long.toString() + "L")) { is KtConstantExpression -> KotlinULiteralExpression(literalExpr, null) @@ -312,6 +328,21 @@ abstract class KotlinUastElementFactory(project: Project) : UastElementFactory { return psiFactory(context).createComment(text).toUElementOfType()!! } + override fun createClass(className: String, extends: List, implements: List, context: PsiElement): UClass? { + val extendsPart = if (extends.size + implements.size >= 1) + (extends + implements).joinToString(", ", " : ") + else + "" + + val classText = """ + class $className$extendsPart { + } + """.trimIndent() + + val ktClass = psiFactory(context).createClass(classText) + return ktClass.toUElement(UClass::class.java) + } + /*override*/ fun createIntLiteral(value: Int, context: PsiElement?): ULiteralExpression { return psiFactory(context).createExpression(value.toString()).toUElementOfType()!! } diff --git a/uast/uast-common-ide/src/org/jetbrains/uast/generate/UastCodeGenerationPlugin.kt b/uast/uast-common-ide/src/org/jetbrains/uast/generate/UastCodeGenerationPlugin.kt index ee44695b51da..0d200774537b 100644 --- a/uast/uast-common-ide/src/org/jetbrains/uast/generate/UastCodeGenerationPlugin.kt +++ b/uast/uast-common-ide/src/org/jetbrains/uast/generate/UastCodeGenerationPlugin.kt @@ -70,6 +70,10 @@ interface UastCodeGenerationPlugin { */ fun shortenReference(reference: UReferenceExpression): UReferenceExpression? + fun shortenReference(uDeclaration: UDeclaration): UDeclaration? { + throw NotImplementedError() + } + /** * Import the qualifier of the specified element as an on demand import (star import). * @@ -211,11 +215,22 @@ interface UastElementFactory { fun createStringLiteralExpression(text: String, context: PsiElement?): UExpression? + fun createIntegerConstantExpression(integer: Int, context: PsiElement?): UExpression? { + throw NotImplementedError() + } + fun createLongConstantExpression(long: Long, context: PsiElement?): UExpression? fun createNullLiteral(context: PsiElement?): ULiteralExpression? fun createComment(text: String, context: PsiElement?): UComment + + fun createClass(className: String, + extends: List, + implements: List, + context: PsiElement): UClass? { + throw NotImplementedError() + } } @ApiStatus.Experimental diff --git a/uast/uast-java-ide/src/org/jetbrains/uast/java/generate/JavaUastCodeGenerationPlugin.kt b/uast/uast-java-ide/src/org/jetbrains/uast/java/generate/JavaUastCodeGenerationPlugin.kt index 703d743d35f6..d88b1a1e7577 100644 --- a/uast/uast-java-ide/src/org/jetbrains/uast/java/generate/JavaUastCodeGenerationPlugin.kt +++ b/uast/uast-java-ide/src/org/jetbrains/uast/java/generate/JavaUastCodeGenerationPlugin.kt @@ -3,6 +3,7 @@ package org.jetbrains.uast.java.generate import com.intellij.codeInsight.BlockUtils import com.intellij.codeInsight.intention.impl.AddOnDemandStaticImportAction +import com.intellij.ide.highlighter.JavaFileType import com.intellij.lang.Language import com.intellij.lang.java.JavaLanguage import com.intellij.lang.jvm.JvmModifier @@ -16,6 +17,7 @@ import com.intellij.psi.impl.source.tree.CompositeElement import com.intellij.psi.impl.source.tree.ElementType import com.intellij.psi.impl.source.tree.java.PsiLiteralExpressionImpl import com.intellij.psi.util.* +import com.intellij.util.IncorrectOperationException import com.intellij.util.asSafely import com.siyeh.ig.psiutils.CommentTracker import com.siyeh.ig.psiutils.ParenthesesUtils @@ -103,6 +105,12 @@ internal class JavaUastCodeGenerationPlugin : UastCodeGenerationPlugin { return styleManager.shortenClassReferences(sourceReference).toUElementOfType() } + override fun shortenReference(uDeclaration: UDeclaration): UDeclaration? { + val sourceReference = uDeclaration.sourcePsi ?: return null + val styleManager = JavaCodeStyleManager.getInstance(sourceReference.project) + return styleManager.shortenClassReferences(sourceReference).toUElementOfType() + } + override fun importMemberOnDemand(reference: UQualifiedReferenceExpression): UExpression? { val source = reference.sourcePsi ?: return null val (qualifier, selector) = when (source) { @@ -299,6 +307,13 @@ class JavaUastElementFactory(private val project: Project) : UastElementFactory return JavaULiteralExpression(literalExpr, null) } + override fun createIntegerConstantExpression(integer: Int, context: PsiElement?): UExpression? { + return when (val literalExpr = psiFactory.createExpressionFromText("$integer", context)) { + is PsiLiteralExpressionImpl -> JavaULiteralExpression(literalExpr, null) + else -> null + } + } + override fun createLongConstantExpression(long: Long, context: PsiElement?): UExpression? { return when (val literalExpr = psiFactory.createExpressionFromText(long.toString() + "L", context)) { is PsiLiteralExpressionImpl -> JavaULiteralExpression(literalExpr, null) @@ -317,6 +332,35 @@ class JavaUastElementFactory(private val project: Project) : UastElementFactory return psiFactory.createCommentFromText(text, context).toUElementOfType()!! } + override fun createClass(className: String, extends: List, implements: List, context: PsiElement): UClass? { + val extendsPart = if (extends.isNotEmpty()) + " extends " + extends.joinToString() + else + "" + + val implementsPart = if (implements.isNotEmpty()) + " implements " + implements.joinToString() + else + "" + + val classText = """ + class $className$extendsPart$implementsPart { + } + """.trimIndent() + + val aFile = PsiFileFactory.getInstance(context.project) + .createFileFromText("_Dummy_." + JavaFileType.INSTANCE.defaultExtension, + JavaFileType.INSTANCE, + classText) as PsiJavaFile + + val classes = aFile.getClasses() + if (classes.size != 1) { + throw IncorrectOperationException("Incorrect class '$classText'") + } + + return classes[0].toUElement(UClass::class.java) + } + private class MethodCallUpgradeHelper(val project: Project, val methodCall: PsiMethodCallExpression, val expectedReturnType: PsiType) { lateinit var resultType: PsiType