Skip to content

Commit e10f752

Browse files
committed
Change @Local and @ModifyVariable argsOnly inspections so they also work if the local is specified by name
1 parent 175d500 commit e10f752

File tree

2 files changed

+51
-52
lines changed

2 files changed

+51
-52
lines changed

src/main/kotlin/platform/mixin/inspection/injector/ModifyVariableArgsOnlyInspection.kt

Lines changed: 41 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,22 @@
2020

2121
package com.demonwav.mcdev.platform.mixin.inspection.injector
2222

23+
import com.demonwav.mcdev.platform.mixin.handlers.InjectorAnnotationHandler
2324
import com.demonwav.mcdev.platform.mixin.handlers.MixinAnnotationHandler
25+
import com.demonwav.mcdev.platform.mixin.handlers.injectionPoint.CollectVisitor
2426
import com.demonwav.mcdev.platform.mixin.inspection.MixinInspection
2527
import com.demonwav.mcdev.platform.mixin.inspection.fix.AnnotationAttributeFix
26-
import com.demonwav.mcdev.platform.mixin.util.ClassAndMethodNode
28+
import com.demonwav.mcdev.platform.mixin.util.LocalInfo
2729
import com.demonwav.mcdev.platform.mixin.util.MethodTargetMember
2830
import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Annotations.MODIFY_VARIABLE
2931
import com.demonwav.mcdev.platform.mixin.util.hasAccess
30-
import com.demonwav.mcdev.util.constantValue
31-
import com.demonwav.mcdev.util.descriptor
3232
import com.demonwav.mcdev.util.findAnnotation
33-
import com.demonwav.mcdev.util.ifEmpty
33+
import com.demonwav.mcdev.util.findModule
3434
import com.intellij.codeInspection.ProblemsHolder
3535
import com.intellij.psi.JavaElementVisitor
3636
import com.intellij.psi.PsiAnnotation
3737
import com.intellij.psi.PsiElementVisitor
3838
import com.intellij.psi.PsiMethod
39-
import com.intellij.psi.PsiType
4039
import org.objectweb.asm.Opcodes
4140
import org.objectweb.asm.Type
4241

@@ -48,15 +47,14 @@ class ModifyVariableArgsOnlyInspection : MixinInspection() {
4847
return object : JavaElementVisitor() {
4948
override fun visitMethod(method: PsiMethod) {
5049
val modifyVariable = method.findAnnotation(MODIFY_VARIABLE) ?: return
51-
val wantedType = method.parameterList.getParameter(0)?.type ?: return
50+
val localType = method.parameterList.getParameter(0)?.type ?: return
5251
val problemElement = modifyVariable.nameReferenceElement ?: return
5352

54-
val targets = MixinAnnotationHandler.resolveTarget(modifyVariable).ifEmpty { return }
55-
val methodTargets = targets.asSequence()
56-
.filterIsInstance<MethodTargetMember>()
57-
.map { it.classAndMethod }
53+
val injector =
54+
MixinAnnotationHandler.forMixinAnnotation(MODIFY_VARIABLE) as? InjectorAnnotationHandler ?: return
55+
val localInfo = LocalInfo.fromAnnotation(localType, modifyVariable)
5856

59-
if (shouldReport(modifyVariable, wantedType, methodTargets)) {
57+
if (shouldReport(localInfo, injector, modifyVariable)) {
6058
val description = "@ModifyVariable may be argsOnly = true"
6159
holder.registerProblem(
6260
problemElement,
@@ -70,46 +68,47 @@ class ModifyVariableArgsOnlyInspection : MixinInspection() {
7068

7169
companion object {
7270
fun shouldReport(
73-
annotation: PsiAnnotation,
74-
wantedType: PsiType,
75-
methodTargets: Sequence<ClassAndMethodNode>,
71+
localInfo: LocalInfo,
72+
injector: InjectorAnnotationHandler,
73+
injectorAnnotation: PsiAnnotation,
7674
): Boolean {
77-
if (annotation.findDeclaredAttributeValue("argsOnly")?.constantValue == true) {
75+
if (localInfo.argsOnly) {
7876
return false
7977
}
8078

81-
val ordinal = (annotation.findDeclaredAttributeValue("ordinal")?.constantValue as? Int?)
82-
?.takeIf { it != -1 }
83-
val index = (annotation.findDeclaredAttributeValue("index")?.constantValue as? Int?)
84-
?.takeIf { it != -1 }
85-
if (ordinal == null && index == null && annotation.findDeclaredAttributeValue("name") != null) {
86-
return false
87-
}
79+
val localInfo = LocalInfo(
80+
localInfo.type,
81+
argsOnly = true,
82+
localInfo.index,
83+
localInfo.ordinal,
84+
localInfo.names,
85+
)
86+
87+
val module = injectorAnnotation.findModule() ?: return false
8888

89-
val wantedDesc = wantedType.descriptor
89+
for (targetMember in MixinAnnotationHandler.resolveTarget(injectorAnnotation)) {
90+
val (targetClass, targetMethod) = (targetMember as? MethodTargetMember)?.classAndMethod ?: continue
91+
val resolvedInsns = injector.resolveInstructions(injectorAnnotation, targetClass, targetMethod)
9092

91-
for ((_, targetMethod) in methodTargets) {
92-
val argTypes = mutableListOf<String?>()
93-
if (!targetMethod.hasAccess(Opcodes.ACC_STATIC)) {
94-
argTypes += null
93+
if (resolvedInsns.isEmpty()) {
94+
// unresolved injection point, don't report that we can be argsOnly
95+
return false
9596
}
96-
for (arg in Type.getArgumentTypes(targetMethod.desc)) {
97-
argTypes += arg.descriptor
98-
if (arg.size == 2) {
99-
argTypes += null
100-
}
97+
98+
var argumentsSize = Type.getArgumentsAndReturnSizes(targetMethod.desc) shr 2
99+
if (targetMethod.hasAccess(Opcodes.ACC_STATIC)) {
100+
argumentsSize--
101101
}
102102

103-
if (ordinal != null) {
104-
if (argTypes.asSequence().filter { it == wantedDesc }.count() <= ordinal) {
105-
return false
106-
}
107-
} else if (index != null) {
108-
if (argTypes.size <= index) {
109-
return false
110-
}
111-
} else {
112-
if (argTypes.asSequence().filter { it == wantedDesc }.count() != 1) {
103+
for (insn in resolvedInsns) {
104+
val matchedLocals = localInfo.matchLocals(
105+
module,
106+
targetClass,
107+
targetMethod,
108+
insn.insn,
109+
CollectVisitor.Mode.RESOLUTION
110+
)
111+
if (matchedLocals.isNullOrEmpty() || matchedLocals.any { it.index >= argumentsSize }) {
113112
return false
114113
}
115114
}

src/main/kotlin/platform/mixin/inspection/mixinextras/LocalArgsOnlyInspection.kt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,21 @@
2020

2121
package com.demonwav.mcdev.platform.mixin.inspection.mixinextras
2222

23+
import com.demonwav.mcdev.platform.mixin.handlers.InjectorAnnotationHandler
2324
import com.demonwav.mcdev.platform.mixin.handlers.MixinAnnotationHandler
2425
import com.demonwav.mcdev.platform.mixin.inspection.MixinInspection
2526
import com.demonwav.mcdev.platform.mixin.inspection.fix.AnnotationAttributeFix
2627
import com.demonwav.mcdev.platform.mixin.inspection.injector.ModifyVariableArgsOnlyInspection
27-
import com.demonwav.mcdev.platform.mixin.util.MethodTargetMember
28+
import com.demonwav.mcdev.platform.mixin.util.LocalInfo
2829
import com.demonwav.mcdev.platform.mixin.util.MixinConstants
2930
import com.demonwav.mcdev.platform.mixin.util.unwrapLocalRef
3031
import com.demonwav.mcdev.util.constantValue
31-
import com.demonwav.mcdev.util.findContainingMethod
32-
import com.demonwav.mcdev.util.ifEmpty
32+
import com.demonwav.mcdev.util.mapFirstNotNull
3333
import com.intellij.codeInspection.ProblemsHolder
3434
import com.intellij.psi.JavaElementVisitor
3535
import com.intellij.psi.PsiAnnotation
3636
import com.intellij.psi.PsiElementVisitor
37+
import com.intellij.psi.PsiMethod
3738
import com.intellij.psi.PsiParameter
3839
import com.intellij.psi.util.parentOfType
3940

@@ -50,17 +51,16 @@ class LocalArgsOnlyInspection : MixinInspection() {
5051
return
5152
}
5253
val parameter = localAnnotation.parentOfType<PsiParameter>() ?: return
53-
val method = parameter.findContainingMethod() ?: return
54+
val method = parameter.declarationScope as? PsiMethod ?: return
5455

55-
val targets = method.annotations.flatMap { annotation ->
56-
MixinAnnotationHandler.resolveTarget(annotation).asSequence()
57-
.filterIsInstance<MethodTargetMember>()
58-
.map { it.classAndMethod }
59-
}.ifEmpty { return }
56+
val (injector, injectorAnnotation) = method.annotations.mapFirstNotNull { annotation ->
57+
(MixinAnnotationHandler.forMixinAnnotation(annotation, holder.project) as? InjectorAnnotationHandler)?.let { it to annotation }
58+
} ?: return
6059

6160
val localType = parameter.type.unwrapLocalRef()
61+
val localInfo = LocalInfo.fromAnnotation(localType, localAnnotation)
6262

63-
if (ModifyVariableArgsOnlyInspection.shouldReport(localAnnotation, localType, targets.asSequence())) {
63+
if (ModifyVariableArgsOnlyInspection.shouldReport(localInfo, injector, injectorAnnotation)) {
6464
holder.registerProblem(
6565
localAnnotation.nameReferenceElement ?: localAnnotation,
6666
"@Local may be argsOnly = true",

0 commit comments

Comments
 (0)