diff --git a/asm-commons/src/main/java/org/objectweb/asm/commons/ClassRemapper.java b/asm-commons/src/main/java/org/objectweb/asm/commons/ClassRemapper.java index 18251dc2551a62c21960d4722499ff400a49caf5..7ecdc31344a57be392598b5ca90d44a417f9ed93 100644 --- a/asm-commons/src/main/java/org/objectweb/asm/commons/ClassRemapper.java +++ b/asm-commons/src/main/java/org/objectweb/asm/commons/ClassRemapper.java @@ -168,7 +168,7 @@ public class ClassRemapper extends ClassVisitor { super.visitInnerClass( remapper.mapType(name), outerName == null ? null : remapper.mapType(outerName), - innerName, + innerName == null ? null : remapper.mapInnerClassName(name, outerName, innerName), access); } diff --git a/asm-commons/src/main/java/org/objectweb/asm/commons/Remapper.java b/asm-commons/src/main/java/org/objectweb/asm/commons/Remapper.java index d4f5969097fd565675f4377b6f56ba4fbb3c468b..0a0e7cabaffc5f3e13cf25623b04c3d1f675196a 100644 --- a/asm-commons/src/main/java/org/objectweb/asm/commons/Remapper.java +++ b/asm-commons/src/main/java/org/objectweb/asm/commons/Remapper.java @@ -214,6 +214,26 @@ public abstract class Remapper { return new SignatureRemapper(signatureVisitor, this); } + /** + * Maps an inner class name to its new name. The default implementation of this method provides a + * strategy that will work for inner classes produced by Java, but not necessarily other + * languages. Subclasses can override. + * + * @param name the fully-qualified internal name of the inner class. + * @param ownerName the internal name of the owner class of the inner class. + * @param innerName the internal name of the inner class. + * @return the new inner name of the inner class. + */ + public String mapInnerClassName( + final String name, final String ownerName, final String innerName) { + final String remappedInnerName = this.mapType(name); + if (remappedInnerName.contains("$")) { + return remappedInnerName.substring(remappedInnerName.lastIndexOf('$') + 1); + } else { + return innerName; + } + } + /** * Maps a method name to its new name. The default implementation of this method returns the given * name, unchanged. Subclasses can override. diff --git a/asm-commons/src/test/java/org/objectweb/asm/commons/ClassRemapperTest.java b/asm-commons/src/test/java/org/objectweb/asm/commons/ClassRemapperTest.java index 6af394c4068b3a3f1cbeef8ed31d868530301387..30ef0d0ac480755a1c18463abe983cd19833a622 100644 --- a/asm-commons/src/test/java/org/objectweb/asm/commons/ClassRemapperTest.java +++ b/asm-commons/src/test/java/org/objectweb/asm/commons/ClassRemapperTest.java @@ -58,6 +58,26 @@ public class ClassRemapperTest extends AsmTest { assertEquals("new/pkg/C", classNode.name); } + @Test + public void testRenameInnerClass() { + final ClassNode node = new ClassNode(); + final ClassRemapper remapper = + new ClassRemapper( + node, + new Remapper() { + @Override + public String map(final String internalName) { + if ("a".equals(internalName)) return "pkg/Demo"; + if ("a$g".equals(internalName)) return "pkg/Demo$Container"; + return internalName; + } + }); + remapper.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "a", null, "java/lang/Object", null); + remapper.visitInnerClass("a$g", "a", "g", Opcodes.ACC_PUBLIC); + assertEquals("pkg/Demo", node.innerClasses.get(0).outerName); + assertEquals("Container", node.innerClasses.get(0).innerName); + } + @Test public void testRenameModuleHashes() { ClassNode classNode = new ClassNode();