OSDN Git Service

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