From 3ecde2dd5961afd995ca0c2f2dec3339037d5e22 Mon Sep 17 00:00:00 2001 From: LlamaLad7 Date: Tue, 2 Jul 2024 16:34:19 +0100 Subject: [PATCH] MixinExtras Expressions: Migrate to Expressions library. --- build.gradle.kts | 10 +++-- .../expression/MEExpressionCompletionUtil.kt | 10 ++--- .../mixin/expression/MEExpressionMatchUtil.kt | 7 ++- .../mixin/expression/MEExpressionService.kt | 44 +++++++++++++++++++ .../mixin/expression/MEFlowContext.kt | 26 +++++++++++ .../MixinExtrasInjectorAnnotationHandler.kt | 12 ++--- .../ModifyExpressionValueHandler.kt | 12 ++--- .../mixinextras/WrapOperationHandler.kt | 22 ++++++---- .../kotlin/platform/mixin/util/AsmUtil.kt | 4 +- .../kotlin/platform/mixin/BaseMixinTest.kt | 2 +- 10 files changed, 117 insertions(+), 32 deletions(-) create mode 100644 src/main/kotlin/platform/mixin/expression/MEExpressionService.kt create mode 100644 src/main/kotlin/platform/mixin/expression/MEFlowContext.kt diff --git a/build.gradle.kts b/build.gradle.kts index d4ac4965b..99e7431fb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -89,7 +89,7 @@ repositories { mavenCentral() // TODO: temporary waiting for MixinExtras expression library - maven("https://repo.spongepowered.org/") + maven("https://repo.spongepowered.org/maven/") maven("https://jitpack.io/") { content { includeGroupByRegex("com\\.github\\..+") @@ -101,9 +101,11 @@ dependencies { // Add tools.jar for the JDI API implementation(files(Jvm.current().toolsJar)) - // TODO: temporary waiting for MixinExtras expression library - testLibs(implementation("com.github.LlamaLad7.MixinExtras:mixinextras-common:86c9835")!!) - implementation("org.spongepowered:mixin:0.8.4") + // TODO: temporary waiting for a release + fun mixinExtras(variant: String) = "com.github.LlamaLad7.MixinExtras:mixinextras-$variant:4d2e01e" + + implementation(mixinExtras("expressions")) + testLibs(mixinExtras("common")) implementation("org.ow2.asm:asm-util:9.3") // Kotlin diff --git a/src/main/kotlin/platform/mixin/expression/MEExpressionCompletionUtil.kt b/src/main/kotlin/platform/mixin/expression/MEExpressionCompletionUtil.kt index 115f24b70..dcda90ba2 100644 --- a/src/main/kotlin/platform/mixin/expression/MEExpressionCompletionUtil.kt +++ b/src/main/kotlin/platform/mixin/expression/MEExpressionCompletionUtil.kt @@ -118,7 +118,7 @@ import com.llamalad7.mixinextras.expression.impl.flow.expansion.InsnExpander import com.llamalad7.mixinextras.expression.impl.flow.postprocessing.InstantiationInfo import com.llamalad7.mixinextras.expression.impl.point.ExpressionContext import com.llamalad7.mixinextras.expression.impl.pool.IdentifierPool -import com.llamalad7.mixinextras.utils.Decorations +import com.llamalad7.mixinextras.expression.impl.utils.FlowDecorations import org.apache.commons.lang3.mutable.MutableInt import org.objectweb.asm.Handle import org.objectweb.asm.Opcodes @@ -770,7 +770,7 @@ object MEExpressionCompletionUtil { lookup.withTail( BracketsTailType( 1, - flows[insn]?.hasDecoration(Decorations.ARRAY_CREATION_INFO) == true, + flows[insn]?.hasDecoration(FlowDecorations.ARRAY_CREATION_INFO) == true, ) ) .createEliminable("new [${insn.insn.desc}") @@ -778,7 +778,7 @@ object MEExpressionCompletionUtil { } Opcodes.NEW -> { val initCall = flows[insn] - ?.getDecoration(Decorations.INSTANTIATION_INFO) + ?.getDecoration(FlowDecorations.INSTANTIATION_INFO) ?.initCall ?.virtualInsnOrNull ?.insn as MethodInsnNode? @@ -811,7 +811,7 @@ object MEExpressionCompletionUtil { .withTail( BracketsTailType( 1, - flows[insn]?.hasDecoration(Decorations.ARRAY_CREATION_INFO) == true, + flows[insn]?.hasDecoration(FlowDecorations.ARRAY_CREATION_INFO) == true, ) ) .createEliminable("new $type[]") @@ -827,7 +827,7 @@ object MEExpressionCompletionUtil { .withTail( BracketsTailType( type.dimensions, - flows[insn]?.hasDecoration(Decorations.ARRAY_CREATION_INFO) == true + flows[insn]?.hasDecoration(FlowDecorations.ARRAY_CREATION_INFO) == true ) ) .createEliminable("new ${insn.insn.desc}") diff --git a/src/main/kotlin/platform/mixin/expression/MEExpressionMatchUtil.kt b/src/main/kotlin/platform/mixin/expression/MEExpressionMatchUtil.kt index f1663f4ea..1461facc4 100644 --- a/src/main/kotlin/platform/mixin/expression/MEExpressionMatchUtil.kt +++ b/src/main/kotlin/platform/mixin/expression/MEExpressionMatchUtil.kt @@ -40,6 +40,7 @@ import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.Project import com.intellij.psi.PsiModifierList import com.llamalad7.mixinextras.expression.impl.ExpressionParserFacade +import com.llamalad7.mixinextras.expression.impl.ExpressionService import com.llamalad7.mixinextras.expression.impl.ast.expressions.Expression import com.llamalad7.mixinextras.expression.impl.flow.ComplexDataException import com.llamalad7.mixinextras.expression.impl.flow.FlowInterpreter @@ -73,13 +74,17 @@ value class VirtualInsn(val insn: AbstractInsnNode) object MEExpressionMatchUtil { private val LOGGER = logger() + init { + ExpressionService.offerInstance(MEExpressionService) + } + fun getFlowMap(project: Project, classIn: ClassNode, methodIn: MethodNode): FlowMap? { if (methodIn.instructions == null) { return null } return methodIn.cached(classIn, project) { classNode, methodNode -> - val interpreter = object : FlowInterpreter(classNode, methodNode) { + val interpreter = object : FlowInterpreter(classNode, methodNode, MEFlowContext(project)) { override fun newValue(type: Type?): FlowValue? { ProgressManager.checkCanceled() return super.newValue(type) diff --git a/src/main/kotlin/platform/mixin/expression/MEExpressionService.kt b/src/main/kotlin/platform/mixin/expression/MEExpressionService.kt new file mode 100644 index 000000000..5a3408652 --- /dev/null +++ b/src/main/kotlin/platform/mixin/expression/MEExpressionService.kt @@ -0,0 +1,44 @@ +/* + * 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 . + */ + +package com.demonwav.mcdev.platform.mixin.expression + +import com.demonwav.mcdev.platform.mixin.util.toPsiType +import com.demonwav.mcdev.util.descriptor +import com.intellij.psi.GenericsUtil +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiManager +import com.llamalad7.mixinextras.expression.impl.ExpressionService +import com.llamalad7.mixinextras.expression.impl.flow.FlowContext +import org.objectweb.asm.Type + +object MEExpressionService : ExpressionService() { + override fun getCommonSuperClass(ctx: FlowContext, type1: Type, type2: Type): Type { + ctx as MEFlowContext + val elementFactory = JavaPsiFacade.getElementFactory(ctx.project) + return Type.getType( + GenericsUtil.getLeastUpperBound( + type1.toPsiType(elementFactory), + type2.toPsiType(elementFactory), + PsiManager.getInstance(ctx.project) + )?.descriptor ?: error("Failed to merge types $type1 and $type2!") + ) + } +} diff --git a/src/main/kotlin/platform/mixin/expression/MEFlowContext.kt b/src/main/kotlin/platform/mixin/expression/MEFlowContext.kt new file mode 100644 index 000000000..e7d22f578 --- /dev/null +++ b/src/main/kotlin/platform/mixin/expression/MEFlowContext.kt @@ -0,0 +1,26 @@ +/* + * 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 . + */ + +package com.demonwav.mcdev.platform.mixin.expression + +import com.intellij.openapi.project.Project +import com.llamalad7.mixinextras.expression.impl.flow.FlowContext + +class MEFlowContext(val project: Project) : FlowContext diff --git a/src/main/kotlin/platform/mixin/handlers/mixinextras/MixinExtrasInjectorAnnotationHandler.kt b/src/main/kotlin/platform/mixin/handlers/mixinextras/MixinExtrasInjectorAnnotationHandler.kt index 5604134f6..2e76bcb9b 100644 --- a/src/main/kotlin/platform/mixin/handlers/mixinextras/MixinExtrasInjectorAnnotationHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/mixinextras/MixinExtrasInjectorAnnotationHandler.kt @@ -38,7 +38,7 @@ import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiElement import com.intellij.psi.PsiType import com.intellij.psi.PsiTypes -import com.llamalad7.mixinextras.utils.Decorations +import com.llamalad7.mixinextras.expression.impl.utils.ExpressionDecorations import org.objectweb.asm.Opcodes import org.objectweb.asm.Type import org.objectweb.asm.tree.AbstractInsnNode @@ -78,14 +78,16 @@ abstract class MixinExtrasInjectorAnnotationHandler : InjectorAnnotationHandler( }, SIMPLE_OPERATION { override fun matches(target: TargetInsn) = - target.hasDecoration(Decorations.SIMPLE_OPERATION_ARGS) && - target.hasDecoration(Decorations.SIMPLE_OPERATION_RETURN_TYPE) + target.hasDecoration(ExpressionDecorations.SIMPLE_OPERATION_ARGS) && + target.hasDecoration(ExpressionDecorations.SIMPLE_OPERATION_RETURN_TYPE) }, SIMPLE_EXPRESSION { - override fun matches(target: TargetInsn) = target.hasDecoration(Decorations.SIMPLE_EXPRESSION_TYPE) + override fun matches(target: TargetInsn) = + target.hasDecoration(ExpressionDecorations.SIMPLE_EXPRESSION_TYPE) }, STRING_CONCAT_EXPRESSION { - override fun matches(target: TargetInsn) = target.hasDecoration(Decorations.IS_STRING_CONCAT_EXPRESSION) + override fun matches(target: TargetInsn) = + target.hasDecoration(ExpressionDecorations.IS_STRING_CONCAT_EXPRESSION) }; abstract fun matches(target: TargetInsn): Boolean diff --git a/src/main/kotlin/platform/mixin/handlers/mixinextras/ModifyExpressionValueHandler.kt b/src/main/kotlin/platform/mixin/handlers/mixinextras/ModifyExpressionValueHandler.kt index 4b1bbc983..f16bf4924 100644 --- a/src/main/kotlin/platform/mixin/handlers/mixinextras/ModifyExpressionValueHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/mixinextras/ModifyExpressionValueHandler.kt @@ -28,8 +28,8 @@ import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiType import com.llamalad7.mixinextras.expression.impl.point.ExpressionContext -import com.llamalad7.mixinextras.utils.Decorations -import com.llamalad7.mixinextras.utils.TypeUtils +import com.llamalad7.mixinextras.expression.impl.utils.ExpressionASMUtils +import com.llamalad7.mixinextras.expression.impl.utils.ExpressionDecorations import org.objectweb.asm.Type import org.objectweb.asm.tree.AbstractInsnNode import org.objectweb.asm.tree.ClassNode @@ -57,8 +57,8 @@ class ModifyExpressionValueHandler : MixinExtrasInjectorAnnotationHandler() { } override fun intLikeTypePositions(target: TargetInsn): List { - val expressionType = target.getDecoration(Decorations.SIMPLE_EXPRESSION_TYPE) - if (expressionType == TypeUtils.INTLIKE_TYPE) { + val expressionType = target.getDecoration(ExpressionDecorations.SIMPLE_EXPRESSION_TYPE) + if (expressionType == ExpressionASMUtils.INTLIKE_TYPE) { return listOf(MethodSignature.TypePosition.Return, MethodSignature.TypePosition.Param(0)) } return emptyList() @@ -68,12 +68,12 @@ class ModifyExpressionValueHandler : MixinExtrasInjectorAnnotationHandler() { target: TargetInsn, annotation: PsiAnnotation ): PsiType? { - if (target.hasDecoration(Decorations.IS_STRING_CONCAT_EXPRESSION)) { + if (target.hasDecoration(ExpressionDecorations.IS_STRING_CONCAT_EXPRESSION)) { return PsiType.getJavaLangString(annotation.manager, annotation.resolveScope) } val psiReturnType = getPsiReturnType(target.insn, annotation) val rawReturnType = getInsnReturnType(target.insn) - val exprType = target.getDecoration(Decorations.SIMPLE_EXPRESSION_TYPE) + val exprType = target.getDecoration(ExpressionDecorations.SIMPLE_EXPRESSION_TYPE) if (exprType != null && rawReturnType != exprType) { // The expression knows more than the standard logic does. return exprType.toPsiType(JavaPsiFacade.getElementFactory(annotation.project)) diff --git a/src/main/kotlin/platform/mixin/handlers/mixinextras/WrapOperationHandler.kt b/src/main/kotlin/platform/mixin/handlers/mixinextras/WrapOperationHandler.kt index 2acb6be78..ef1726cc8 100644 --- a/src/main/kotlin/platform/mixin/handlers/mixinextras/WrapOperationHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/mixinextras/WrapOperationHandler.kt @@ -29,8 +29,8 @@ import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiType import com.llamalad7.mixinextras.expression.impl.point.ExpressionContext -import com.llamalad7.mixinextras.utils.Decorations -import com.llamalad7.mixinextras.utils.TypeUtils +import com.llamalad7.mixinextras.expression.impl.utils.ExpressionASMUtils +import com.llamalad7.mixinextras.expression.impl.utils.ExpressionDecorations import org.objectweb.asm.Type import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.MethodNode @@ -60,11 +60,14 @@ class WrapOperationHandler : MixinExtrasInjectorAnnotationHandler() { } override fun intLikeTypePositions(target: TargetInsn) = buildList { - if (target.getDecoration(Decorations.SIMPLE_OPERATION_RETURN_TYPE) == TypeUtils.INTLIKE_TYPE) { + if ( + target.getDecoration(ExpressionDecorations.SIMPLE_OPERATION_RETURN_TYPE) + == ExpressionASMUtils.INTLIKE_TYPE + ) { add(MethodSignature.TypePosition.Return) } - target.getDecoration>(Decorations.SIMPLE_OPERATION_ARGS)?.forEachIndexed { i, it -> - if (it == TypeUtils.INTLIKE_TYPE) { + target.getDecoration>(ExpressionDecorations.SIMPLE_OPERATION_ARGS)?.forEachIndexed { i, it -> + if (it == ExpressionASMUtils.INTLIKE_TYPE) { add(MethodSignature.TypePosition.Param(i)) } } @@ -76,8 +79,11 @@ class WrapOperationHandler : MixinExtrasInjectorAnnotationHandler() { annotation: PsiAnnotation ): List? { getPsiParameters(target.insn, targetClass, annotation)?.let { return it } - val args = target.getDecoration>(Decorations.SIMPLE_OPERATION_ARGS) ?: return null - return args.toList().toParameters(annotation, target.getDecoration(Decorations.SIMPLE_OPERATION_PARAM_NAMES)) + val args = target.getDecoration>(ExpressionDecorations.SIMPLE_OPERATION_ARGS) ?: return null + return args.toList().toParameters( + annotation, + target.getDecoration(ExpressionDecorations.SIMPLE_OPERATION_PARAM_NAMES) + ) } private fun getReturnType( @@ -85,7 +91,7 @@ class WrapOperationHandler : MixinExtrasInjectorAnnotationHandler() { annotation: PsiAnnotation ): PsiType? { getPsiReturnType(target.insn, annotation)?.let { return it } - val type = target.getDecoration(Decorations.SIMPLE_OPERATION_RETURN_TYPE) ?: return null + val type = target.getDecoration(ExpressionDecorations.SIMPLE_OPERATION_RETURN_TYPE) ?: return null return type.toPsiType(JavaPsiFacade.getElementFactory(annotation.project)) } diff --git a/src/main/kotlin/platform/mixin/util/AsmUtil.kt b/src/main/kotlin/platform/mixin/util/AsmUtil.kt index 161ad6a56..981be7320 100644 --- a/src/main/kotlin/platform/mixin/util/AsmUtil.kt +++ b/src/main/kotlin/platform/mixin/util/AsmUtil.kt @@ -76,7 +76,7 @@ import com.intellij.psi.util.CachedValue import com.intellij.psi.util.PsiUtil import com.intellij.refactoring.util.LambdaRefactoringUtil import com.intellij.util.CommonJavaRefactoringUtil -import com.llamalad7.mixinextras.utils.TypeUtils +import com.llamalad7.mixinextras.expression.impl.utils.ExpressionASMUtils import java.io.PrintWriter import java.io.StringWriter import java.lang.reflect.InvocationTargetException @@ -143,7 +143,7 @@ private fun hasModifier(access: Int, @PsiModifier.ModifierConstant modifier: Str } fun Type.toPsiType(elementFactory: PsiElementFactory, context: PsiElement? = null): PsiType { - if (this == TypeUtils.INTLIKE_TYPE) { + if (this == ExpressionASMUtils.INTLIKE_TYPE) { return PsiTypes.intType() } val javaClassName = className.replace("(\\$)(\\D)".toRegex()) { "." + it.groupValues[2] } diff --git a/src/test/kotlin/platform/mixin/BaseMixinTest.kt b/src/test/kotlin/platform/mixin/BaseMixinTest.kt index a2e406849..caac9bc5d 100644 --- a/src/test/kotlin/platform/mixin/BaseMixinTest.kt +++ b/src/test/kotlin/platform/mixin/BaseMixinTest.kt @@ -41,7 +41,7 @@ abstract class BaseMixinTest : BaseMinecraftTest(PlatformType.MIXIN) { fun initMixin() { runWriteTask { mixinLibrary = createLibrary(project, "mixin") - mixinExtrasLibrary = createLibrary(project, "mixinextras-common") // TODO: this will probably change + mixinExtrasLibrary = createLibrary(project, "mixinextras-common") testDataLibrary = createLibrary(project, "mixin-test-data") }