From f57e387acd554890929001d3086a892ef3d94b51 Mon Sep 17 00:00:00 2001 From: ishland Date: Tue, 6 Jan 2026 00:15:53 +0800 Subject: [PATCH 1/5] fix: always add descriptor to disambiguate remapped names --- .../CommonInjectionAnnotationVisitor.java | 2 +- .../mixin/integration/MixinIntegrationTest.java | 17 ++++++++++++++++- .../mixins/AmbiguousRemappedNameMixin.java | 15 +++++++++++++++ .../targets/AmbiguousRemappedNameTarget.java | 11 +++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/mixins/AmbiguousRemappedNameMixin.java create mode 100644 src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/targets/AmbiguousRemappedNameTarget.java 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 762c07f4..4080ccf1 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 @@ -191,7 +191,7 @@ public MemberInfo result() { } return collection.stream().findFirst() - .map(pair -> new MemberInfo(data.mapper.asTrRemapper().map(info.getOwner()), pair.first(), info.getQuantifier(), info.getDesc().isEmpty() ? "" : pair.second())) + .map(pair -> new MemberInfo(data.mapper.asTrRemapper().map(info.getOwner()), pair.first(), info.getQuantifier(), info.getQuantifier().equals("*") ? "" : pair.second())) .orElse(info); } } 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 9dbcbc7e..81315860 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 @@ -41,8 +41,10 @@ import net.fabricmc.tinyremapper.OutputConsumerPath; 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.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.NonObfuscatedOverrideTarget; import net.fabricmc.tinyremapper.extension.mixin.integration.targets.WildcardTarget; @@ -69,13 +71,26 @@ public void remapInvokeNonObfuscatedOverride() throws IOException { out.acceptMethod(new IMappingProvider.Member(fqn, "callAdd", "(Ljava/lang/Object;)V"), "obfuscatedCallAdd"); }); - assertTrue(remapped.contains("@Lorg/spongepowered/asm/mixin/injection/Inject;(method={\"obfuscatedCallAdd\"")); + assertTrue(remapped.contains("@Lorg/spongepowered/asm/mixin/injection/Inject;(method={\"obfuscatedCallAdd(Ljava/lang/Object;)V\"")); // Method is implemented in the target class assertTrue(remapped.contains("@Lorg/spongepowered/asm/mixin/injection/At;(value=\"INVOKE\", target=\"Lcom/example/Obfuscated;add(Ljava/lang/Object;)Z\"")); // Method is NOT implemented in the target class and instead comes from unobfuscated super class assertTrue(remapped.contains("@Lorg/spongepowered/asm/mixin/injection/At;(value=\"INVOKE\", target=\"Lcom/example/Obfuscated;addAll(Ljava/util/Collection;)Z\"")); } + @Test + public void remapAmbiuousRemappedName() throws IOException { + String remapped = remap(AmbiguousRemappedNameTarget.class, AmbiguousRemappedNameMixin.class, out -> { + String fqn = "net/fabricmc/tinyremapper/extension/mixin/integration/targets/AmbiguousRemappedNameTarget"; + out.acceptClass(fqn, "com/example/Remapped"); + out.acceptMethod(new IMappingProvider.Member(fqn, "addString", "(Ljava/lang/String;)V"), "add"); + out.acceptMethod(new IMappingProvider.Member(fqn, "addList", "(Ljava/util/List;)V"), "add"); + }); + + // full signature is used to disambiguate names + assertTrue(remapped.contains("@Lorg/spongepowered/asm/mixin/injection/Inject;(method={\"add(Ljava/lang/String;)V\"")); + } + 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/AmbiguousRemappedNameMixin.java b/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/mixins/AmbiguousRemappedNameMixin.java new file mode 100644 index 00000000..f9ad32a1 --- /dev/null +++ b/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/mixins/AmbiguousRemappedNameMixin.java @@ -0,0 +1,15 @@ +package net.fabricmc.tinyremapper.extension.mixin.integration.mixins; + +import net.fabricmc.tinyremapper.extension.mixin.integration.targets.AmbiguousRemappedNameTarget; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(AmbiguousRemappedNameTarget.class) +public class AmbiguousRemappedNameMixin { + @Inject(method = "addString", at = @At("HEAD")) + private void injectAddString(String string, CallbackInfo ci) { + } +} diff --git a/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/targets/AmbiguousRemappedNameTarget.java b/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/targets/AmbiguousRemappedNameTarget.java new file mode 100644 index 00000000..1261f36d --- /dev/null +++ b/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/targets/AmbiguousRemappedNameTarget.java @@ -0,0 +1,11 @@ +package net.fabricmc.tinyremapper.extension.mixin.integration.targets; + +import java.util.List; + +public class AmbiguousRemappedNameTarget { + public void addString(String string) { + } + + public void addList(List list) { + } +} From d7a310fee07c34aa9df43a6c5fecd9405f77b31b Mon Sep 17 00:00:00 2001 From: ishland Date: Tue, 6 Jan 2026 00:50:01 +0800 Subject: [PATCH 2/5] fix: checkstyle and spotless --- .../mixins/AmbiguousRemappedNameMixin.java | 22 +++++++++++++++++-- .../targets/AmbiguousRemappedNameTarget.java | 18 +++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/mixins/AmbiguousRemappedNameMixin.java b/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/mixins/AmbiguousRemappedNameMixin.java index f9ad32a1..d1482500 100644 --- a/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/mixins/AmbiguousRemappedNameMixin.java +++ b/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/mixins/AmbiguousRemappedNameMixin.java @@ -1,12 +1,30 @@ -package net.fabricmc.tinyremapper.extension.mixin.integration.mixins; +/* + * 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 . + */ -import net.fabricmc.tinyremapper.extension.mixin.integration.targets.AmbiguousRemappedNameTarget; +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.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import net.fabricmc.tinyremapper.extension.mixin.integration.targets.AmbiguousRemappedNameTarget; + @Mixin(AmbiguousRemappedNameTarget.class) public class AmbiguousRemappedNameMixin { @Inject(method = "addString", at = @At("HEAD")) diff --git a/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/targets/AmbiguousRemappedNameTarget.java b/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/targets/AmbiguousRemappedNameTarget.java index 1261f36d..ec381f2d 100644 --- a/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/targets/AmbiguousRemappedNameTarget.java +++ b/src/test/java/net/fabricmc/tinyremapper/extension/mixin/integration/targets/AmbiguousRemappedNameTarget.java @@ -1,3 +1,21 @@ +/* + * 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; import java.util.List; From d869ac5f76d467e36d52bf29b2905497670378e1 Mon Sep 17 00:00:00 2001 From: ishland Date: Tue, 6 Jan 2026 22:43:15 +0800 Subject: [PATCH 3/5] change: only add descriptor for ambiguous target names --- .../CommonInjectionAnnotationVisitor.java | 17 +++++++++++++++-- .../mixin/integration/MixinIntegrationTest.java | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) 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 4080ccf1..5f44b0d9 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 @@ -27,6 +27,7 @@ import org.objectweb.asm.AnnotationVisitor; import net.fabricmc.tinyremapper.api.TrClass; +import net.fabricmc.tinyremapper.api.TrMethod; import net.fabricmc.tinyremapper.api.TrMember; import net.fabricmc.tinyremapper.api.TrMember.MemberType; import net.fabricmc.tinyremapper.extension.mixin.common.IMappable; @@ -181,7 +182,17 @@ public MemberInfo result() { .map(target -> resolvePartial(target, info.getName(), info.getDesc())) .filter(Optional::isPresent) .map(Optional::get) - .map(m -> Pair.of(data.mapper.mapName(m), data.mapper.mapDesc(m))) + .map(m -> { + String mappedName = data.mapper.mapName(m); + boolean shouldPassDesc = false; // only pass descriptor on ambiguous targets + for (TrMethod other : m.getOwner().getMethods()) { + if (other == m) continue; + if (data.mapper.mapName(other).equals(mappedName)) { + shouldPassDesc = true; + } + } + return Pair.of(mappedName, shouldPassDesc ? data.mapper.mapDesc(m) : ""); + }) .distinct().collect(Collectors.toList()); if (collection.size() > 1) { @@ -191,7 +202,9 @@ public MemberInfo result() { } return collection.stream().findFirst() - .map(pair -> new MemberInfo(data.mapper.asTrRemapper().map(info.getOwner()), pair.first(), info.getQuantifier(), info.getQuantifier().equals("*") ? "" : pair.second())) + .map(pair -> { + return new MemberInfo(data.mapper.asTrRemapper().map(info.getOwner()), pair.first(), info.getQuantifier(), info.getQuantifier().equals("*") ? "" : pair.second()); + }) .orElse(info); } } 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 81315860..576f768c 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 @@ -71,7 +71,7 @@ public void remapInvokeNonObfuscatedOverride() throws IOException { out.acceptMethod(new IMappingProvider.Member(fqn, "callAdd", "(Ljava/lang/Object;)V"), "obfuscatedCallAdd"); }); - assertTrue(remapped.contains("@Lorg/spongepowered/asm/mixin/injection/Inject;(method={\"obfuscatedCallAdd(Ljava/lang/Object;)V\"")); + assertTrue(remapped.contains("@Lorg/spongepowered/asm/mixin/injection/Inject;(method={\"obfuscatedCallAdd\"")); // Method is implemented in the target class assertTrue(remapped.contains("@Lorg/spongepowered/asm/mixin/injection/At;(value=\"INVOKE\", target=\"Lcom/example/Obfuscated;add(Ljava/lang/Object;)Z\"")); // Method is NOT implemented in the target class and instead comes from unobfuscated super class From 56f0aac7eccea98516e923486088b2cea938bc34 Mon Sep 17 00:00:00 2001 From: ishland Date: Tue, 6 Jan 2026 22:46:10 +0800 Subject: [PATCH 4/5] fix: checkstyle again --- .../injection/CommonInjectionAnnotationVisitor.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 5f44b0d9..4edbd428 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 @@ -27,9 +27,9 @@ import org.objectweb.asm.AnnotationVisitor; import net.fabricmc.tinyremapper.api.TrClass; -import net.fabricmc.tinyremapper.api.TrMethod; import net.fabricmc.tinyremapper.api.TrMember; import net.fabricmc.tinyremapper.api.TrMember.MemberType; +import net.fabricmc.tinyremapper.api.TrMethod; import net.fabricmc.tinyremapper.extension.mixin.common.IMappable; import net.fabricmc.tinyremapper.extension.mixin.common.ResolveUtility; import net.fabricmc.tinyremapper.extension.mixin.common.data.Annotation; @@ -184,13 +184,16 @@ public MemberInfo result() { .map(Optional::get) .map(m -> { String mappedName = data.mapper.mapName(m); - boolean shouldPassDesc = false; // only pass descriptor on ambiguous targets - for (TrMethod other : m.getOwner().getMethods()) { + boolean shouldPassDesc = false; + + for (TrMethod other : m.getOwner().getMethods()) { // look for ambiguous targets if (other == m) continue; + if (data.mapper.mapName(other).equals(mappedName)) { shouldPassDesc = true; } } + return Pair.of(mappedName, shouldPassDesc ? data.mapper.mapDesc(m) : ""); }) .distinct().collect(Collectors.toList()); From cf6cd500d429526e68e6daf5b46259a777019f79 Mon Sep 17 00:00:00 2001 From: ishland Date: Tue, 6 Jan 2026 22:47:12 +0800 Subject: [PATCH 5/5] chore: diff cleanup --- .../injection/CommonInjectionAnnotationVisitor.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 4edbd428..47a531a3 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 @@ -205,9 +205,7 @@ public MemberInfo result() { } return collection.stream().findFirst() - .map(pair -> { - return new MemberInfo(data.mapper.asTrRemapper().map(info.getOwner()), pair.first(), info.getQuantifier(), info.getQuantifier().equals("*") ? "" : pair.second()); - }) + .map(pair -> new MemberInfo(data.mapper.asTrRemapper().map(info.getOwner()), pair.first(), info.getQuantifier(), info.getQuantifier().equals("*") ? "" : pair.second())) .orElse(info); } }