User: joe Date: 09 Nov 25 19:33 Revision: 8fcf79305261b9420505631a1588dacb48c3e396 Summary: Fix @ModifyConstant's expected method signature for class types. Closes #2231, closes #2258 TeamCity URL: http://ci.mcdev.io:80/viewModification.html?tab=vcsModificationFiles&modId=10253&personal=false Index: src/main/kotlin/platform/mixin/handlers/ModifyConstantHandler.kt =================================================================== --- src/main/kotlin/platform/mixin/handlers/ModifyConstantHandler.kt (revision ceb6439288f15d79248f529ff400249c599f19b0) +++ src/main/kotlin/platform/mixin/handlers/ModifyConstantHandler.kt (revision 8fcf79305261b9420505631a1588dacb48c3e396) @@ -25,7 +25,10 @@ import com.demonwav.mcdev.platform.mixin.inspection.injector.MethodSignature import com.demonwav.mcdev.platform.mixin.inspection.injector.ParameterGroup import com.demonwav.mcdev.util.findAnnotations +import com.intellij.openapi.project.Project +import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiAnnotation +import com.intellij.psi.PsiElement import com.intellij.psi.PsiManager import com.intellij.psi.PsiMethod import com.intellij.psi.PsiType @@ -61,6 +64,8 @@ Opcodes.IFGE, Opcodes.IFGT, Opcodes.IFLE, + Opcodes.CHECKCAST, + Opcodes.INSTANCEOF, ) private fun getConstantInfos(modifyConstant: PsiAnnotation): List? { @@ -103,32 +108,91 @@ } val psiManager = PsiManager.getInstance(annotation.project) - return constantInfos.asSequence().map { + return constantInfos.asSequence() + .distinctBy { it.constant?.javaClass } + .flatMap { - when (it.constant) { + when (it.constant) { - null -> PsiType.getJavaLangObject(psiManager, annotation.resolveScope) - is Int -> PsiTypes.intType() - is Float -> PsiTypes.floatType() - is Long -> PsiTypes.longType() - is Double -> PsiTypes.doubleType() - is String -> PsiType.getJavaLangString(psiManager, annotation.resolveScope) - is Type -> PsiType.getJavaLangClass(psiManager, annotation.resolveScope) + null -> sequenceOf( + makeMethodSignature(annotation.project, targetClass, targetMethod, PsiType.getJavaLangObject(psiManager, annotation.resolveScope)) + ) + is Int -> sequenceOf( + makeMethodSignature(annotation.project, targetClass, targetMethod, PsiTypes.intType()), + makeMethodSignature(annotation.project, targetClass, targetMethod, PsiTypes.booleanType()), + makeMethodSignature(annotation.project, targetClass, targetMethod, PsiTypes.byteType()), + makeMethodSignature(annotation.project, targetClass, targetMethod, PsiTypes.charType()), + makeMethodSignature(annotation.project, targetClass, targetMethod, PsiTypes.shortType()), + ) + is Long -> sequenceOf( + makeMethodSignature(annotation.project, targetClass, targetMethod, PsiTypes.longType()) + ) + is Float -> sequenceOf( + makeMethodSignature(annotation.project, targetClass, targetMethod, PsiTypes.floatType()) + ) + is Double -> sequenceOf( + makeMethodSignature(annotation.project, targetClass, targetMethod, PsiTypes.doubleType()) + ) + is String -> sequenceOf( + makeMethodSignature(annotation.project, targetClass, targetMethod, PsiType.getJavaLangString(psiManager, annotation.resolveScope)) + ) + is Type -> sequenceOf( + makeTypeCheckMethodSignature(annotation.project, psiManager, annotation, targetClass, targetMethod, getClassType(psiManager, annotation)), + makeTypeCheckMethodSignature(annotation.project, psiManager, annotation, targetClass, targetMethod, PsiTypes.booleanType()), + ) - else -> throw IllegalStateException("Unknown constant type: ${it.constant.javaClass.name}") - } + else -> throw IllegalStateException("Unknown constant type: ${it.constant.javaClass.name}") + } - }.distinct().map { type -> - MethodSignature( + } + .toList() + } + + private fun makeMethodSignature( + project: Project, + targetClass: ClassNode, + targetMethod: MethodNode, + type: PsiType, + ): MethodSignature { + return MethodSignature( - listOf( - ParameterGroup(listOf(sanitizedParameter(type, "constant"))), - ParameterGroup( + listOf( + ParameterGroup(listOf(sanitizedParameter(type, "constant"))), + ParameterGroup( - collectTargetMethodParameters(annotation.project, targetClass, targetMethod), + collectTargetMethodParameters(project, targetClass, targetMethod), - isVarargs = true, - required = ParameterGroup.RequiredLevel.OPTIONAL, - ), - ), - type, - ) + isVarargs = true, + required = ParameterGroup.RequiredLevel.OPTIONAL, + ), + ), + type, + ) - }.toList() } + private fun makeTypeCheckMethodSignature( + project: Project, + psiManager: PsiManager, + context: PsiElement, + targetClass: ClassNode, + targetMethod: MethodNode, + returnType: PsiType, + ): MethodSignature { + return MethodSignature( + listOf( + ParameterGroup( + listOf( + sanitizedParameter(PsiType.getJavaLangObject(psiManager, context.resolveScope), "instance"), + sanitizedParameter(getClassType(psiManager, context), "type"), + ) + ), + ParameterGroup( + collectTargetMethodParameters(project, targetClass, targetMethod), + isVarargs = true, + required = ParameterGroup.RequiredLevel.OPTIONAL, + ), + ), + returnType, + ) + } + + private fun getClassType(psiManager: PsiManager, context: PsiElement): PsiType { + return JavaPsiFacade.getElementFactory(psiManager.project).createTypeFromText("java.lang.Class", context) + } + override fun isInsnAllowed(insn: AbstractInsnNode, decorations: Map): Boolean { return insn.opcode in allowedOpcodes } Index: src/main/kotlin/platform/mixin/handlers/injectionPoint/AtResolver.kt =================================================================== --- src/main/kotlin/platform/mixin/handlers/injectionPoint/AtResolver.kt (revision ceb6439288f15d79248f529ff400249c599f19b0) +++ src/main/kotlin/platform/mixin/handlers/injectionPoint/AtResolver.kt (revision 8fcf79305261b9420505631a1588dacb48c3e396) @@ -37,9 +37,10 @@ import com.demonwav.mcdev.util.computeStringArray import com.demonwav.mcdev.util.constantStringValue import com.demonwav.mcdev.util.constantValue +import com.demonwav.mcdev.util.descriptor import com.demonwav.mcdev.util.equivalentTo import com.demonwav.mcdev.util.findMethods -import com.demonwav.mcdev.util.fullQualifiedName +import com.demonwav.mcdev.util.internalName import com.intellij.codeInsight.lookup.LookupElementBuilder import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiAnnotation @@ -56,6 +57,7 @@ import com.intellij.psi.PsiQualifiedReference import com.intellij.psi.PsiReference import com.intellij.psi.PsiReferenceExpression +import com.intellij.psi.PsiType import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.util.PsiUtil import com.intellij.psi.util.parents @@ -140,7 +142,8 @@ return value.initializers.map { valueToString(it) ?: return null }.joinToString(",") } return when (val constant = value.constantValue) { - is PsiClassType -> constant.fullQualifiedName?.replace('.', '/') + is PsiClassType -> constant.resolve()?.internalName + is PsiType -> constant.descriptor null -> when (value) { is PsiReferenceExpression -> value.referenceName else -> null