1
2
3
4 package net.sourceforge.pmd.dcd;
5
6 import java.lang.reflect.Method;
7 import java.lang.reflect.Modifier;
8
9 import net.sourceforge.pmd.dcd.graph.ClassNode;
10 import net.sourceforge.pmd.dcd.graph.ConstructorNode;
11 import net.sourceforge.pmd.dcd.graph.FieldNode;
12 import net.sourceforge.pmd.dcd.graph.MemberNode;
13 import net.sourceforge.pmd.dcd.graph.MethodNode;
14 import net.sourceforge.pmd.dcd.graph.NodeVisitorAdapter;
15 import net.sourceforge.pmd.dcd.graph.UsageGraph;
16
17
18
19
20
21
22 public class UsageNodeVisitor extends NodeVisitorAdapter {
23
24
25
26
27 public static final class Options {
28 private boolean ignoreClassAnonymous = true;
29
30 private boolean ignoreConstructorStaticInitializer = true;
31
32 private boolean ignoreConstructorSinglePrivateNoArg = true;
33
34 private boolean ignoreConstructorAllPrivate = false;
35
36 private boolean ignoreMethodJavaLangObjectOverride = true;
37
38 private boolean ignoreMethodAllOverride = false;
39
40 private boolean ignoreMethodMain = true;
41
42 private boolean ignoreFieldInlinable = true;
43
44 public boolean isIgnoreClassAnonymous() {
45 return ignoreClassAnonymous;
46 }
47
48 public void setIgnoreClassAnonymous(boolean ignoreClassAnonymous) {
49 this.ignoreClassAnonymous = ignoreClassAnonymous;
50 }
51
52 public boolean isIgnoreConstructorStaticInitializer() {
53 return ignoreConstructorStaticInitializer;
54 }
55
56 public void setIgnoreConstructorStaticInitializer(boolean ignoreConstructorStaticInitializer) {
57 this.ignoreConstructorStaticInitializer = ignoreConstructorStaticInitializer;
58 }
59
60 public boolean isIgnoreConstructorSinglePrivateNoArg() {
61 return ignoreConstructorSinglePrivateNoArg;
62 }
63
64 public void setIgnoreConstructorSinglePrivateNoArg(boolean ignoreConstructorSinglePrivateNoArg) {
65 this.ignoreConstructorSinglePrivateNoArg = ignoreConstructorSinglePrivateNoArg;
66 }
67
68 public boolean isIgnoreConstructorAllPrivate() {
69 return ignoreConstructorAllPrivate;
70 }
71
72 public void setIgnoreConstructorAllPrivate(boolean ignoreConstructorAllPrivate) {
73 this.ignoreConstructorAllPrivate = ignoreConstructorAllPrivate;
74 }
75
76 public boolean isIgnoreMethodJavaLangObjectOverride() {
77 return ignoreMethodJavaLangObjectOverride;
78 }
79
80 public void setIgnoreMethodJavaLangObjectOverride(boolean ignoreMethodJavaLangObjectOverride) {
81 this.ignoreMethodJavaLangObjectOverride = ignoreMethodJavaLangObjectOverride;
82 }
83
84 public boolean isIgnoreMethodAllOverride() {
85 return ignoreMethodAllOverride;
86 }
87
88 public void setIgnoreMethodAllOverride(boolean ignoreMethodAllOverride) {
89 this.ignoreMethodAllOverride = ignoreMethodAllOverride;
90 }
91
92 public boolean isIgnoreMethodMain() {
93 return ignoreMethodMain;
94 }
95
96 public void setIgnoreMethodMain(boolean ignoreMethodMain) {
97 this.ignoreMethodMain = ignoreMethodMain;
98 }
99
100 public boolean isIgnoreFieldInlinable() {
101 return ignoreFieldInlinable;
102 }
103
104 public void setIgnoreFieldInlinable(boolean ignoreFieldInlinable) {
105 this.ignoreFieldInlinable = ignoreFieldInlinable;
106 }
107
108 }
109
110 private final Options options = new Options();
111
112 public Object visit(UsageGraph usageGraph, Object data) {
113 System.out.println("----------------------------------------");
114 super.visit(usageGraph, data);
115 System.out.println("----------------------------------------");
116 return data;
117 }
118
119 public Object visit(ClassNode classNode, Object data) {
120 boolean log = true;
121 if (options.isIgnoreClassAnonymous() && classNode.getType().isAnonymousClass()) {
122 ignore("class anonymous", classNode);
123 log = false;
124 }
125 if (log) {
126 System.out.println("--- " + classNode.getName() + " ---");
127 return super.visit(classNode, data);
128 } else {
129 return data;
130 }
131 }
132
133 public Object visit(FieldNode fieldNode, Object data) {
134 if (fieldNode.getUsers().isEmpty()) {
135 boolean log = true;
136
137
138
139 if (options.isIgnoreFieldInlinable()) {
140 if (Modifier.isFinal(fieldNode.getMember().getModifiers())
141 && fieldNode.getMember().getType().isPrimitive()
142 || fieldNode.getMember().getType().getName().equals("java.lang.String")) {
143 ignore("field inlinable", fieldNode);
144 log = false;
145 }
146 }
147 if (log) {
148 System.out.println("\t" + fieldNode.toStringLong());
149 }
150 }
151 return super.visit(fieldNode, data);
152 }
153
154 public Object visit(ConstructorNode constructorNode, Object data) {
155 if (constructorNode.getUsers().isEmpty()) {
156 boolean log = true;
157 if (constructorNode.isStaticInitializer()) {
158 if (options.isIgnoreConstructorStaticInitializer()) {
159 ignore("constructor static initializer", constructorNode);
160 log = false;
161 }
162 } else if (constructorNode.isInstanceInitializer()) {
163 if (Modifier.isPrivate(constructorNode.getMember().getModifiers())) {
164 if (options.isIgnoreConstructorAllPrivate()) {
165 ignore("constructor all private", constructorNode);
166 log = false;
167 } else if (options.isIgnoreConstructorSinglePrivateNoArg()
168 && constructorNode.getMember().getParameterTypes().length == 0
169 && constructorNode.getClassNode().getConstructorNodes().size() == 1) {
170 ignore("constructor single private no-arg", constructorNode);
171 log = false;
172 }
173 }
174 }
175 if (log) {
176 System.out.println("\t" + constructorNode.toStringLong());
177 }
178 }
179 return super.visit(constructorNode, data);
180 }
181
182 private static boolean isMainMethod(MethodNode node) {
183
184 final Method method = node.getMember();
185
186 return method.getName().equals("main")
187 && Modifier.isPublic(method.getModifiers())
188 && Modifier.isStatic(method.getModifiers())
189 && method.getReturnType() == Void.TYPE
190 && method.getParameterTypes().length == 1
191 && method.getParameterTypes()[0].isArray()
192 && method.getParameterTypes()[0].getComponentType().equals(java.lang.String.class);
193 }
194
195
196 public Object visit(MethodNode methodNode, Object data) {
197 if (methodNode.getUsers().isEmpty()) {
198 boolean log = true;
199 if (options.isIgnoreMethodAllOverride()) {
200 if (ClassLoaderUtil.isOverridenMethod(methodNode.getClassNode().getClass(), methodNode.getMember(),
201 false)) {
202 ignore("method all override", methodNode);
203 log = false;
204 }
205 } else if (options.isIgnoreMethodJavaLangObjectOverride()) {
206 if (ClassLoaderUtil.isOverridenMethod(java.lang.Object.class, methodNode.getMember(), true)) {
207 ignore("method java.lang.Object override", methodNode);
208 log = false;
209 }
210 }
211 if (options.isIgnoreMethodMain()) {
212 if (isMainMethod(methodNode)) {
213 ignore("method public static void main(String[])", methodNode);
214 log = false;
215 }
216 }
217 if (log) {
218 System.out.println("\t" + methodNode.toStringLong());
219 }
220 }
221 return super.visit(methodNode, data);
222 }
223
224 private void ignore(String description, ClassNode classNode) {
225 System.out.println("Ignoring " + description + ": " + classNode.getName());
226 }
227
228 private void ignore(String description, MemberNode memberNode) {
229 System.out.println("Ignoring " + description + ": " + memberNode.toStringLong());
230 }
231 }