OSDN Git Service

93f7ec837248ccbdce356c036b5273a3f92ef228
[stigmata/stigmata.git] / src / main / java / jp / sourceforge / stigmata / birthmarks / uc / UsedClassesBirthmarkExtractVisitor.java
1 package jp.sourceforge.stigmata.birthmarks.uc;
2
3 /*
4  * $Id$
5  */
6
7 import jp.sourceforge.stigmata.Birthmark;
8 import jp.sourceforge.stigmata.BirthmarkContext;
9 import jp.sourceforge.stigmata.BirthmarkElement;
10 import jp.sourceforge.stigmata.birthmarks.BirthmarkExtractVisitor;
11
12 import org.objectweb.asm.ClassVisitor;
13 import org.objectweb.asm.FieldVisitor;
14 import org.objectweb.asm.Label;
15 import org.objectweb.asm.MethodAdapter;
16 import org.objectweb.asm.MethodVisitor;
17 import org.objectweb.asm.Type;
18 import org.objectweb.asm.signature.SignatureReader;
19 import org.objectweb.asm.signature.SignatureWriter;
20
21 /**
22  *
23  * @author Haruaki TAMADA
24  */
25 public class UsedClassesBirthmarkExtractVisitor extends BirthmarkExtractVisitor{
26     public UsedClassesBirthmarkExtractVisitor(ClassVisitor visitor, Birthmark birthmark,
27             BirthmarkContext context){
28         super(visitor, birthmark, context);
29     }
30
31     @Override
32     public void visit(int version, int access, String name, String signature,
33             String superName, String[] interfaces){
34         addSignatureClass(signature);
35
36         if(getEnvironment().getWellknownClassManager().isWellKnownClass(superName)){
37             add(superName);
38         }
39         for(String i: interfaces){
40             if(getEnvironment().getWellknownClassManager().isWellKnownClass(i)){
41                 add(i);
42             }
43         }
44     }
45
46     @Override
47     public FieldVisitor visitField(int access, String name, String desc,
48             String signature, Object value){
49         FieldVisitor visitor = super.visitField(access, name, desc, signature, value);
50
51         addDescriptor(desc);
52         addSignatureClass(signature);
53
54         return visitor;
55     }
56
57     @Override
58     public MethodVisitor visitMethod(int access, String name, String desc,
59                                      String signature, String[] exceptions){
60         if(exceptions != null){
61             for(String exception: exceptions){
62                 if(getEnvironment().getWellknownClassManager().isWellKnownClass(exception)){
63                     add(exception);
64                 }
65             }
66         }
67         addMethodDescriptor(desc);
68         addSignatureClass(signature);
69
70         MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);
71
72         return new MethodAdapter(visitor){
73             @Override
74             public void visitTypeInsn(int opcode, String desc){
75                 Type type = Type.getType("L" + desc + ";");
76                 if(checkType(type)){
77                     add(desc);
78                 }
79                 super.visitTypeInsn(opcode, desc);
80             }
81
82             @Override
83             public void visitTryCatchBlock(Label start, Label end, Label handle, String desc){
84                 Type type = Type.getType("L" + desc + ";");
85                 if(checkType(type)){
86                     add(getType(type));
87                 }
88                 super.visitTryCatchBlock(start, end, handle, desc);
89             }
90
91             @Override
92             public void visitMultiANewArrayInsn(String desc, int dims){
93                 Type type = Type.getType(desc);
94                 if(checkType(type)){
95                     add(getType(type));
96                 }
97                 super.visitMultiANewArrayInsn(desc, dims);
98             }
99
100             @Override
101             public void visitLocalVariable(String name, String desc, String signature,
102                                            Label start, Label end, int index){
103                 if(checkType(Type.getType(desc))){
104                     add(desc);
105                 }
106                 addSignatureClass(signature);
107
108                 super.visitLocalVariable(name, desc, signature, start, end, index);
109             }
110
111             @Override
112             public void visitFieldInsn(int opcode, String owner, String name, String desc){
113                 if(getEnvironment().getWellknownClassManager().isWellKnownClass(owner)){
114                     add(owner);
115                 }
116                 addDescriptor(desc);
117                 super.visitFieldInsn(opcode, owner, name, desc);
118             }
119             @Override
120             public void visitMethodInsn(int opcode, String owner, String name, String desc){
121                 String className = normalize(owner);
122                 if(getEnvironment().getWellknownClassManager().isWellKnownClass(className)){
123                     add(className);
124                 }
125                 addMethodDescriptor(desc);
126                 super.visitMethodInsn(opcode, owner, name, desc);
127             }
128         };
129     }
130
131     private void addSignatureClass(String signature){
132         if(signature != null){
133             SignatureReader in = new SignatureReader(signature);
134             SignatureWriter writer = new SignatureWriter(){
135                 @Override
136                 public void visitClassType(String classType){
137                     if(getEnvironment().getWellknownClassManager().isWellKnownClass(classType)){
138                         add(classType);
139                     }
140                 }
141             };
142             in.accept(writer);
143         }
144     }
145
146     private void addMethodDescriptor(String desc){
147         Type returnType = Type.getReturnType(desc);
148         Type[] args = Type.getArgumentTypes(desc);
149         if(checkType(returnType)){
150             add(getType(returnType));
151         }
152         for(Type arg: args){
153             if(checkType(arg)){
154                 add(getType(arg));
155             }
156         }
157     }
158
159     private void addDescriptor(String desc){
160         Type type = Type.getType(desc);
161         if(checkType(type)){
162             add(desc);
163         }
164     }
165
166     private String getType(Type type){
167         if(type.getSort() == Type.ARRAY){
168             while(type.getSort() != Type.ARRAY){
169                 type = type.getElementType();
170             }
171         }
172
173         if(type.getSort() == Type.OBJECT){
174             return normalize(type.getClassName());
175         }
176
177         return null;
178     }
179
180     private boolean checkType(Type type){
181         if(type.getSort() == Type.ARRAY){
182             while(type.getSort() != Type.ARRAY){
183                 type = type.getElementType();
184             }
185         }
186
187         if(type.getSort() == Type.OBJECT){
188             String className = type.getClassName();
189             if(getEnvironment().getWellknownClassManager().isWellKnownClass(className)){
190                 return true;
191             }
192         }
193         return false;
194     }
195
196     private String normalize(String name){
197         if(name.startsWith("L") && name.endsWith(";")){
198             name = name.substring(1, name.length() - 1);
199         }
200         name = name.replace('/', '.');
201
202         return name;
203     }
204
205     private void add(String name){
206         addElement(new BirthmarkElement(normalize(name)));
207     }
208 }