Skip to content

Commit f148917

Browse files
committed
Bump version number, and add new transformer that adds synthetic <init> methods to inner classes.
Mojang's current snapshots include inner classes that are never initalized, so ProGuard removes the <init> methods. We must re-add them so that FernFlower can detect the synthetic parent instance for proper decompilation.
1 parent 7258466 commit f148917

File tree

3 files changed

+81
-1
lines changed

3 files changed

+81
-1
lines changed

build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ apply plugin: 'fatjar'
1313
apply plugin: 'maven'
1414

1515
group = 'de.oceanlabs.mcp'
16-
version = '3.4-SNAPSHOT'
16+
version = '3.5-SNAPSHOT'
1717
targetCompatibility = '1.6'
1818
sourceCompatibility = '1.6'
1919

src/main/java/de/oceanlabs/mcp/mcinjector/MCInjectorImpl.java

+3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import de.oceanlabs.mcp.mcinjector.adaptors.ApplyMap;
4444
import de.oceanlabs.mcp.mcinjector.adaptors.ApplyMarker;
4545
import de.oceanlabs.mcp.mcinjector.adaptors.GenerateMap;
46+
import de.oceanlabs.mcp.mcinjector.adaptors.InnerClassInitAdder;
4647
import de.oceanlabs.mcp.mcinjector.adaptors.JsonAttribute;
4748
import de.oceanlabs.mcp.mcinjector.adaptors.LVTFernflower;
4849
import de.oceanlabs.mcp.mcinjector.adaptors.LVTLvt;
@@ -640,6 +641,8 @@ public byte[] processClass(byte[] cls, boolean readOnly)
640641
}
641642
ca = new AccessReader(ca, this);
642643

644+
ca = new InnerClassInitAdder(ca);
645+
643646
cr.accept(ca, 0);
644647

645648
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package de.oceanlabs.mcp.mcinjector.adaptors;
2+
3+
import static org.objectweb.asm.Opcodes.*;
4+
5+
import java.util.logging.Logger;
6+
7+
import org.objectweb.asm.ClassVisitor;
8+
import org.objectweb.asm.FieldVisitor;
9+
import org.objectweb.asm.MethodVisitor;
10+
import org.objectweb.asm.Opcodes;
11+
12+
public class InnerClassInitAdder extends ClassVisitor
13+
{
14+
private static final Logger log = Logger.getLogger("MCInjector");
15+
private String className, parentName, parentField;
16+
private boolean hasInit = false;
17+
private boolean isStatic = false;
18+
private int FIELD_ACCESS = ACC_FINAL | ACC_SYNTHETIC;
19+
20+
public InnerClassInitAdder(ClassVisitor cv)
21+
{
22+
super(Opcodes.ASM5, cv);
23+
}
24+
25+
@Override
26+
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
27+
{
28+
this.isStatic = (access & ACC_STATIC) != 0;
29+
this.className = name;
30+
super.visit(version, access, name, signature, superName, interfaces);
31+
}
32+
33+
@Override // The reader *should* read this before any fields/methods, so we can set the parent name to find the field
34+
public void visitInnerClass(String name, String outerName, String innerName, int access)
35+
{
36+
if (this.className.equals(name))
37+
{
38+
this.parentName = "L" + outerName + ";";
39+
}
40+
super.visitInnerClass(name, outerName, innerName, access);
41+
}
42+
43+
@Override
44+
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value)
45+
{
46+
if ((access & FIELD_ACCESS) == FIELD_ACCESS && desc.equals(this.parentName))
47+
{
48+
this.parentField = name;
49+
}
50+
return super.visitField(access, name, desc, signature, value);
51+
}
52+
53+
@Override
54+
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
55+
{
56+
if ("<init>".equals(name))
57+
{
58+
hasInit = true;
59+
}
60+
return super.visitMethod(access, name, desc, signature, exceptions);
61+
}
62+
63+
@Override
64+
public void visitEnd()
65+
{
66+
if (!hasInit && !isStatic && parentName != null && parentField != null)
67+
{
68+
log.fine(" Adding synthetic <init> " + parentName + " " + parentField);
69+
MethodVisitor mv = this.visitMethod(ACC_PRIVATE | ACC_SYNTHETIC, "<init>", "(" + parentName + ")V", null, null);
70+
mv.visitVarInsn(ALOAD, 0);
71+
mv.visitVarInsn(ALOAD, 1);
72+
mv.visitFieldInsn(PUTFIELD, className, parentField, parentName);
73+
mv.visitInsn(RETURN);
74+
}
75+
super.visitEnd();
76+
}
77+
}

0 commit comments

Comments
 (0)