Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import com.demonwav.mcdev.platform.mixin.util.getGenericParameterTypes
import com.demonwav.mcdev.platform.mixin.util.hasAccess
import com.demonwav.mcdev.platform.mixin.util.mixinTargets
import com.demonwav.mcdev.util.Parameter
import com.demonwav.mcdev.util.Quantifier
import com.demonwav.mcdev.util.cached
import com.demonwav.mcdev.util.computeStringArray
import com.demonwav.mcdev.util.findAnnotations
Expand All @@ -46,8 +47,10 @@ import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiEllipsisType
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiType
import com.intellij.psi.util.PsiModificationTracker
import com.intellij.psi.util.findParentOfType
import com.llamalad7.mixinextras.expression.impl.point.ExpressionContext
import java.util.concurrent.ConcurrentHashMap
import org.objectweb.asm.Opcodes
Expand All @@ -67,16 +70,22 @@ abstract class InjectorAnnotationHandler : MixinAnnotationHandler {
val actualTarget = selector.getCustomOwner(targetClass)
(actualTarget to actualTarget.methods)
}
val isStatic = annotation.findParentOfType<PsiMethod>()?.hasModifierProperty(PsiModifier.STATIC) ?: true

return targetClassMethods.flatMap { (selector, pair) ->
val maxCount = selector.quantifier.max(Quantifier.Context.MEMBER)
val (clazz, methods) = pair
methods.mapNotNull { method ->
if (selector.matchMethod(method, clazz)) {
MethodTargetMember(clazz, method)
} else {
null
methods.asSequence()
.mapNotNull { method ->
if (selector.matchMethod(method, clazz) &&
(maxCount <= 1 || isStatic || !method.hasAccess(Opcodes.ACC_STATIC))
) {
MethodTargetMember(clazz, method)
} else {
null
}
}
}
.take(maxCount)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class NewInsnInjectionPoint : InjectionPoint<PsiMember>() {
val anonymousName = anonymousClass?.fullQualifiedName?.replace('.', '/')
if (anonymousName != null) {
val methods = findClassNodeByPsiClass(anonymousClass)
?.findMethods(selector.withQuantifier(Quantifier.Default))
?.findMethods(selector.withQuantifier(Quantifier.Any), allowStatic = true)
.orEmpty()

if (methods.any { selector.matchMethod(anonymousName, it.name, it.desc) }) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiArrayInitializerMemberValue
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiSubstitutor
import com.intellij.psi.ResolveResult
import com.intellij.psi.util.parentOfType
Expand Down Expand Up @@ -82,13 +84,15 @@ abstract class AbstractMethodReference : PolyReferenceResolver(), MixinReference
return false
}

val isStatic = context.parentOfType<PsiMethod>()?.hasModifierProperty(PsiModifier.STATIC) ?: true
val stringValue = context.constantStringValue ?: return false
val targetMethodInfo = parseSelector(stringValue, context) ?: return false
val minMatches = targetMethodInfo.quantifier.min(Quantifier.Context.MEMBER).coerceAtLeast(1)
val targets = getTargets(context) ?: return false

return targets.any {
targetMethodInfo.getCustomOwner(it).findMethods(targetMethodInfo).countIsLessThan(minMatches)
targetMethodInfo.getCustomOwner(it).findMethods(targetMethodInfo, allowStatic = isStatic)
.countIsLessThan(minMatches)
}
}

Expand All @@ -104,10 +108,13 @@ abstract class AbstractMethodReference : PolyReferenceResolver(), MixinReference
}

private fun isAmbiguous(targets: Collection<ClassNode>, targetReference: MemberInfo): Boolean {
return targets.any { it.findMethods(targetReference.withQuantifier(Quantifier.Any)).countIsAtLeast(2) }
return targets.any {
it.findMethods(targetReference.withQuantifier(Quantifier.Any), allowStatic = true).countIsAtLeast(2)
}
}

fun resolve(context: PsiElement): Sequence<ClassAndMethodNode>? {
val isStatic = context.parentOfType<PsiMethod>()?.hasModifierProperty(PsiModifier.STATIC) ?: true
val targets = getTargets(context) ?: return null
val targetedMethods = when (context) {
is PsiArrayInitializerMemberValue -> context.initializers.mapNotNull { it.constantStringValue }
Expand All @@ -116,18 +123,19 @@ abstract class AbstractMethodReference : PolyReferenceResolver(), MixinReference

return targetedMethods.asSequence().flatMap { method ->
val targetReference = parseSelector(method, context) ?: return@flatMap emptySequence()
return@flatMap resolve(targets, targetReference)
return@flatMap resolve(targets, targetReference, allowStatic = isStatic)
}
}

private fun resolve(
targets: Collection<ClassNode>,
selector: MixinSelector,
allowStatic: Boolean,
): Sequence<ClassAndMethodNode> {
return targets.asSequence()
.flatMap { target ->
val actualTarget = selector.getCustomOwner(target)
actualTarget.findMethods(selector).map { ClassAndMethodNode(actualTarget, it) }
actualTarget.findMethods(selector, allowStatic).map { ClassAndMethodNode(actualTarget, it) }
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/main/kotlin/platform/mixin/util/AsmUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -472,9 +472,11 @@ fun ClassNode.findField(ref: MemberMatcher): FieldNode? {
return findFields(ref).firstOrNull()
}

fun ClassNode.findMethods(ref: MixinSelector): Sequence<MethodNode> {
fun ClassNode.findMethods(ref: MixinSelector, allowStatic: Boolean): Sequence<MethodNode> {
val maxMatches = ref.quantifier.max(Quantifier.Context.MEMBER)
return methods?.asSequence()?.filter { ref.matchMethod(it, this) }?.take(maxMatches).orEmpty()
return methods?.asSequence()?.filter {
ref.matchMethod(it, this) && (maxMatches <= 1 || allowStatic || !it.hasAccess(Opcodes.ACC_STATIC))
}?.take(maxMatches).orEmpty()
}

fun ClassNode.findMethod(ref: MemberReference): MethodNode? {
Expand Down
Loading