55import java .util .logging .Logger ;
66
77import org .objectweb .asm .ClassVisitor ;
8+ import org .objectweb .asm .FieldVisitor ;
9+ import org .objectweb .asm .MethodVisitor ;
810import org .objectweb .asm .Opcodes ;
11+ import org .objectweb .asm .Type ;
912
1013public class JsonAttributeClassAdaptor extends ClassVisitor
1114{
@@ -15,23 +18,84 @@ public class JsonAttributeClassAdaptor extends ClassVisitor
1518 private JsonStruct json ;
1619 private boolean visitedOuter = false ;
1720 private Set <String > visitedInners = new HashSet <String >();
21+ private Set <String > refedInners = new HashSet <String >();
22+
1823
1924 public JsonAttributeClassAdaptor (ClassVisitor cv , MCInjectorImpl mci )
2025 {
2126 super (Opcodes .ASM4 , cv );
2227 this .mci = mci ;
2328 }
2429
30+ private String getAccess (int access )
31+ {
32+ StringBuilder buf = new StringBuilder ();
33+ if ((access & Opcodes .ACC_PUBLIC ) != 0 ) buf .append ("PUBLIC " );
34+ else if ((access & Opcodes .ACC_PRIVATE ) != 0 ) buf .append ("PRIVATE " );
35+ else if ((access & Opcodes .ACC_PROTECTED ) != 0 ) buf .append ("PROTECTED " );
36+ else buf .append ("DEFAULT " );
37+ if ((access & Opcodes .ACC_FINAL ) != 0 ) buf .append ("FINAL " );
38+ if ((access & Opcodes .ACC_SUPER ) != 0 ) buf .append ("SUPER " );
39+ if ((access & Opcodes .ACC_INTERFACE ) != 0 ) buf .append ("INTERFACE " );
40+ if ((access & Opcodes .ACC_ABSTRACT ) != 0 ) buf .append ("ABSTRACT " );
41+ if ((access & Opcodes .ACC_SYNTHETIC ) != 0 ) buf .append ("SYNTHETIC " );
42+ if ((access & Opcodes .ACC_ANNOTATION ) != 0 ) buf .append ("ANNOTATION " );
43+ if ((access & Opcodes .ACC_ENUM ) != 0 ) buf .append ("ENUM " );
44+ return buf .toString ().trim ();
45+ }
46+
47+ private boolean isInnerClass (String name )
48+ {
49+ return name .contains ("$" );
50+ }
51+
52+ private void referenced (Type type )
53+ {
54+ if (type .getSort () == Type .ARRAY )
55+ type = type .getElementType ();
56+ if (type .getSort () == Type .OBJECT )
57+ {
58+ String internal = type .getInternalName ();
59+ if (isInnerClass (internal ))
60+ refedInners .add (internal );
61+ }
62+ }
63+
2564 @ Override
2665 public void visit (int version , int access , String name , String signature , String superName , String [] interfaces )
2766 {
2867 this .className = name ;
2968 json = mci .json .get (className );
3069 visitedOuter = false ;
3170 visitedInners .clear ();
71+ for (String i : interfaces )
72+ if (isInnerClass (i ))
73+ refedInners .add (i );
3274 super .visit (version , access , name , signature , superName , interfaces );
3375 }
34-
76+
77+ @ Override
78+ public FieldVisitor visitField (int access , String name , String desc , String signature , Object value )
79+ {
80+ referenced (Type .getType (desc ));
81+ return super .visitField (access , name , desc , signature , value );
82+ }
83+
84+ @ Override
85+ public MethodVisitor visitMethod (int access , String name , String desc , String signature , String [] exceptions )
86+ {
87+ if (exceptions != null )
88+ for (String s : exceptions )
89+ if (isInnerClass (s ))
90+ refedInners .add (s );
91+
92+ referenced (Type .getReturnType (desc ));
93+ for (Type t : Type .getArgumentTypes (desc ))
94+ referenced (t );
95+
96+ return super .visitMethod (access , name , desc , signature , exceptions );
97+ }
98+
3599 @ Override
36100 public void visitInnerClass (String name , String outerName , String innerName , int access )
37101 {
@@ -58,7 +122,9 @@ public void visitEnd()
58122 JsonStruct .EnclosingMethod enc = json .enclosingMethod ;
59123 if (enc != null && !visitedOuter && enc .name != null && enc .desc != null )
60124 {
61- log .fine ("Adding Outer Class: " + enc .owner + " " + enc .name + " " + enc .desc );
125+ log .fine (" Adding Outer Class:" );
126+ log .fine (" Owner: " + enc .owner );
127+ log .fine (" Method: " + enc .name + enc .desc );
62128 super .visitOuterClass (enc .owner , enc .name , enc .desc );
63129 }
64130
@@ -68,10 +134,37 @@ public void visitEnd()
68134 {
69135 if (!visitedInners .contains (inner .inner_class ))
70136 {
71- log .fine ("Adding Inner Class: " + inner .inner_class + " " + inner .getAccess () + " " + inner .outer_class + " " + inner .inner_name );
137+ visitedInners .add (inner .inner_class );
138+ log .fine (" Adding Inner Class:" );
139+ log .fine (" Inner: " + inner .inner_class );
140+ log .fine (" Access: " + getAccess (inner .getAccess ()));
141+ if (inner .outer_class != null )
142+ log .fine (" Outer: " + inner .outer_class );
143+ if (inner .inner_name != null )
144+ log .fine (" Name: " + inner .inner_name );
72145 super .visitInnerClass (inner .inner_class , inner .outer_class , inner .inner_name , inner .getAccess ());
73146 }
74147 }
75148 }
149+
150+ refedInners .removeAll (visitedInners );
151+ for (String inner : refedInners )
152+ {
153+ JsonStruct .InnerClass ic = mci .inners .get (inner );
154+ if (ic == null )
155+ {
156+ log .fine (" Referenced Inner Class: " + inner + " (missing)" );
157+ }
158+ else
159+ {
160+ log .fine (" Referenced Inner Class:" );
161+ log .fine (" Inner: " + ic .inner_class );
162+ log .fine (" Access: " + getAccess (ic .getAccess ()));
163+ if (ic .outer_class != null )
164+ log .fine (" Outer: " + ic .outer_class );
165+ if (ic .inner_name != null )
166+ log .fine (" Name: " + ic .inner_name );
167+ }
168+ }
76169 }
77170}
0 commit comments