[spring] IDEA-352154 Correctly inject prototype beans

GitOrigin-RevId: bd6dc5c920c164302a85fcc6aa451d1bb9a3a41c
This commit is contained in:
Evgenii Zakharchenko
2024-04-22 16:44:45 +02:00
committed by intellij-monorepo-bot
parent 012e6f9c48
commit e4a8575130
9 changed files with 75 additions and 26 deletions

View File

@@ -84,6 +84,7 @@ private class JavaMethodRenderer(
method = insertMethod(method)
method = forcePsiPostprocessAndRestoreElement(method) ?: return
val builder = setupTemplate(method)
builder.setScrollToTemplate(request.isStartTemplate)
method = forcePsiPostprocessAndRestoreElement(method) ?: return
val template = builder.buildInlineTemplate()
startTemplate(method, template)
@@ -107,8 +108,15 @@ private class JavaMethodRenderer(
setModifierProperty(method, modifier.toPsiModifier(), true)
}
val factory = PsiElementFactory.getInstance(project)
for (annotation in request.annotations) {
method.modifierList.addAnnotation(annotation.qualifiedName)
val psiAnotation = method.modifierList.addAnnotation(annotation.qualifiedName)
annotation.attributes.forEach {
val value = CreateAnnotationActionUtil.attributeRequestToValue(it.value, factory, null)
psiAnotation.setDeclaredAttributeValue(it.name, value)
}
}
val shouldHaveBody = !abstract && (!targetClass.isInterface || JvmModifier.STATIC in requestedModifiers)

View File

@@ -542,7 +542,10 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
}
@Suppress("USELESS_CAST") // KT-10755
when {
callableInfo is FunctionInfo -> psiFactory.createFunction("${modifiers}fun<> $header $body") as KtNamedDeclaration
callableInfo is FunctionInfo -> {
val braces = if (isStartTemplate) "<>" else ""
psiFactory.createFunction("${modifiers}fun$braces $header $body") as KtNamedDeclaration
}
(callableInfo as ConstructorInfo).isPrimary -> {
val constructorText = if (modifiers.isNotEmpty()) "${modifiers}constructor$paramList" else paramList
psiFactory.createPrimaryConstructor(constructorText) as KtNamedDeclaration
@@ -601,12 +604,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
}
}
if (callableInfo is PropertyInfo) {
callableInfo.annotations.forEach { declaration.addAnnotationEntry(it) }
}
if (callableInfo is ConstructorInfo) {
callableInfo.annotations.forEach { declaration.addAnnotationEntry(it) }
}
callableInfo.annotations.forEach { declaration.addAnnotationEntry(it) }
val newInitializer = pointerOfAssignmentToReplace?.element
if (newInitializer != null) {

View File

@@ -185,7 +185,8 @@ abstract class CallableInfo(
val possibleContainers: List<KtElement>,
val typeParameterInfos: List<TypeInfo>,
val isForCompanion: Boolean = false,
val modifierList: KtModifierList? = null
val modifierList: KtModifierList? = null,
val annotations: List<KtAnnotationEntry> = emptyList()
) {
abstract val kind: CallableKind
abstract val parameterInfos: List<ParameterInfo>
@@ -208,8 +209,9 @@ class FunctionInfo(
typeParameterInfos: List<TypeInfo> = Collections.emptyList(),
isForCompanion: Boolean = false,
modifierList: KtModifierList? = null,
val preferEmptyBody: Boolean = false
) : CallableInfo(name, receiverTypeInfo, returnTypeInfo, possibleContainers, typeParameterInfos, isForCompanion, modifierList) {
val preferEmptyBody: Boolean = false,
annotations: List<KtAnnotationEntry> = emptyList()
) : CallableInfo(name, receiverTypeInfo, returnTypeInfo, possibleContainers, typeParameterInfos, isForCompanion, modifierList, annotations) {
override val kind: CallableKind get() = CallableKind.FUNCTION
override fun copy(
@@ -224,7 +226,8 @@ class FunctionInfo(
parameterInfos,
typeParameterInfos,
isForCompanion,
modifierList
modifierList,
annotations = annotations
)
}
@@ -258,8 +261,10 @@ class ConstructorInfo(
val isPrimary: Boolean = false,
modifierList: KtModifierList? = null,
val withBody: Boolean = false,
val annotations: List<KtAnnotationEntry> = emptyList()
) : CallableInfo("", TypeInfo.Empty, TypeInfo.Empty, Collections.emptyList(), Collections.emptyList(), false, modifierList = modifierList) {
annotations: List<KtAnnotationEntry> = emptyList()
) : CallableInfo("", TypeInfo.Empty, TypeInfo.Empty, Collections.emptyList(), Collections.emptyList(),
false, modifierList = modifierList,
annotations = annotations) {
override val kind: CallableKind get() = CallableKind.CONSTRUCTOR
override fun copy(
@@ -279,10 +284,10 @@ class PropertyInfo(
val isLateinitPreferred: Boolean = false,
val isConst: Boolean = false,
isForCompanion: Boolean = false,
val annotations: List<KtAnnotationEntry> = emptyList(),
annotations: List<KtAnnotationEntry> = emptyList(),
modifierList: KtModifierList? = null,
val initializer: KtExpression? = null
) : CallableInfo(name, receiverTypeInfo, returnTypeInfo, possibleContainers, typeParameterInfos, isForCompanion, modifierList) {
) : CallableInfo(name, receiverTypeInfo, returnTypeInfo, possibleContainers, typeParameterInfos, isForCompanion, modifierList, annotations) {
override val kind: CallableKind get() = CallableKind.PROPERTY
override val parameterInfos: List<ParameterInfo> get() = Collections.emptyList()

View File

@@ -2,6 +2,7 @@
package org.jetbrains.kotlin.idea.quickfix.crossLanguage
import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.actions.AnnotationRequest
import com.intellij.lang.jvm.actions.CreateMethodRequest
import com.intellij.psi.createSmartPointer
import org.jetbrains.annotations.Nls
@@ -14,13 +15,15 @@ import org.jetbrains.kotlin.idea.quickfix.crossLanguage.KotlinElementActionsFact
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtModifierList
import org.jetbrains.kotlin.psi.KtPsiFactory
class AddMethodCreateCallableFromUsageFix(
private val request: CreateMethodRequest,
modifierList: KtModifierList,
providedText: String,
@Nls familyName: String,
targetContainer: KtElement
targetContainer: KtElement,
val annotations: List<AnnotationRequest> = emptyList(),
) : AbstractCreateCallableFromUsageFixWithTextAndFamilyName<KtElement>(
providedText = providedText,
familyName = familyName,
@@ -44,6 +47,10 @@ class AddMethodCreateCallableFromUsageFix(
val parameterInfos = parameters.map { parameter ->
ParameterInfo(parameter.expectedTypes.toKotlinTypeInfo(resolutionFacade), parameter.semanticNames.toList())
}
val psiFactory = KtPsiFactory(targetContainer.project)
val annotations = annotations.map {
psiFactory.createAnnotationEntry("@${renderAnnotation(targetContainer, it, psiFactory)}")
}
val methodName = request.methodName
FunctionInfo(
methodName,
@@ -53,7 +60,10 @@ class AddMethodCreateCallableFromUsageFix(
parameterInfos,
isForCompanion = JvmModifier.STATIC in request.modifiers,
modifierList = modifierList,
preferEmptyBody = true
preferEmptyBody = true,
annotations = annotations
)
}
override fun isStartTemplate(): Boolean = request.isStartTemplate
}

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2022 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.quickfix.crossLanguage
import com.intellij.lang.jvm.actions.AnnotationRequest
import com.intellij.lang.jvm.types.JvmType
import com.intellij.psi.PsiType
import com.intellij.psi.createSmartPointer
@@ -20,6 +21,7 @@ class AddPropertyActionCreateCallableFromUsageFix(
val propertyName: String,
val setterRequired: Boolean,
val isLateinitPreferred: Boolean = setterRequired,
val annotations: List<AnnotationRequest> = emptyList(),
classOrFileName: String?
) : AbstractPropertyActionCreateCallableFromUsageFix(targetContainer, classOrFileName) {
private val modifierListPointer = modifierList.createSmartPointer()
@@ -34,9 +36,13 @@ class AddPropertyActionCreateCallableFromUsageFix(
val modifierList = modifierListPointer.element ?: return@run null
val resolutionFacade = targetContainer.getResolutionFacade()
val nullableAnyType = resolutionFacade.moduleDescriptor.builtIns.nullableAnyType
val initializer = if (!isLateinitPreferred) {
KtPsiFactory(targetContainer.project).createExpression("TODO(\"initialize me\")")
val psiFactory = KtPsiFactory(targetContainer.project)
val initializer = if(!isLateinitPreferred) {
psiFactory.createExpression("TODO(\"initialize me\")")
} else null
val annotations = annotations.map {
psiFactory.createAnnotationEntry("@${renderAnnotation(targetContainer, it, psiFactory)}")
}
val ktType = (propertyType as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: nullableAnyType
val propertyInfo = PropertyInfo(
propertyName,
@@ -46,7 +52,8 @@ class AddPropertyActionCreateCallableFromUsageFix(
listOf(targetContainer),
modifierList = modifierList,
initializer = initializer,
isLateinitPreferred = isLateinitPreferred
isLateinitPreferred = isLateinitPreferred,
annotations = annotations
)
propertyInfo
}

View File

@@ -2,6 +2,7 @@
package org.jetbrains.kotlin.idea.quickfix.crossLanguage
import com.intellij.codeInsight.Nullability
import com.intellij.codeInsight.daemon.QuickFixBundle
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.codeInsight.intention.QuickFixFactory
@@ -20,6 +21,7 @@ import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl
import com.intellij.psi.util.PropertyUtil
import com.intellij.psi.util.PropertyUtilBase
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.util.asSafely
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.asJava.elements.KtLightElement
@@ -55,6 +57,7 @@ import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
import org.jetbrains.kotlin.resolve.AnnotationChecker
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.types.TypeUtils.makeNullableAsSpecified
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -70,7 +73,10 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
internal fun ExpectedTypes.toKotlinTypeInfo(resolutionFacade: ResolutionFacade): TypeInfo {
val candidateTypes = flatMapTo(LinkedHashSet()) {
val ktType = (it.theType as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: return@flatMapTo emptyList()
var ktType = (it.theType as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: return@flatMapTo emptyList()
if (it.asSafely<ExpectedTypeWithNullability>()?.nullability == Nullability.NULLABLE) {
ktType = makeNullableAsSpecified(ktType, true)
}
when (it.theKind) {
ExpectedType.Kind.EXACT, ExpectedType.Kind.SUBTYPE -> listOf(ktType)
ExpectedType.Kind.SUPERTYPE -> listOf(ktType) + ktType.supertypes()
@@ -271,7 +277,8 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
propertyType: JvmType,
propertyName: String,
setterRequired: Boolean,
classOrFileName: String?
classOrFileName: String?,
annotations: List<AnnotationRequest>
): List<IntentionAction> {
val modifierBuilder = ModifierBuilder(targetContainer).apply { addJvmModifiers(modifiers) }
if (!modifierBuilder.isValid) return emptyList()
@@ -283,6 +290,7 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
propertyName = propertyName,
setterRequired = setterRequired,
isLateinitPreferred = false,
annotations = annotations,
classOrFileName = classOrFileName
)
@@ -294,6 +302,7 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
propertyType = propertyType,
propertyName = propertyName,
setterRequired = true,
annotations = annotations,
classOrFileName = classOrFileName
)
)
@@ -361,7 +370,8 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
propertyType.theType,
nameAndKind.first,
setterRequired,
targetClass.name
targetClass.name,
request.annotations.toList()
)
}
}
@@ -371,7 +381,8 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
modifierList = modifierBuilder.modifierList,
familyName = KotlinBundle.message("add.method"),
providedText = KotlinBundle.message("add.method.0.to.1", methodName, targetClassName.toString()),
targetContainer = targetContainer
targetContainer = targetContainer,
annotations = request.annotations.toList()
)
return listOf(addMethodAction)
@@ -678,7 +689,7 @@ internal fun addAnnotationEntry(
return target.addAnnotationEntry(psiFactory.createAnnotationEntry(annotationText))
}
private fun renderAnnotation(target: PsiElement, request: AnnotationRequest, psiFactory: KtPsiFactory): String {
internal fun renderAnnotation(target: PsiElement, request: AnnotationRequest, psiFactory: KtPsiFactory): String {
val javaPsiFacade = JavaPsiFacade.getInstance(target.project)
fun isKotlinAnnotation(annotation: AnnotationRequest): Boolean =
javaPsiFacade.findClass(annotation.qualifiedName, target.resolveScope)?.language == KotlinLanguage.INSTANCE

View File

@@ -296,6 +296,10 @@ abstract class KotlinUastElementFactory(project: Project) : UastElementFactory {
return psiFactory(context).createExpression("null").toUElementOfType()!!
}
override fun createComment(text: String, context: PsiElement?): UComment {
return psiFactory(context).createComment(text).toUElementOfType()!!
}
/*override*/ fun createIntLiteral(value: Int, context: PsiElement?): ULiteralExpression {
return psiFactory(context).createExpression(value.toString()).toUElementOfType()!!
}

View File

@@ -214,6 +214,8 @@ interface UastElementFactory {
fun createLongConstantExpression(long: Long, context: PsiElement?): UExpression?
fun createNullLiteral(context: PsiElement?): ULiteralExpression?
fun createComment(text: String, context: PsiElement?): UComment
}
@ApiStatus.Experimental

View File

@@ -309,6 +309,10 @@ class JavaUastElementFactory(private val project: Project) : UastElementFactory
return JavaULiteralExpression(literalExpr, null)
}
override fun createComment(text: String, context: PsiElement?): UComment {
return psiFactory.createCommentFromText(text, context).toUElementOfType()!!
}
private class MethodCallUpgradeHelper(val project: Project, val methodCall: PsiMethodCallExpression, val expectedReturnType: PsiType) {
lateinit var resultType: PsiType