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 @@ -3,7 +3,7 @@
*
* https://mcdev.io/
*
* Copyright (C) 2025 minecraft-dev
* Copyright (C) 2026 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
Expand All @@ -29,4 +29,7 @@ public void method(String string) {

public void uniqueMethod(String string) {
}

public void uniqueDescMethod(int i) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* https://mcdev.io/
*
* Copyright (C) 2025 minecraft-dev
* Copyright (C) 2026 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
Expand All @@ -21,7 +21,6 @@
package com.demonwav.mcdev.platform.mixin.action

import com.demonwav.mcdev.platform.mixin.handlers.injectionPoint.QualifiedMember
import com.demonwav.mcdev.platform.mixin.reference.toMixinString
import com.demonwav.mcdev.util.findReferencedMember
import com.demonwav.mcdev.util.getQualifiedMemberReference
import com.demonwav.mcdev.util.qualifiedMemberReference
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* https://mcdev.io/
*
* Copyright (C) 2025 minecraft-dev
* Copyright (C) 2026 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
Expand All @@ -24,6 +24,7 @@ import com.demonwav.mcdev.platform.mixin.MixinModuleType
import com.demonwav.mcdev.platform.mixin.folding.MixinFoldingSettings
import com.demonwav.mcdev.platform.mixin.reference.target.FieldDefinitionReference
import com.demonwav.mcdev.platform.mixin.reference.target.MethodDefinitionReference
import com.demonwav.mcdev.platform.mixin.util.MemberInfo
import com.demonwav.mcdev.platform.mixin.util.MixinConstants
import com.demonwav.mcdev.util.MemberReference
import com.intellij.lang.ASTNode
Expand All @@ -49,8 +50,8 @@ class MEDefinitionFoldingBuilder : CustomFoldingBuilder() {
val psi = node.psi
if (psi is PsiLiteralExpression) {
val value = psi.value as? String ?: return "..."
val memberReference = MemberReference.parse(value) ?: return "..."
return memberReference.presentableText
val memberInfo = MemberInfo.parse(value) ?: return "..."
return MemberReference(memberInfo.name ?: "*", memberInfo.descriptor, memberInfo.owner).presentableText
}
return "..."
}
Expand Down Expand Up @@ -108,7 +109,7 @@ class MEDefinitionFoldingBuilder : CustomFoldingBuilder() {
if (FieldDefinitionReference.ELEMENT_PATTERN.accepts(expression) ||
MethodDefinitionReference.ELEMENT_PATTERN.accepts(expression)
) {
if (MemberReference.parse(expression.value as String) != null) {
if (MemberInfo.parse(expression.value as String) != null) {
descriptors.add(FoldingDescriptor(expression.node, expression.textRange))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* https://mcdev.io/
*
* Copyright (C) 2025 minecraft-dev
* Copyright (C) 2026 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
Expand All @@ -24,8 +24,8 @@ import com.demonwav.mcdev.platform.mixin.handlers.InjectorAnnotationHandler
import com.demonwav.mcdev.platform.mixin.handlers.MixinAnnotationHandler
import com.demonwav.mcdev.platform.mixin.handlers.injectionPoint.CollectVisitor
import com.demonwav.mcdev.platform.mixin.util.LocalInfo
import com.demonwav.mcdev.platform.mixin.util.MemberInfo
import com.demonwav.mcdev.platform.mixin.util.MixinConstants
import com.demonwav.mcdev.util.MemberReference
import com.demonwav.mcdev.util.computeStringArray
import com.demonwav.mcdev.util.constantStringValue
import com.demonwav.mcdev.util.descriptor
Expand Down Expand Up @@ -172,7 +172,7 @@ object MEExpressionMatchUtil {

val fields = annotation.findDeclaredAttributeValue("field")?.computeStringArray() ?: emptyList()
for (field in fields) {
val fieldRef = MemberReference.parse(field) ?: continue
val fieldRef = MemberInfo.parse(field) ?: continue
pool.addMember(
definitionId,
SimpleMemberDefinition {
Expand All @@ -183,7 +183,7 @@ object MEExpressionMatchUtil {

val methods = annotation.findDeclaredAttributeValue("method")?.computeStringArray() ?: emptyList()
for (method in methods) {
val methodRef = MemberReference.parse(method) ?: continue
val methodRef = MemberInfo.parse(method) ?: continue
pool.addMember(
definitionId,
object : SimpleMemberDefinition {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* https://mcdev.io/
*
* Copyright (C) 2025 minecraft-dev
* Copyright (C) 2026 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
Expand All @@ -21,7 +21,7 @@
package com.demonwav.mcdev.platform.mixin.expression

import com.demonwav.mcdev.platform.mixin.util.LocalInfo
import com.demonwav.mcdev.util.MemberReference
import com.demonwav.mcdev.platform.mixin.util.MemberInfo
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement

Expand All @@ -32,8 +32,8 @@ class MESourceMatchContext(val project: Project) {
val captures: List<PsiElement> get() = capturesInternal

private val types = mutableMapOf<String, MutableList<String>>()
private val fields = mutableMapOf<String, MutableList<MemberReference>>()
private val methods = mutableMapOf<String, MutableList<MemberReference>>()
private val fields = mutableMapOf<String, MutableList<MemberInfo>>()
private val methods = mutableMapOf<String, MutableList<MemberInfo>>()
private val localInfos = mutableMapOf<String, MutableList<LocalInfo>>()

init {
Expand All @@ -57,15 +57,15 @@ class MESourceMatchContext(val project: Project) {
types.getOrPut(key, ::mutableListOf) += desc
}

fun getFields(key: String): List<MemberReference> = fields[key] ?: emptyList()
fun getFields(key: String): List<MemberInfo> = fields[key] ?: emptyList()

fun addField(key: String, field: MemberReference) {
fun addField(key: String, field: MemberInfo) {
fields.getOrPut(key, ::mutableListOf) += field
}

fun getMethods(key: String): List<MemberReference> = methods[key] ?: emptyList()
fun getMethods(key: String): List<MemberInfo> = methods[key] ?: emptyList()

fun addMethod(key: String, method: MemberReference) {
fun addMethod(key: String, method: MemberInfo) {
methods.getOrPut(key, ::mutableListOf) += method
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* https://mcdev.io/
*
* Copyright (C) 2025 minecraft-dev
* Copyright (C) 2026 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
Expand Down Expand Up @@ -51,7 +51,7 @@ class MixinTargetDescriptorFoldingBuilder : CustomFoldingBuilder() {

override fun getLanguagePlaceholderText(node: ASTNode, range: TextRange): String? {
val element = node.psi
return TargetReference.resolveTarget(element)?.let { formatElement(it) }
return TargetReference.resolveTargets(element).singleOrNull()?.let { formatElement(it) }
}

private fun formatElement(element: PsiElement): String? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ abstract class InjectorAnnotationHandler : MixinAnnotationHandler {
(actualTarget to actualTarget.methods)
}

return targetClassMethods.mapNotNull { (selector, pair) ->
return targetClassMethods.flatMap { (selector, pair) ->
val (clazz, methods) = pair
methods.firstNotNullOfOrNull { method ->
methods.mapNotNull { method ->
if (selector.matchMethod(method, clazz)) {
MethodTargetMember(clazz, method)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@ import com.demonwav.mcdev.platform.mixin.util.findSourceClass
import com.demonwav.mcdev.platform.mixin.util.findSourceElement
import com.demonwav.mcdev.platform.mixin.util.isClinit
import com.demonwav.mcdev.platform.mixin.util.memberReference
import com.demonwav.mcdev.util.Quantifier
import com.demonwav.mcdev.util.computeStringArray
import com.demonwav.mcdev.util.constantStringValue
import com.demonwav.mcdev.util.constantValue
import com.demonwav.mcdev.util.countIs
import com.demonwav.mcdev.util.descriptor
import com.demonwav.mcdev.util.equivalentTo
import com.demonwav.mcdev.util.findMethods
Expand Down Expand Up @@ -197,7 +199,17 @@ class AtResolver(
InsnResolutionInfo.Failure()
}
}
return collectVisitor.visit(targetMethod) as? InsnResolutionInfo.Failure
return when (val result = collectVisitor.visit(targetMethod)) {
is InsnResolutionInfo.Failure -> result
is InsnResolutionInfo.Success -> {
val minMatches = collectVisitor.quantifier.min(Quantifier.Context.INSTRUCTION).coerceAtLeast(1)
if (result.results.countIs >= minMatches) {
null
} else {
InsnResolutionInfo.Failure()
}
}
}
}

fun resolveInstructions(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ package com.demonwav.mcdev.platform.mixin.handlers.injectionPoint

import com.demonwav.mcdev.platform.mixin.handlers.MixinAnnotationHandler
import com.demonwav.mcdev.platform.mixin.reference.MixinSelector
import com.demonwav.mcdev.platform.mixin.util.MemberInfo
import com.demonwav.mcdev.platform.mixin.util.MethodTargetMember
import com.demonwav.mcdev.platform.mixin.util.fakeResolve
import com.demonwav.mcdev.platform.mixin.util.findOrConstructSourceMethod
import com.demonwav.mcdev.util.MemberReference
import com.demonwav.mcdev.util.Quantifier
import com.demonwav.mcdev.util.constantStringValue
import com.demonwav.mcdev.util.createLiteralExpression
import com.demonwav.mcdev.util.toTypedArray
Expand Down Expand Up @@ -148,7 +149,7 @@ class ConstantStringMethodInjectionPoint : AbstractMethodInjectionPoint() {
mode: CollectVisitor.Mode,
): CollectVisitor<PsiMethod>? {
if (mode == CollectVisitor.Mode.COMPLETION) {
return MyCollectVisitor(mode, at.project, MemberReference(""), null)
return MyCollectVisitor(mode, at.project, MemberInfo(), null)
}
return target?.let { MyCollectVisitor(mode, at.project, it, AtResolver.getArgs(at)["ldc"]) }
}
Expand Down Expand Up @@ -204,6 +205,9 @@ class ConstantStringMethodInjectionPoint : AbstractMethodInjectionPoint() {
private val selector: MixinSelector,
private val ldc: String?,
) : CollectVisitor<PsiMethod>(mode) {
override val quantifier: Quantifier
get() = selector.quantifier

override fun accept(methodNode: MethodNode) = sequence {
val insns = methodNode.instructions ?: return@sequence
var seenStringConstant: String? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
package com.demonwav.mcdev.platform.mixin.handlers.injectionPoint

import com.demonwav.mcdev.platform.mixin.reference.MixinSelector
import com.demonwav.mcdev.platform.mixin.util.MemberInfo
import com.demonwav.mcdev.platform.mixin.util.fakeResolve
import com.demonwav.mcdev.platform.mixin.util.findOrConstructSourceField
import com.demonwav.mcdev.util.MemberReference
import com.demonwav.mcdev.util.Quantifier
import com.demonwav.mcdev.util.constantValue
import com.intellij.codeInsight.completion.JavaLookupElementBuilder
import com.intellij.codeInsight.lookup.LookupElementBuilder
Expand Down Expand Up @@ -97,7 +98,7 @@ class FieldInjectionPoint : QualifiedInjectionPoint<PsiField>() {
mode: CollectVisitor.Mode,
): CollectVisitor<PsiField>? {
if (mode == CollectVisitor.Mode.COMPLETION) {
return MyCollectVisitor(mode, at.project, MemberReference(""), -1, null, 8)
return MyCollectVisitor(mode, at.project, MemberInfo(), -1, null, 8)
}
val opcode = (at.findDeclaredAttributeValue("opcode")?.constantValue as? Int)
?.takeIf { it in Const.VALID_OPCODES } ?: -1
Expand Down Expand Up @@ -197,6 +198,9 @@ class FieldInjectionPoint : QualifiedInjectionPoint<PsiField>() {
private val arrayAccess: ArrayAccessType?,
private val fuzz: Int,
) : CollectVisitor<PsiField>(mode) {
override val quantifier: Quantifier
get() = selector.quantifier

override fun accept(methodNode: MethodNode) = sequence {
val insns = methodNode.instructions ?: return@sequence
for (insn in insns) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* https://mcdev.io/
*
* Copyright (C) 2025 minecraft-dev
* Copyright (C) 2026 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
Expand All @@ -26,6 +26,7 @@ import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Annotations.SLICE
import com.demonwav.mcdev.platform.mixin.util.SourceCodeLocationInfo
import com.demonwav.mcdev.platform.mixin.util.fakeResolve
import com.demonwav.mcdev.platform.mixin.util.findOrConstructSourceMethod
import com.demonwav.mcdev.util.Quantifier
import com.demonwav.mcdev.util.constantStringValue
import com.demonwav.mcdev.util.constantValue
import com.demonwav.mcdev.util.createLiteralExpression
Expand Down Expand Up @@ -162,6 +163,7 @@ abstract class InjectionPoint<T : PsiElement> {
// results are shown.
if (mode != CollectVisitor.Mode.COMPLETION) {
addOrdinalFilter(at, targetClass, collectVisitor)
addQuantifierFilter(at, targetClass, collectVisitor)
addSpecifierFilter(at, targetClass, collectVisitor, defaultSpecifier)
}
}
Expand Down Expand Up @@ -219,6 +221,13 @@ abstract class InjectionPoint<T : PsiElement> {
}
}

protected open fun addQuantifierFilter(at: PsiAnnotation, targetClass: ClassNode, collectVisitor: CollectVisitor<T>) {
val maxMatches = collectVisitor.quantifier.max(Quantifier.Context.INSTRUCTION)
collectVisitor.addResultFilter("quantifier") { results, _ ->
results.take(maxMatches)
}
}

protected open fun addSpecifierFilter(
at: PsiAnnotation,
targetClass: ClassNode,
Expand Down Expand Up @@ -356,6 +365,8 @@ abstract class NavigationVisitor : JavaRecursiveElementVisitor() {
}

abstract class CollectVisitor<T : PsiElement>(protected val mode: Mode) {
open val quantifier: Quantifier get() = Quantifier.Any

fun visit(methodNode: MethodNode): InsnResolutionInfo<T> {
val numRetained = IntArray(resultFilters.size + 1)
var results = accept(methodNode).onEach { numRetained[0]++ }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
package com.demonwav.mcdev.platform.mixin.handlers.injectionPoint

import com.demonwav.mcdev.platform.mixin.reference.MixinSelector
import com.demonwav.mcdev.util.MemberReference
import com.demonwav.mcdev.platform.mixin.util.MemberInfo
import com.demonwav.mcdev.util.Quantifier
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.CommonClassNames
Expand Down Expand Up @@ -105,7 +106,7 @@ class InvokeAssignInjectionPoint : AbstractMethodInjectionPoint() {
val skip = args["skip"]?.let { parseSkip(it) } ?: Const.DEFAULT_SKIP

if (mode == CollectVisitor.Mode.COMPLETION) {
return MyCollectVisitor(mode, at.project, MemberReference(""), fuzz, skip)
return MyCollectVisitor(mode, at.project, MemberInfo(), fuzz, skip)
}
return target?.let { MyCollectVisitor(mode, at.project, it, fuzz, skip) }
}
Expand Down Expand Up @@ -162,6 +163,9 @@ class InvokeAssignInjectionPoint : AbstractMethodInjectionPoint() {
private val fuzz: Int,
private val skip: Set<Int>,
) : CollectVisitor<PsiMethod>(mode) {
override val quantifier: Quantifier
get() = selector.quantifier

override fun accept(methodNode: MethodNode) = sequence {
val insns = methodNode.instructions ?: return@sequence
for (insn in insns) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* https://mcdev.io/
*
* Copyright (C) 2025 minecraft-dev
* Copyright (C) 2026 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
Expand All @@ -21,7 +21,8 @@
package com.demonwav.mcdev.platform.mixin.handlers.injectionPoint

import com.demonwav.mcdev.platform.mixin.reference.MixinSelector
import com.demonwav.mcdev.util.MemberReference
import com.demonwav.mcdev.platform.mixin.util.MemberInfo
import com.demonwav.mcdev.util.Quantifier
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.CommonClassNames
Expand Down Expand Up @@ -64,7 +65,7 @@ class InvokeInjectionPoint : AbstractMethodInjectionPoint() {
mode: CollectVisitor.Mode,
): CollectVisitor<PsiMethod>? {
if (mode == CollectVisitor.Mode.COMPLETION) {
return MyCollectVisitor(mode, at.project, MemberReference(""))
return MyCollectVisitor(mode, at.project, MemberInfo())
}
return target?.let { MyCollectVisitor(mode, at.project, it) }
}
Expand Down Expand Up @@ -153,6 +154,9 @@ class InvokeInjectionPoint : AbstractMethodInjectionPoint() {
private val project: Project,
private val selector: MixinSelector,
) : CollectVisitor<PsiMethod>(mode) {
override val quantifier: Quantifier
get() = selector.quantifier

override fun accept(methodNode: MethodNode) = sequence {
val insns = methodNode.instructions ?: return@sequence
for (insn in insns) {
Expand Down
Loading
Loading