diff --git a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/AtAnnotationVisitor.java b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/AtAnnotationVisitor.java index 1c3b8260..6969d593 100644 --- a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/AtAnnotationVisitor.java +++ b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/AtAnnotationVisitor.java @@ -18,11 +18,13 @@ package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; +import java.util.List; import java.util.Objects; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.tree.AnnotationNode; +import net.fabricmc.tinyremapper.api.TrMember; import net.fabricmc.tinyremapper.extension.mixin.common.IMappable; import net.fabricmc.tinyremapper.extension.mixin.common.data.Annotation; import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; @@ -37,14 +39,16 @@ class AtAnnotationVisitor extends AnnotationNode { private final CommonData data; private final AnnotationVisitor delegate; + private final List targets; private String value; - AtAnnotationVisitor(CommonData data, AnnotationVisitor delegate) { + AtAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { super(Constant.ASM_VERSION, Annotation.AT); this.data = Objects.requireNonNull(data); this.delegate = Objects.requireNonNull(delegate); + this.targets = Objects.requireNonNull(targets); } @Override @@ -58,7 +62,7 @@ public void visit(String name, Object value) { @Override public void visitEnd() { - accept(new AtSecondPassAnnotationVisitor(data, delegate, value)); + accept(new AtSecondPassAnnotationVisitor(data, delegate, value, targets)); super.visitEnd(); } @@ -66,12 +70,14 @@ public void visitEnd() { private static class AtSecondPassAnnotationVisitor extends AnnotationVisitor { private final CommonData data; private final String value; + private final List targets; - AtSecondPassAnnotationVisitor(CommonData data, AnnotationVisitor delegate, String value) { + AtSecondPassAnnotationVisitor(CommonData data, AnnotationVisitor delegate, String value, List targets) { super(Constant.ASM_VERSION, delegate); this.data = Objects.requireNonNull(data); this.value = Objects.requireNonNull(value); + this.targets = Objects.requireNonNull(targets); } @Override @@ -91,6 +97,21 @@ public void visit(String name, Object value) { super.visit(name, value); } + @Override + public AnnotationVisitor visitAnnotation(String name, String descriptor) { + AnnotationVisitor av = super.visitAnnotation(name, descriptor); + + if (name.equals(AnnotationElement.DESC)) { + if (!descriptor.equals(Annotation.DESC)) { + throw new RuntimeException("Unexpected annotation " + descriptor); + } + + av = new DescAnnotationVisitor(targets, data, av, this.value.equals("FIELD") ? TrMember.MemberType.FIELD : TrMember.MemberType.METHOD); + } + + return av; + } + @Override public AnnotationVisitor visitArray(String name) { AnnotationVisitor av = super.visitArray(name); diff --git a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/CommonInjectionAnnotationVisitor.java b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/CommonInjectionAnnotationVisitor.java index 5ac80e2a..06cd1a05 100644 --- a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/CommonInjectionAnnotationVisitor.java +++ b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/CommonInjectionAnnotationVisitor.java @@ -65,13 +65,13 @@ public AnnotationVisitor visitAnnotation(String name, String descriptor) { throw new RuntimeException("Unexpected annotation " + descriptor); } - av = new AtAnnotationVisitor(data, av); + av = new AtAnnotationVisitor(data, av, targets); } else if (name.equals(AnnotationElement.SLICE)) { // @ModifyArg, @ModifyArgs, @Redirect, @ModifyVariable if (!descriptor.equals(Annotation.SLICE)) { throw new RuntimeException("Unexpected annotation " + descriptor); } - av = new SliceAnnotationVisitor(data, av); + av = new SliceAnnotationVisitor(data, av, targets); } return av; @@ -113,7 +113,7 @@ public AnnotationVisitor visitAnnotation(String name, String descriptor) { } AnnotationVisitor av1 = super.visitAnnotation(name, descriptor); - return new AtAnnotationVisitor(data, av1); + return new AtAnnotationVisitor(data, av1, targets); } }; } else if (name.equals(AnnotationElement.SLICE)) { // @Inject @ModifyConstant @@ -125,7 +125,7 @@ public AnnotationVisitor visitAnnotation(String name, String descriptor) { } AnnotationVisitor av1 = super.visitAnnotation(name, descriptor); - return new SliceAnnotationVisitor(data, av1); + return new SliceAnnotationVisitor(data, av1, targets); } }; } diff --git a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/SliceAnnotationVisitor.java b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/SliceAnnotationVisitor.java index d3d7362a..8df8bbe4 100644 --- a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/SliceAnnotationVisitor.java +++ b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/injection/SliceAnnotationVisitor.java @@ -18,6 +18,7 @@ package net.fabricmc.tinyremapper.extension.mixin.soft.annotation.injection; +import java.util.List; import java.util.Objects; import org.objectweb.asm.AnnotationVisitor; @@ -29,10 +30,12 @@ public class SliceAnnotationVisitor extends AnnotationVisitor { private final CommonData data; + private final List targets; - public SliceAnnotationVisitor(CommonData data, AnnotationVisitor delegate) { + public SliceAnnotationVisitor(CommonData data, AnnotationVisitor delegate, List targets) { super(Constant.ASM_VERSION, delegate); this.data = Objects.requireNonNull(data); + this.targets = Objects.requireNonNull(targets); } @Override @@ -44,7 +47,7 @@ public AnnotationVisitor visitAnnotation(String name, String descriptor) { throw new RuntimeException("Unexpected annotation " + descriptor); } - av = new AtAnnotationVisitor(data, av); + av = new AtAnnotationVisitor(data, av, targets); } return av; diff --git a/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/MixinIntegrationTest.java b/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/MixinIntegrationTest.java index 62a27206..12ab1787 100644 --- a/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/MixinIntegrationTest.java +++ b/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/MixinIntegrationTest.java @@ -42,10 +42,12 @@ import net.fabricmc.tinyremapper.TinyRemapper; import net.fabricmc.tinyremapper.extension.mixin.MixinExtension; import net.fabricmc.tinyremapper.extension.mixin.integration.mixins.AmbiguousRemappedNameMixin; +import net.fabricmc.tinyremapper.extension.mixin.integration.mixins.DescAtMixin; import net.fabricmc.tinyremapper.extension.mixin.integration.mixins.LvtRemapTargetMixin; import net.fabricmc.tinyremapper.extension.mixin.integration.mixins.NonObfuscatedOverrideMixin; import net.fabricmc.tinyremapper.extension.mixin.integration.mixins.WildcardTargetMixin; import net.fabricmc.tinyremapper.extension.mixin.integration.targets.AmbiguousRemappedNameTarget; +import net.fabricmc.tinyremapper.extension.mixin.integration.targets.DescAtTarget; import net.fabricmc.tinyremapper.extension.mixin.integration.targets.LvtRemapTarget; import net.fabricmc.tinyremapper.extension.mixin.integration.targets.NonObfuscatedOverrideTarget; import net.fabricmc.tinyremapper.extension.mixin.integration.targets.WildcardTarget; @@ -109,6 +111,18 @@ public void remapLvtName() throws IOException { assertTrue(remapped.contains("@Lorg/spongepowered/asm/mixin/injection/ModifyVariable;(method={\"targetRemapped\"}, at=@Lorg/spongepowered/asm/mixin/injection/At;(value=\"HEAD\"), name={\"remappedStr3\"})")); } + @Test + public void remapDescAt() throws IOException { + String remapped = remap(DescAtTarget.class, DescAtMixin.class, out -> { + String fqn = "net/fabricmc/tinyremapper/extension/mixin/integration/targets/DescAtTarget"; + out.acceptClass(fqn, "com/example/Remapped"); + out.acceptMethod(new IMappingProvider.Member(fqn, "mainTarget", "(I)V"), "mainTargetRemapped"); + out.acceptMethod(new IMappingProvider.Member(fqn, "atTarget", "(Ljava/lang/String;)I"), "at"); + }); + + assertTrue(remapped.contains("@Lorg/spongepowered/asm/mixin/injection/Desc;(args={java.lang.String.class}, ret=int.class, value=\"at\"")); + } + private String remap(Class target, Class mixin, IMappingProvider mappings) throws IOException { Path classpath = createJar(target); Path input = createJar(mixin); diff --git a/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/mixins/DescAtMixin.java b/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/mixins/DescAtMixin.java new file mode 100644 index 00000000..172c2259 --- /dev/null +++ b/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/mixins/DescAtMixin.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, 2018, Player, asie + * Copyright (c) 2026, FabricMC + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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 Lesser 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 net.fabricmc.tinyremapper.extension.mixin.integration.mixins; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Desc; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.fabricmc.tinyremapper.extension.mixin.integration.targets.DescAtTarget; + +@Mixin(DescAtTarget.class) +public class DescAtMixin { + @Inject(method = "mainTarget", at = @At(value = "INVOKE", desc = @Desc(value = "atTarget", args = {String.class}, ret = int.class))) + private void injectAddString(String string, CallbackInfo ci) { + } +} diff --git a/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/targets/DescAtTarget.java b/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/targets/DescAtTarget.java new file mode 100644 index 00000000..9c9e3550 --- /dev/null +++ b/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/targets/DescAtTarget.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016, 2018, Player, asie + * Copyright (c) 2026, FabricMC + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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 Lesser 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 net.fabricmc.tinyremapper.extension.mixin.integration.targets; + +public class DescAtTarget { + public void mainTarget(int a) { + a = atTarget("test"); + } + + public int atTarget(String param) { + return 0; + } +}