Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
DependencyVisitor |
|
| 1.3448275862068966;1.345 |
1 | package org.apache.maven.shared.dependency.analyzer.asm; | |
2 | ||
3 | /* | |
4 | * Licensed to the Apache Software Foundation (ASF) under one | |
5 | * or more contributor license agreements. See the NOTICE file | |
6 | * distributed with this work for additional information | |
7 | * regarding copyright ownership. The ASF licenses this file | |
8 | * to you under the Apache License, Version 2.0 (the | |
9 | * "License"); you may not use this file except in compliance | |
10 | * with the License. You may obtain a copy of the License at | |
11 | * | |
12 | * http://www.apache.org/licenses/LICENSE-2.0 | |
13 | * | |
14 | * Unless required by applicable law or agreed to in writing, | |
15 | * software distributed under the License is distributed on an | |
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
17 | * KIND, either express or implied. See the License for the | |
18 | * specific language governing permissions and limitations | |
19 | * under the License. | |
20 | */ | |
21 | ||
22 | import java.util.HashSet; | |
23 | import java.util.Set; | |
24 | ||
25 | import org.objectweb.asm.AnnotationVisitor; | |
26 | import org.objectweb.asm.Attribute; | |
27 | import org.objectweb.asm.ClassVisitor; | |
28 | import org.objectweb.asm.FieldVisitor; | |
29 | import org.objectweb.asm.Label; | |
30 | import org.objectweb.asm.MethodVisitor; | |
31 | import org.objectweb.asm.Type; | |
32 | import org.objectweb.asm.signature.SignatureReader; | |
33 | import org.objectweb.asm.signature.SignatureVisitor; | |
34 | ||
35 | /** | |
36 | * Computes the set of classes referenced by visited code. | |
37 | * Inspired by <code>org.objectweb.asm.depend.DependencyVisitor</code> in the ASM dependencies example. | |
38 | * | |
39 | * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a> | |
40 | * @version $Id: DependencyVisitor.java 1174427 2011-09-22 22:25:17Z hboutemy $ | |
41 | * @see #getClasses() | |
42 | */ | |
43 | public class DependencyVisitor | |
44 | implements AnnotationVisitor, SignatureVisitor, ClassVisitor, FieldVisitor, MethodVisitor | |
45 | { | |
46 | // fields ----------------------------------------------------------------- | |
47 | ||
48 | private final Set<String> classes; | |
49 | ||
50 | // constructors ----------------------------------------------------------- | |
51 | ||
52 | public DependencyVisitor() | |
53 | 77 | { |
54 | 77 | classes = new HashSet<String>(); |
55 | 77 | } |
56 | ||
57 | // ClassVisitor methods --------------------------------------------------- | |
58 | ||
59 | /* | |
60 | * @see org.objectweb.asm.ClassVisitor#visit(int, int, java.lang.String, java.lang.String, java.lang.String, | |
61 | * java.lang.String[]) | |
62 | */ | |
63 | public void visit( final int version, final int access, final String name, final String signature, | |
64 | final String superName, final String[] interfaces ) | |
65 | { | |
66 | 13 | if ( signature == null ) |
67 | { | |
68 | 8 | addName( superName ); |
69 | 8 | addNames( interfaces ); |
70 | } | |
71 | else | |
72 | { | |
73 | 5 | addSignature( signature ); |
74 | } | |
75 | 13 | } |
76 | ||
77 | /* | |
78 | * @see org.objectweb.asm.ClassVisitor#visitSource(java.lang.String, java.lang.String) | |
79 | */ | |
80 | public void visitSource( final String source, final String debug ) | |
81 | { | |
82 | // no-op | |
83 | 5 | } |
84 | ||
85 | /* | |
86 | * @see org.objectweb.asm.ClassVisitor#visitOuterClass(java.lang.String, java.lang.String, java.lang.String) | |
87 | */ | |
88 | public void visitOuterClass( final String owner, final String name, final String desc ) | |
89 | { | |
90 | // addName(owner); | |
91 | // addMethodDesc(desc); | |
92 | 2 | } |
93 | ||
94 | /* | |
95 | * @see org.objectweb.asm.ClassVisitor#visitAnnotation(java.lang.String, boolean) | |
96 | */ | |
97 | public AnnotationVisitor visitAnnotation( final String desc, final boolean visible ) | |
98 | { | |
99 | 2 | addDesc( desc ); |
100 | ||
101 | 2 | return this; |
102 | } | |
103 | ||
104 | /* | |
105 | * @see org.objectweb.asm.ClassVisitor#visitAttribute(org.objectweb.asm.Attribute) | |
106 | */ | |
107 | public void visitAttribute( final Attribute attr ) | |
108 | { | |
109 | // no-op | |
110 | 1 | } |
111 | ||
112 | /* | |
113 | * @see org.objectweb.asm.ClassVisitor#visitInnerClass(java.lang.String, java.lang.String, java.lang.String, int) | |
114 | */ | |
115 | public void visitInnerClass( final String name, final String outerName, final String innerName, final int access ) | |
116 | { | |
117 | // addName( outerName); | |
118 | // addName( innerName); | |
119 | 2 | } |
120 | ||
121 | /* | |
122 | * @see org.objectweb.asm.ClassVisitor#visitField(int, java.lang.String, java.lang.String, java.lang.String, | |
123 | * java.lang.Object) | |
124 | */ | |
125 | public FieldVisitor visitField( final int access, final String name, final String desc, final String signature, | |
126 | final Object value ) | |
127 | { | |
128 | 6 | if ( signature == null ) |
129 | { | |
130 | 5 | addDesc( desc ); |
131 | } | |
132 | else | |
133 | { | |
134 | 1 | addTypeSignature( signature ); |
135 | } | |
136 | ||
137 | 6 | if ( value instanceof Type ) |
138 | { | |
139 | 0 | addType( (Type) value ); |
140 | } | |
141 | ||
142 | 6 | return this; |
143 | } | |
144 | ||
145 | /* | |
146 | * @see org.objectweb.asm.ClassVisitor#visitMethod(int, java.lang.String, java.lang.String, java.lang.String, | |
147 | * java.lang.String[]) | |
148 | */ | |
149 | public MethodVisitor visitMethod( final int access, final String name, final String desc, final String signature, | |
150 | final String[] exceptions ) | |
151 | { | |
152 | 17 | if ( signature == null ) |
153 | { | |
154 | 16 | addMethodDesc( desc ); |
155 | } | |
156 | else | |
157 | { | |
158 | 1 | addSignature( signature ); |
159 | } | |
160 | ||
161 | 17 | addNames( exceptions ); |
162 | ||
163 | 17 | return this; |
164 | } | |
165 | ||
166 | // MethodVisitor methods -------------------------------------------------- | |
167 | ||
168 | /* | |
169 | * @see org.objectweb.asm.MethodVisitor#visitAnnotationDefault() | |
170 | */ | |
171 | public AnnotationVisitor visitAnnotationDefault() | |
172 | { | |
173 | 1 | return this; |
174 | } | |
175 | ||
176 | /* | |
177 | * @see org.objectweb.asm.MethodVisitor#visitParameterAnnotation(int, java.lang.String, boolean) | |
178 | */ | |
179 | public AnnotationVisitor visitParameterAnnotation( final int parameter, final String desc, final boolean visible ) | |
180 | { | |
181 | 1 | addDesc( desc ); |
182 | ||
183 | 1 | return this; |
184 | } | |
185 | ||
186 | /* | |
187 | * @see org.objectweb.asm.MethodVisitor#visitCode() | |
188 | */ | |
189 | public void visitCode() | |
190 | { | |
191 | // no-op | |
192 | 5 | } |
193 | ||
194 | /* | |
195 | * @see org.objectweb.asm.MethodVisitor#visitFrame(int, int, java.lang.Object[], int, java.lang.Object[]) | |
196 | */ | |
197 | public void visitFrame( final int type, final int nLocal, final Object[] local, final int nStack, | |
198 | final Object[] stack ) | |
199 | { | |
200 | // no-op | |
201 | 1 | } |
202 | ||
203 | /* | |
204 | * @see org.objectweb.asm.MethodVisitor#visitInsn(int) | |
205 | */ | |
206 | public void visitInsn( final int opcode ) | |
207 | { | |
208 | // no-op | |
209 | 7 | } |
210 | ||
211 | /* | |
212 | * @see org.objectweb.asm.MethodVisitor#visitIntInsn(int, int) | |
213 | */ | |
214 | public void visitIntInsn( final int opcode, final int operand ) | |
215 | { | |
216 | // no-op | |
217 | 1 | } |
218 | ||
219 | /* | |
220 | * @see org.objectweb.asm.MethodVisitor#visitVarInsn(int, int) | |
221 | */ | |
222 | public void visitVarInsn( final int opcode, final int var ) | |
223 | { | |
224 | // no-op | |
225 | 7 | } |
226 | ||
227 | /* | |
228 | * @see org.objectweb.asm.MethodVisitor#visitTypeInsn(int, java.lang.String) | |
229 | */ | |
230 | public void visitTypeInsn( final int opcode, final String desc ) | |
231 | { | |
232 | 3 | if ( desc.charAt( 0 ) == '[' ) |
233 | { | |
234 | 0 | addDesc( desc ); |
235 | } | |
236 | else | |
237 | { | |
238 | 3 | addName( desc ); |
239 | } | |
240 | 3 | } |
241 | ||
242 | /* | |
243 | * @see org.objectweb.asm.MethodVisitor#visitFieldInsn(int, java.lang.String, java.lang.String, java.lang.String) | |
244 | */ | |
245 | public void visitFieldInsn( final int opcode, final String owner, final String name, final String desc ) | |
246 | { | |
247 | 2 | addName( owner ); |
248 | /* | |
249 | * NOTE: Merely accessing a field does not impose a direct dependency on its type. For example, the code line | |
250 | * <code>java.lang.Object var = bean.field;</code> does not directly depend on the type of the field. A direct | |
251 | * dependency is only introduced when the code explicitly references the field's type by means of a variable | |
252 | * declaration or a type check/cast. Those cases are handled by other visitor callbacks. | |
253 | */ | |
254 | 2 | } |
255 | ||
256 | /* | |
257 | * @see org.objectweb.asm.MethodVisitor#visitMethodInsn(int, java.lang.String, java.lang.String, java.lang.String) | |
258 | */ | |
259 | public void visitMethodInsn( final int opcode, final String owner, final String name, final String desc ) | |
260 | { | |
261 | 16 | addName( owner ); |
262 | /* | |
263 | * NOTE: Merely invoking a method does not impose a direct dependency on its return type nor its parameter | |
264 | * types. For example, the code line <code>bean.method(null);</code> only depends on the owner type of the | |
265 | * method. A direct dependency is only introduced when the code explicitly references the method's types by | |
266 | * means of a variable declaration or a type check/cast. Those cases are handled by other visitor callbacks. | |
267 | */ | |
268 | 16 | } |
269 | ||
270 | /* | |
271 | * @see org.objectweb.asm.MethodVisitor#visitJumpInsn(int, org.objectweb.asm.Label) | |
272 | */ | |
273 | public void visitJumpInsn( final int opcode, final Label label ) | |
274 | { | |
275 | // no-op | |
276 | 1 | } |
277 | ||
278 | /* | |
279 | * @see org.objectweb.asm.MethodVisitor#visitLabel(org.objectweb.asm.Label) | |
280 | */ | |
281 | public void visitLabel( final Label label ) | |
282 | { | |
283 | // no-op | |
284 | 15 | } |
285 | ||
286 | /* | |
287 | * @see org.objectweb.asm.MethodVisitor#visitLdcInsn(java.lang.Object) | |
288 | */ | |
289 | public void visitLdcInsn( final Object cst ) | |
290 | { | |
291 | 3 | if ( cst instanceof Type ) |
292 | { | |
293 | 2 | addType( (Type) cst ); |
294 | } | |
295 | 3 | } |
296 | ||
297 | /* | |
298 | * @see org.objectweb.asm.MethodVisitor#visitIincInsn(int, int) | |
299 | */ | |
300 | public void visitIincInsn( final int var, final int increment ) | |
301 | { | |
302 | // no-op | |
303 | 1 | } |
304 | ||
305 | /* | |
306 | * @see org.objectweb.asm.MethodVisitor#visitTableSwitchInsn(int, int, org.objectweb.asm.Label, | |
307 | * org.objectweb.asm.Label[]) | |
308 | */ | |
309 | public void visitTableSwitchInsn( final int min, final int max, final Label dflt, final Label[] labels ) | |
310 | { | |
311 | // no-op | |
312 | 1 | } |
313 | ||
314 | /* | |
315 | * @see org.objectweb.asm.MethodVisitor#visitLookupSwitchInsn(org.objectweb.asm.Label, int[], | |
316 | * org.objectweb.asm.Label[]) | |
317 | */ | |
318 | public void visitLookupSwitchInsn( final Label dflt, final int[] keys, final Label[] labels ) | |
319 | { | |
320 | // no-op | |
321 | 1 | } |
322 | ||
323 | /* | |
324 | * @see org.objectweb.asm.MethodVisitor#visitMultiANewArrayInsn(java.lang.String, int) | |
325 | */ | |
326 | public void visitMultiANewArrayInsn( final String desc, final int dims ) | |
327 | { | |
328 | 2 | addDesc( desc ); |
329 | 2 | } |
330 | ||
331 | /* | |
332 | * @see org.objectweb.asm.MethodVisitor#visitTryCatchBlock(org.objectweb.asm.Label, org.objectweb.asm.Label, | |
333 | * org.objectweb.asm.Label, java.lang.String) | |
334 | */ | |
335 | public void visitTryCatchBlock( final Label start, final Label end, final Label handler, final String type ) | |
336 | { | |
337 | 2 | addName( type ); |
338 | 2 | } |
339 | ||
340 | /* | |
341 | * @see org.objectweb.asm.MethodVisitor#visitLocalVariable(java.lang.String, java.lang.String, java.lang.String, | |
342 | * org.objectweb.asm.Label, org.objectweb.asm.Label, int) | |
343 | */ | |
344 | public void visitLocalVariable( final String name, final String desc, final String signature, final Label start, | |
345 | final Label end, final int index ) | |
346 | { | |
347 | 12 | if ( signature == null ) |
348 | { | |
349 | 10 | addDesc( desc ); |
350 | } | |
351 | else | |
352 | { | |
353 | 2 | addTypeSignature( signature ); |
354 | } | |
355 | 12 | } |
356 | ||
357 | /* | |
358 | * @see org.objectweb.asm.MethodVisitor#visitLineNumber(int, org.objectweb.asm.Label) | |
359 | */ | |
360 | public void visitLineNumber( final int line, final Label start ) | |
361 | { | |
362 | // no-op | |
363 | 11 | } |
364 | ||
365 | /* | |
366 | * @see org.objectweb.asm.MethodVisitor#visitMaxs(int, int) | |
367 | */ | |
368 | public void visitMaxs( final int maxStack, final int maxLocals ) | |
369 | { | |
370 | // no-op | |
371 | 5 | } |
372 | ||
373 | // AnnotationVisitor methods ---------------------------------------------- | |
374 | ||
375 | /* | |
376 | * @see org.objectweb.asm.AnnotationVisitor#visit(java.lang.String, java.lang.Object) | |
377 | */ | |
378 | public void visit( final String name, final Object value ) | |
379 | { | |
380 | 0 | if ( value instanceof Type ) |
381 | { | |
382 | 0 | addType( (Type) value ); |
383 | } | |
384 | 0 | } |
385 | ||
386 | /* | |
387 | * @see org.objectweb.asm.AnnotationVisitor#visitEnum(java.lang.String, java.lang.String, java.lang.String) | |
388 | */ | |
389 | public void visitEnum( final String name, final String desc, final String value ) | |
390 | { | |
391 | 0 | addDesc( desc ); |
392 | 0 | } |
393 | ||
394 | /* | |
395 | * @see org.objectweb.asm.AnnotationVisitor#visitAnnotation(java.lang.String, java.lang.String) | |
396 | */ | |
397 | public AnnotationVisitor visitAnnotation( final String name, final String desc ) | |
398 | { | |
399 | 0 | addDesc( desc ); |
400 | ||
401 | 0 | return this; |
402 | } | |
403 | ||
404 | /* | |
405 | * @see org.objectweb.asm.AnnotationVisitor#visitArray(java.lang.String) | |
406 | */ | |
407 | public AnnotationVisitor visitArray( final String name ) | |
408 | { | |
409 | 0 | return this; |
410 | } | |
411 | ||
412 | /* | |
413 | * @see org.objectweb.asm.AnnotationVisitor#visitEnd() | |
414 | */ | |
415 | public void visitEnd() | |
416 | { | |
417 | // no-op | |
418 | 32 | } |
419 | ||
420 | // SignatureVisitor methods ----------------------------------------------- | |
421 | ||
422 | /* | |
423 | * @see org.objectweb.asm.signature.SignatureVisitor#visitFormalTypeParameter(java.lang.String) | |
424 | */ | |
425 | public void visitFormalTypeParameter( final String name ) | |
426 | { | |
427 | // no-op | |
428 | 5 | } |
429 | ||
430 | /* | |
431 | * @see org.objectweb.asm.signature.SignatureVisitor#visitClassBound() | |
432 | */ | |
433 | public SignatureVisitor visitClassBound() | |
434 | { | |
435 | 5 | return this; |
436 | } | |
437 | ||
438 | /* | |
439 | * @see org.objectweb.asm.signature.SignatureVisitor#visitInterfaceBound() | |
440 | */ | |
441 | public SignatureVisitor visitInterfaceBound() | |
442 | { | |
443 | 0 | return this; |
444 | } | |
445 | ||
446 | /* | |
447 | * @see org.objectweb.asm.signature.SignatureVisitor#visitSuperclass() | |
448 | */ | |
449 | public SignatureVisitor visitSuperclass() | |
450 | { | |
451 | 5 | return this; |
452 | } | |
453 | ||
454 | /* | |
455 | * @see org.objectweb.asm.signature.SignatureVisitor#visitInterface() | |
456 | */ | |
457 | public SignatureVisitor visitInterface() | |
458 | { | |
459 | 2 | return this; |
460 | } | |
461 | ||
462 | /* | |
463 | * @see org.objectweb.asm.signature.SignatureVisitor#visitParameterType() | |
464 | */ | |
465 | public SignatureVisitor visitParameterType() | |
466 | { | |
467 | 1 | return this; |
468 | } | |
469 | ||
470 | /* | |
471 | * @see org.objectweb.asm.signature.SignatureVisitor#visitReturnType() | |
472 | */ | |
473 | public SignatureVisitor visitReturnType() | |
474 | { | |
475 | 1 | return this; |
476 | } | |
477 | ||
478 | /* | |
479 | * @see org.objectweb.asm.signature.SignatureVisitor#visitExceptionType() | |
480 | */ | |
481 | public SignatureVisitor visitExceptionType() | |
482 | { | |
483 | 0 | return this; |
484 | } | |
485 | ||
486 | /* | |
487 | * @see org.objectweb.asm.signature.SignatureVisitor#visitBaseType(char) | |
488 | */ | |
489 | public void visitBaseType( final char descriptor ) | |
490 | { | |
491 | // no-op | |
492 | 1 | } |
493 | ||
494 | /* | |
495 | * @see org.objectweb.asm.signature.SignatureVisitor#visitTypeVariable(java.lang.String) | |
496 | */ | |
497 | public void visitTypeVariable( final String name ) | |
498 | { | |
499 | // TODO: verify | |
500 | 1 | } |
501 | ||
502 | /* | |
503 | * @see org.objectweb.asm.signature.SignatureVisitor#visitArrayType() | |
504 | */ | |
505 | public SignatureVisitor visitArrayType() | |
506 | { | |
507 | 1 | return this; |
508 | } | |
509 | ||
510 | /* | |
511 | * @see org.objectweb.asm.signature.SignatureVisitor#visitClassType(java.lang.String) | |
512 | */ | |
513 | public void visitClassType( final String name ) | |
514 | { | |
515 | 21 | addName( name ); |
516 | 21 | } |
517 | ||
518 | /* | |
519 | * @see org.objectweb.asm.signature.SignatureVisitor#visitInnerClassType(java.lang.String) | |
520 | */ | |
521 | public void visitInnerClassType( final String name ) | |
522 | { | |
523 | 0 | addName( name ); |
524 | 0 | } |
525 | ||
526 | /* | |
527 | * @see org.objectweb.asm.signature.SignatureVisitor#visitTypeArgument() | |
528 | */ | |
529 | public void visitTypeArgument() | |
530 | { | |
531 | // no-op | |
532 | 0 | } |
533 | ||
534 | /* | |
535 | * @see org.objectweb.asm.signature.SignatureVisitor#visitTypeArgument(char) | |
536 | */ | |
537 | public SignatureVisitor visitTypeArgument( final char wildcard ) | |
538 | { | |
539 | 6 | return this; |
540 | } | |
541 | ||
542 | // public methods --------------------------------------------------------- | |
543 | ||
544 | public Set<String> getClasses() | |
545 | { | |
546 | 77 | return classes; |
547 | } | |
548 | ||
549 | // private methods -------------------------------------------------------- | |
550 | ||
551 | private void addName( String name ) | |
552 | { | |
553 | 81 | if ( name == null ) |
554 | { | |
555 | 1 | return; |
556 | } | |
557 | ||
558 | // decode arrays | |
559 | 80 | if ( name.startsWith( "[L" ) && name.endsWith( ";" ) ) |
560 | { | |
561 | 0 | name = name.substring( 2, name.length() - 1 ); |
562 | } | |
563 | ||
564 | // decode internal representation | |
565 | 80 | name = name.replace( '/', '.' ); |
566 | ||
567 | 80 | classes.add( name ); |
568 | 80 | } |
569 | ||
570 | private void addNames( final String[] names ) | |
571 | { | |
572 | 25 | if ( names == null ) |
573 | { | |
574 | 17 | return; |
575 | } | |
576 | ||
577 | 14 | for ( String name : names ) |
578 | { | |
579 | 6 | addName( name ); |
580 | } | |
581 | 8 | } |
582 | ||
583 | private void addDesc( final String desc ) | |
584 | { | |
585 | 20 | addType( Type.getType( desc ) ); |
586 | 20 | } |
587 | ||
588 | private void addMethodDesc( final String desc ) | |
589 | { | |
590 | 16 | addType( Type.getReturnType( desc ) ); |
591 | ||
592 | 16 | Type[] types = Type.getArgumentTypes( desc ); |
593 | ||
594 | 22 | for ( Type type : types ) |
595 | { | |
596 | 6 | addType( type ); |
597 | } | |
598 | 16 | } |
599 | ||
600 | private void addType( final Type t ) | |
601 | { | |
602 | 51 | switch ( t.getSort() ) |
603 | { | |
604 | case Type.ARRAY: | |
605 | 7 | addType( t.getElementType() ); |
606 | 7 | break; |
607 | ||
608 | case Type.OBJECT: | |
609 | 23 | addName( t.getClassName().replace( '.', '/' ) ); |
610 | break; | |
611 | } | |
612 | 51 | } |
613 | ||
614 | private void addSignature( final String signature ) | |
615 | { | |
616 | 6 | if ( signature != null ) |
617 | { | |
618 | 6 | new SignatureReader( signature ).accept( this ); |
619 | } | |
620 | 6 | } |
621 | ||
622 | private void addTypeSignature( final String signature ) | |
623 | { | |
624 | 3 | if ( signature != null ) |
625 | { | |
626 | 3 | new SignatureReader( signature ).acceptType( this ); |
627 | } | |
628 | 3 | } |
629 | } |