Skip to content

Commit

Permalink
Implement JUMP injection point (without source navigation)
Browse files Browse the repository at this point in the history
  • Loading branch information
Earthcomputer committed Jul 21, 2024
1 parent 2293169 commit 3f2c121
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Minecraft Development for IntelliJ
*
* https://mcdev.io/
*
* Copyright (C) 2024 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
* by the Free Software Foundation, version 3.0 only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.demonwav.mcdev.platform.mixin.handlers.injectionPoint

import com.demonwav.mcdev.platform.mixin.reference.MixinSelector
import com.demonwav.mcdev.platform.mixin.util.findOrConstructSourceMethod
import com.demonwav.mcdev.util.constantValue
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.JumpInsnNode
import org.objectweb.asm.tree.MethodNode

class JumpInjectionPoint : InjectionPoint<PsiElement>() {
companion object {
private val VALID_OPCODES = setOf(
Opcodes.IFEQ,
Opcodes.IFNE,
Opcodes.IFLT,
Opcodes.IFGE,
Opcodes.IFGT,
Opcodes.IFLE,
Opcodes.IF_ICMPEQ,
Opcodes.IF_ICMPNE,
Opcodes.IF_ICMPLT,
Opcodes.IF_ICMPGE,
Opcodes.IF_ICMPGT,
Opcodes.IF_ICMPLE,
Opcodes.IF_ACMPEQ,
Opcodes.IF_ACMPNE,
Opcodes.GOTO,
Opcodes.JSR,
Opcodes.IFNULL,
Opcodes.IFNONNULL,
)
}

override fun createNavigationVisitor(
at: PsiAnnotation,
target: MixinSelector?,
targetClass: PsiClass
): NavigationVisitor? {
// TODO: jump target source navigation? This would be extremely hard
return null
}

override fun doCreateCollectVisitor(
at: PsiAnnotation,
target: MixinSelector?,
targetClass: ClassNode,
mode: CollectVisitor.Mode
): CollectVisitor<PsiElement> {
val opcode = (at.findDeclaredAttributeValue("opcode")?.constantValue as? Int)
?.takeIf { it in VALID_OPCODES } ?: -1
return MyCollectVisitor(at.project, targetClass, mode, opcode)
}

override fun createLookup(
targetClass: ClassNode,
result: CollectVisitor.Result<PsiElement>
): LookupElementBuilder? {
return null
}

private class MyCollectVisitor(
private val project: Project,
private val clazz: ClassNode,
mode: Mode,
private val opcode: Int
) : CollectVisitor<PsiElement>(mode) {
override fun accept(methodNode: MethodNode) {
val insns = methodNode.instructions ?: return
insns.iterator().forEachRemaining { insn ->
if (insn is JumpInsnNode && (opcode == -1 || insn.opcode == opcode)) {
addResult(insn, methodNode.findOrConstructSourceMethod(clazz, project))
}
}
}
}
}
1 change: 1 addition & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@
<injectionPoint atCode="LOAD" implementation="com.demonwav.mcdev.platform.mixin.handlers.injectionPoint.LoadInjectionPoint" />
<injectionPoint atCode="STORE" implementation="com.demonwav.mcdev.platform.mixin.handlers.injectionPoint.StoreInjectionPoint" />
<injectionPoint atCode="CONSTANT" implementation="com.demonwav.mcdev.platform.mixin.handlers.injectionPoint.ConstantInjectionPoint" />
<injectionPoint atCode="JUMP" implementation="com.demonwav.mcdev.platform.mixin.handlers.injectionPoint.JumpInjectionPoint" />
<injectionPoint atCode="MIXINEXTRAS:EXPRESSION" implementation="com.demonwav.mcdev.platform.mixin.handlers.mixinextras.ExpressionInjectionPoint" />

<injectionPointAnnotation annotation="org.spongepowered.asm.mixin.injection.Constant" atCode="CONSTANT" />
Expand Down

0 comments on commit 3f2c121

Please sign in to comment.