1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21package proguard.classfile.visitor;
22
23import proguard.classfile.*;
24import proguard.classfile.attribute.*;
25import proguard.classfile.attribute.annotation.*;
26import proguard.classfile.attribute.annotation.target.*;
27import proguard.classfile.attribute.annotation.target.visitor.*;
28import proguard.classfile.attribute.annotation.visitor.*;
29import proguard.classfile.attribute.preverification.*;
30import proguard.classfile.attribute.preverification.visitor.*;
31import proguard.classfile.attribute.visitor.*;
32import proguard.classfile.constant.*;
33import proguard.classfile.constant.visitor.ConstantVisitor;
34import proguard.classfile.instruction.*;
35import proguard.classfile.instruction.visitor.InstructionVisitor;
36import proguard.classfile.util.*;
37
38import java.io.PrintStream;
39
40
41/**
42 * This <code>ClassVisitor</code> prints out the complete internal
43 * structure of the classes it visits.
44 *
45 * @author Eric Lafortune
46 */
47public class ClassPrinter
48extends      SimplifiedVisitor
49implements   ClassVisitor,
50             ConstantVisitor,
51             MemberVisitor,
52             AttributeVisitor,
53             BootstrapMethodInfoVisitor,
54             InnerClassesInfoVisitor,
55             ExceptionInfoVisitor,
56             StackMapFrameVisitor,
57             VerificationTypeVisitor,
58             LineNumberInfoVisitor,
59             ParameterInfoVisitor,
60             LocalVariableInfoVisitor,
61             LocalVariableTypeInfoVisitor,
62             AnnotationVisitor,
63             TypeAnnotationVisitor,
64             TargetInfoVisitor,
65             LocalVariableTargetElementVisitor,
66             TypePathInfoVisitor,
67             ElementValueVisitor,
68             InstructionVisitor
69{
70    private static final String INDENTATION = "  ";
71
72    private final PrintStream ps;
73
74    private int indentation;
75
76
77    /**
78     * Creates a new ClassPrinter that prints to <code>System.out</code>.
79     */
80    public ClassPrinter()
81    {
82        this(System.out);
83    }
84
85
86    /**
87     * Creates a new ClassPrinter that prints to the given
88     * <code>PrintStream</code>.
89     */
90    public ClassPrinter(PrintStream printStream)
91    {
92        ps = printStream;
93    }
94
95
96    // Implementations for ClassVisitor.
97
98    public void visitProgramClass(ProgramClass programClass)
99    {
100        println("_____________________________________________________________________");
101        println(visitorInfo(programClass) + " " +
102                "Program class: " + programClass.getName());
103        indent();
104        println("Superclass:    " + programClass.getSuperName());
105        println("Major version: 0x" + Integer.toHexString(ClassUtil.internalMajorClassVersion(programClass.u4version)));
106        println("Minor version: 0x" + Integer.toHexString(ClassUtil.internalMinorClassVersion(programClass.u4version)));
107        println("  = target " + ClassUtil.externalClassVersion(programClass.u4version));
108        println("Access flags:  0x" + Integer.toHexString(programClass.u2accessFlags));
109        println("  = " +
110                ((programClass.u2accessFlags & ClassConstants.ACC_ANNOTATTION) != 0 ? "@ " : "") +
111                ClassUtil.externalClassAccessFlags(programClass.u2accessFlags) +
112                ((programClass.u2accessFlags & ClassConstants.ACC_ENUM)      != 0 ? "enum " :
113                 (programClass.u2accessFlags & ClassConstants.ACC_INTERFACE) == 0 ? "class " :
114                                                                                             "") +
115                ClassUtil.externalClassName(programClass.getName()) +
116                (programClass.u2superClass == 0 ? "" : " extends " +
117                ClassUtil.externalClassName(programClass.getSuperName())));
118        outdent();
119        println();
120
121        println("Interfaces (count = " + programClass.u2interfacesCount + "):");
122        indent();
123        programClass.interfaceConstantsAccept(this);
124        outdent();
125        println();
126
127        println("Constant Pool (count = " + programClass.u2constantPoolCount + "):");
128        indent();
129        programClass.constantPoolEntriesAccept(this);
130        outdent();
131        println();
132
133        println("Fields (count = " + programClass.u2fieldsCount + "):");
134        indent();
135        programClass.fieldsAccept(this);
136        outdent();
137        println();
138
139        println("Methods (count = " + programClass.u2methodsCount + "):");
140        indent();
141        programClass.methodsAccept(this);
142        outdent();
143        println();
144
145        println("Class file attributes (count = " + programClass.u2attributesCount + "):");
146        indent();
147        programClass.attributesAccept(this);
148        outdent();
149        println();
150    }
151
152
153    public void visitLibraryClass(LibraryClass libraryClass)
154    {
155        println("_____________________________________________________________________");
156        println(visitorInfo(libraryClass) + " " +
157                "Library class: " + libraryClass.getName());
158        indent();
159        println("Superclass:    " + libraryClass.getSuperName());
160        println("Access flags:  0x" + Integer.toHexString(libraryClass.u2accessFlags));
161        println("  = " +
162                ((libraryClass.u2accessFlags & ClassConstants.ACC_ANNOTATTION) != 0 ? "@ " : "") +
163                ClassUtil.externalClassAccessFlags(libraryClass.u2accessFlags) +
164                ((libraryClass.u2accessFlags & ClassConstants.ACC_ENUM)      != 0 ? "enum " :
165                 (libraryClass.u2accessFlags & ClassConstants.ACC_INTERFACE) == 0 ? "class " :
166                                                                                             "") +
167                ClassUtil.externalClassName(libraryClass.getName()) +
168                (libraryClass.getSuperName() == null ? "" : " extends "  +
169                ClassUtil.externalClassName(libraryClass.getSuperName())));
170        outdent();
171        println();
172
173        println("Interfaces (count = " + libraryClass.interfaceClasses.length + "):");
174        for (int index = 0; index < libraryClass.interfaceClasses.length; index++)
175        {
176            Clazz interfaceClass = libraryClass.interfaceClasses[index];
177            if (interfaceClass != null)
178            {
179                println("  + " + interfaceClass.getName());
180            }
181        }
182
183        println("Fields (count = " + libraryClass.fields.length + "):");
184        libraryClass.fieldsAccept(this);
185
186        println("Methods (count = " + libraryClass.methods.length + "):");
187        libraryClass.methodsAccept(this);
188    }
189
190
191    // Implementations for ConstantVisitor.
192
193    public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
194    {
195        println(visitorInfo(integerConstant) + " Integer [" +
196                integerConstant.getValue() + "]");
197    }
198
199
200    public void visitLongConstant(Clazz clazz, LongConstant longConstant)
201    {
202        println(visitorInfo(longConstant) + " Long [" +
203                longConstant.getValue() + "]");
204    }
205
206
207    public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
208    {
209        println(visitorInfo(floatConstant) + " Float [" +
210                floatConstant.getValue() + "]");
211    }
212
213
214    public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
215    {
216        println(visitorInfo(doubleConstant) + " Double [" +
217                doubleConstant.getValue() + "]");
218    }
219
220
221    public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
222    {
223        println(visitorInfo(stringConstant) + " String [" +
224                stringConstant.getString(clazz) + "]");
225    }
226
227
228    public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
229    {
230        println(visitorInfo(utf8Constant) + " Utf8 [" +
231                utf8Constant.getString() + "]");
232    }
233
234
235    public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
236    {
237        println(visitorInfo(invokeDynamicConstant) + " InvokeDynamic [bootstrap method index = " + invokeDynamicConstant.u2bootstrapMethodAttributeIndex + "]:");
238
239        indent();
240        clazz.constantPoolEntryAccept(invokeDynamicConstant.u2nameAndTypeIndex, this);
241        outdent();
242    }
243
244
245    public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
246    {
247        println(visitorInfo(methodHandleConstant) + " MethodHandle [kind = " + methodHandleConstant.u1referenceKind + "]:");
248
249        indent();
250        clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
251        outdent();
252    }
253
254
255    public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
256    {
257        println(visitorInfo(fieldrefConstant) + " Fieldref [" +
258                clazz.getClassName(fieldrefConstant.u2classIndex) + "." +
259                clazz.getName(fieldrefConstant.u2nameAndTypeIndex) + " " +
260                clazz.getType(fieldrefConstant.u2nameAndTypeIndex) + "]");
261    }
262
263
264    public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
265    {
266        println(visitorInfo(interfaceMethodrefConstant) + " InterfaceMethodref [" +
267                clazz.getClassName(interfaceMethodrefConstant.u2classIndex)  + "." +
268                clazz.getName(interfaceMethodrefConstant.u2nameAndTypeIndex) + " " +
269                clazz.getType(interfaceMethodrefConstant.u2nameAndTypeIndex) + "]");
270    }
271
272
273    public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
274    {
275        println(visitorInfo(methodrefConstant) + " Methodref [" +
276                clazz.getClassName(methodrefConstant.u2classIndex)  + "." +
277                clazz.getName(methodrefConstant.u2nameAndTypeIndex) + " " +
278                clazz.getType(methodrefConstant.u2nameAndTypeIndex) + "]");
279    }
280
281
282    public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
283    {
284        println(visitorInfo(classConstant) + " Class [" +
285                classConstant.getName(clazz) + "]");
286    }
287
288
289    public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
290    {
291        println(visitorInfo(methodTypeConstant) + " MethodType [" +
292                methodTypeConstant.getType(clazz) + "]");
293    }
294
295
296    public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
297    {
298        println(visitorInfo(nameAndTypeConstant) + " NameAndType [" +
299                nameAndTypeConstant.getName(clazz) + " " +
300                nameAndTypeConstant.getType(clazz) + "]");
301    }
302
303
304    // Implementations for MemberVisitor.
305
306    public void visitProgramField(ProgramClass programClass, ProgramField programField)
307    {
308        println(visitorInfo(programField) + " " +
309                "Field:        " +
310                programField.getName(programClass) + " " +
311                programField.getDescriptor(programClass));
312
313        indent();
314        println("Access flags: 0x" + Integer.toHexString(programField.u2accessFlags));
315        println("  = " +
316                ClassUtil.externalFullFieldDescription(programField.u2accessFlags,
317                                                       programField.getName(programClass),
318                                                       programField.getDescriptor(programClass)));
319
320        visitMember(programClass, programField);
321        outdent();
322    }
323
324
325    public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
326    {
327        println(visitorInfo(programMethod) + " " +
328                "Method:       " +
329                programMethod.getName(programClass) +
330                programMethod.getDescriptor(programClass));
331
332        indent();
333        println("Access flags: 0x" + Integer.toHexString(programMethod.u2accessFlags));
334        println("  = " +
335                ClassUtil.externalFullMethodDescription(programClass.getName(),
336                                                        programMethod.u2accessFlags,
337                                                        programMethod.getName(programClass),
338                                                        programMethod.getDescriptor(programClass)));
339
340        visitMember(programClass, programMethod);
341        outdent();
342    }
343
344
345    private void visitMember(ProgramClass programClass, ProgramMember programMember)
346    {
347        if (programMember.u2attributesCount > 0)
348        {
349            println("Class member attributes (count = " + programMember.u2attributesCount + "):");
350            programMember.attributesAccept(programClass, this);
351        }
352    }
353
354
355    public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
356    {
357        println(visitorInfo(libraryField) + " " +
358                "Field:        " +
359                libraryField.getName(libraryClass) + " " +
360                libraryField.getDescriptor(libraryClass));
361
362        indent();
363        println("Access flags: 0x" + Integer.toHexString(libraryField.u2accessFlags));
364        println("  = " +
365                ClassUtil.externalFullFieldDescription(libraryField.u2accessFlags,
366                                                       libraryField.getName(libraryClass),
367                                                       libraryField.getDescriptor(libraryClass)));
368        outdent();
369    }
370
371
372    public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
373    {
374        println(visitorInfo(libraryMethod) + " " +
375                "Method:       " +
376                libraryMethod.getName(libraryClass) + " " +
377                libraryMethod.getDescriptor(libraryClass));
378
379        indent();
380        println("Access flags: 0x" + Integer.toHexString(libraryMethod.u2accessFlags));
381        println("  = " +
382                ClassUtil.externalFullMethodDescription(libraryClass.getName(),
383                                                        libraryMethod.u2accessFlags,
384                                                        libraryMethod.getName(libraryClass),
385                                                        libraryMethod.getDescriptor(libraryClass)));
386        outdent();
387    }
388
389
390    // Implementations for AttributeVisitor.
391    // Note that attributes are typically only referenced once, so we don't
392    // test if they are marked already.
393
394    public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
395    {
396        println(visitorInfo(unknownAttribute) +
397                " Unknown attribute (" + unknownAttribute.getAttributeName(clazz) + ")");
398    }
399
400
401    public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
402    {
403        println(visitorInfo(bootstrapMethodsAttribute) +
404                " Bootstrap methods attribute (count = " + bootstrapMethodsAttribute.u2bootstrapMethodsCount + "):");
405
406        indent();
407        bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
408        outdent();
409    }
410
411
412    public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
413    {
414        println(visitorInfo(sourceFileAttribute) +
415                " Source file attribute:");
416
417        indent();
418        clazz.constantPoolEntryAccept(sourceFileAttribute.u2sourceFileIndex, this);
419        outdent();
420    }
421
422
423    public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
424    {
425        println(visitorInfo(sourceDirAttribute) +
426                " Source dir attribute:");
427
428        indent();
429        clazz.constantPoolEntryAccept(sourceDirAttribute.u2sourceDirIndex, this);
430        outdent();
431    }
432
433
434    public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
435    {
436        println(visitorInfo(innerClassesAttribute) +
437                " Inner classes attribute (count = " + innerClassesAttribute.u2classesCount + ")");
438
439        indent();
440        innerClassesAttribute.innerClassEntriesAccept(clazz, this);
441        outdent();
442    }
443
444
445    public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
446    {
447        println(visitorInfo(enclosingMethodAttribute) +
448                " Enclosing method attribute:");
449
450        indent();
451        clazz.constantPoolEntryAccept(enclosingMethodAttribute.u2classIndex, this);
452
453        if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
454        {
455            clazz.constantPoolEntryAccept(enclosingMethodAttribute.u2nameAndTypeIndex, this);
456        }
457        outdent();
458    }
459
460
461    public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
462    {
463        println(visitorInfo(deprecatedAttribute) +
464                " Deprecated attribute");
465    }
466
467
468    public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
469    {
470        println(visitorInfo(syntheticAttribute) +
471                " Synthetic attribute");
472    }
473
474
475    public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
476    {
477        println(visitorInfo(signatureAttribute) +
478                " Signature attribute:");
479
480        indent();
481        clazz.constantPoolEntryAccept(signatureAttribute.u2signatureIndex, this);
482        outdent();
483    }
484
485
486    public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
487    {
488        println(visitorInfo(constantValueAttribute) +
489                " Constant value attribute:");
490
491        clazz.constantPoolEntryAccept(constantValueAttribute.u2constantValueIndex, this);
492    }
493
494
495    public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
496    {
497        println(visitorInfo(methodParametersAttribute) +
498                " Method parameters attribute (count = " + methodParametersAttribute.u1parametersCount + ")");
499
500        indent();
501        methodParametersAttribute.parametersAccept(clazz, method, this);
502        outdent();
503    }
504
505
506    public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
507    {
508        println(visitorInfo(exceptionsAttribute) +
509                " Exceptions attribute (count = " + exceptionsAttribute.u2exceptionIndexTableLength + ")");
510
511        indent();
512        exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, this);
513        outdent();
514    }
515
516
517    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
518    {
519        println(visitorInfo(codeAttribute) +
520                " Code attribute instructions (code length = "+ codeAttribute.u4codeLength +
521                ", locals = "+ codeAttribute.u2maxLocals +
522                ", stack = "+ codeAttribute.u2maxStack + "):");
523
524        indent();
525
526        codeAttribute.instructionsAccept(clazz, method, this);
527
528        println("Code attribute exceptions (count = " +
529                codeAttribute.u2exceptionTableLength + "):");
530
531        codeAttribute.exceptionsAccept(clazz, method, this);
532
533        println("Code attribute attributes (attribute count = " +
534                codeAttribute.u2attributesCount + "):");
535
536        codeAttribute.attributesAccept(clazz, method, this);
537
538        outdent();
539    }
540
541
542    public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
543    {
544        println(visitorInfo(codeAttribute) +
545                " Stack map attribute (count = "+
546                stackMapAttribute.u2stackMapFramesCount + "):");
547
548        indent();
549        stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
550        outdent();
551    }
552
553
554    public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
555    {
556        println(visitorInfo(codeAttribute) +
557                " Stack map table attribute (count = "+
558                stackMapTableAttribute.u2stackMapFramesCount + "):");
559
560        indent();
561        stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
562        outdent();
563    }
564
565
566    public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
567    {
568        println(visitorInfo(lineNumberTableAttribute) +
569                " Line number table attribute (count = " +
570                lineNumberTableAttribute.u2lineNumberTableLength + ")");
571
572        indent();
573        lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);
574        outdent();
575    }
576
577
578    public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
579    {
580        println(visitorInfo(localVariableTableAttribute) +
581                " Local variable table attribute (count = " +
582                localVariableTableAttribute.u2localVariableTableLength + ")");
583
584        indent();
585        localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
586        outdent();
587    }
588
589
590    public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
591    {
592        println(visitorInfo(localVariableTypeTableAttribute) +
593                " Local variable type table attribute (count = "+
594                localVariableTypeTableAttribute.u2localVariableTypeTableLength + ")");
595
596        indent();
597        localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
598        outdent();
599    }
600
601
602    public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
603    {
604        println(visitorInfo(runtimeVisibleAnnotationsAttribute) +
605                " Runtime visible annotations attribute:");
606
607        indent();
608        runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, this);
609        outdent();
610    }
611
612
613    public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
614    {
615        println(visitorInfo(runtimeInvisibleAnnotationsAttribute) +
616                " Runtime invisible annotations attribute:");
617
618        indent();
619        runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, this);
620        outdent();
621    }
622
623
624    public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)
625    {
626        println(visitorInfo(runtimeVisibleParameterAnnotationsAttribute) +
627                " Runtime visible parameter annotations attribute (parameter count = " + runtimeVisibleParameterAnnotationsAttribute.u1parametersCount + "):");
628
629        indent();
630        runtimeVisibleParameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
631        outdent();
632    }
633
634
635    public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)
636    {
637        println(visitorInfo(runtimeInvisibleParameterAnnotationsAttribute) +
638                " Runtime invisible parameter annotations attribute (parameter count = " + runtimeInvisibleParameterAnnotationsAttribute.u1parametersCount + "):");
639
640        indent();
641        runtimeInvisibleParameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
642        outdent();
643    }
644
645
646    public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
647    {
648        println(visitorInfo(runtimeVisibleTypeAnnotationsAttribute) +
649                " Runtime visible type annotations attribute");
650
651        indent();
652        runtimeVisibleTypeAnnotationsAttribute.typeAnnotationsAccept(clazz, this);
653        outdent();
654    }
655
656
657    public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
658    {
659        println(visitorInfo(runtimeInvisibleTypeAnnotationsAttribute) +
660                " Runtime invisible type annotations attribute");
661
662        indent();
663        runtimeInvisibleTypeAnnotationsAttribute.typeAnnotationsAccept(clazz, this);
664        outdent();
665    }
666
667
668    public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
669    {
670        println(visitorInfo(annotationDefaultAttribute) +
671                " Annotation default attribute:");
672
673        indent();
674        annotationDefaultAttribute.defaultValueAccept(clazz, this);
675        outdent();
676    }
677
678
679    // Implementations for BootstrapMethodInfoVisitor.
680
681    public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
682    {
683        println(visitorInfo(bootstrapMethodInfo) +
684                " BootstrapMethodInfo (argument count = " +
685                bootstrapMethodInfo.u2methodArgumentCount+ "):");
686
687        indent();
688        clazz.constantPoolEntryAccept(bootstrapMethodInfo.u2methodHandleIndex, this);
689        bootstrapMethodInfo.methodArgumentsAccept(clazz, this);
690        outdent();
691    }
692
693
694    // Implementations for InnerClassesInfoVisitor.
695
696    public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
697    {
698        println(visitorInfo(innerClassesInfo) +
699                " InnerClassesInfo:");
700
701        indent();
702        println("Access flags:  0x" + Integer.toHexString(innerClassesInfo.u2innerClassAccessFlags) + " = " +
703                ClassUtil.externalClassAccessFlags(innerClassesInfo.u2innerClassAccessFlags));
704        innerClassesInfo.innerClassConstantAccept(clazz, this);
705        innerClassesInfo.outerClassConstantAccept(clazz, this);
706        innerClassesInfo.innerNameConstantAccept(clazz, this);
707        outdent();
708    }
709
710
711    // Implementations for InstructionVisitor.
712
713    public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
714    {
715        println(instruction.toString(offset));
716    }
717
718
719    public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
720    {
721        println(constantInstruction.toString(offset));
722
723        indent();
724        clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
725        outdent();
726    }
727
728
729    public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
730    {
731        println(tableSwitchInstruction.toString(offset));
732
733        indent();
734
735        int[] jumpOffsets = tableSwitchInstruction.jumpOffsets;
736
737        for (int index = 0; index < jumpOffsets.length; index++)
738        {
739            int jumpOffset = jumpOffsets[index];
740            println(Integer.toString(tableSwitchInstruction.lowCase + index)  + ": offset = " + jumpOffset + ", target = " + (offset + jumpOffset));
741        }
742
743        int defaultOffset = tableSwitchInstruction.defaultOffset;
744        println("default: offset = " + defaultOffset + ", target = "+ (offset + defaultOffset));
745
746        outdent();
747    }
748
749
750    public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
751    {
752        println(lookUpSwitchInstruction.toString(offset));
753
754        indent();
755
756        int[] cases       = lookUpSwitchInstruction.cases;
757        int[] jumpOffsets = lookUpSwitchInstruction.jumpOffsets;
758
759        for (int index = 0; index < jumpOffsets.length; index++)
760        {
761            int jumpOffset = jumpOffsets[index];
762            println(Integer.toString(cases[index])  + ": offset = " + jumpOffset + ", target = " + (offset + jumpOffset));
763        }
764
765        int defaultOffset = lookUpSwitchInstruction.defaultOffset;
766        println("default: offset = " + defaultOffset + ", target = "+ (offset + defaultOffset));
767
768        outdent();
769    }
770
771
772    // Implementations for ExceptionInfoVisitor.
773
774    public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
775    {
776        println(visitorInfo(exceptionInfo) +
777                " ExceptionInfo (" +
778                exceptionInfo.u2startPC + " -> " +
779                exceptionInfo.u2endPC + ": " +
780                exceptionInfo.u2handlerPC + "):");
781
782        if (exceptionInfo.u2catchType != 0)
783        {
784            clazz.constantPoolEntryAccept(exceptionInfo.u2catchType, this);
785        }
786    }
787
788
789    // Implementations for StackMapFrameVisitor.
790
791    public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame)
792    {
793        println(visitorInfo(sameZeroFrame) +
794                " [" + offset  + "]" +
795                " Var: ..., Stack: (empty)");
796    }
797
798
799    public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
800    {
801        print(visitorInfo(sameOneFrame) +
802              " [" + offset  + "]" +
803              " Var: ..., Stack: ");
804
805        sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
806
807        println();
808    }
809
810
811    public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame)
812    {
813        println(visitorInfo(lessZeroFrame) +
814                " [" + offset  + "]" +
815                " Var: -" + lessZeroFrame.choppedVariablesCount +
816                ", Stack: (empty)");
817    }
818
819
820    public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
821    {
822        print(visitorInfo(moreZeroFrame) +
823              " [" + offset  + "]" +
824              " Var: ...");
825
826        moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
827
828        ps.println(", Stack: (empty)");
829    }
830
831
832    public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
833    {
834        print(visitorInfo(fullFrame) +
835              " [" + offset  + "]" +
836              " Var: ");
837
838        fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
839
840        ps.print(", Stack: ");
841
842        fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
843
844        println();
845    }
846
847
848    // Implementations for VerificationTypeVisitor.
849
850    public void visitIntegerType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, IntegerType integerType)
851    {
852        ps.print("[i]");
853    }
854
855
856    public void visitFloatType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FloatType floatType)
857    {
858        ps.print("[f]");
859    }
860
861
862    public void visitLongType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LongType longType)
863    {
864        ps.print("[l]");
865    }
866
867
868    public void visitDoubleType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, DoubleType doubleType)
869    {
870        ps.print("[d]");
871    }
872
873
874    public void visitTopType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TopType topType)
875    {
876        ps.print("[T]");
877    }
878
879
880    public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
881    {
882        ps.print("[a:" + clazz.getClassName(objectType.u2classIndex) + "]");
883    }
884
885
886    public void visitNullType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, NullType nullType)
887    {
888        ps.print("[n]");
889    }
890
891
892    public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
893    {
894        ps.print("[u:" + uninitializedType.u2newInstructionOffset + "]");
895    }
896
897
898    public void visitUninitializedThisType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedThisType uninitializedThisType)
899    {
900        ps.print("[u:this]");
901    }
902
903
904    // Implementations for LineNumberInfoVisitor.
905
906    public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
907    {
908        println("[" + lineNumberInfo.u2startPC + "] -> line " +
909                lineNumberInfo.u2lineNumber);
910    }
911
912
913    // Implementations for ParameterInfoVisitor.
914
915    public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)
916    {
917        println("p" + parameterIndex + ":  Access flags: 0x" + Integer.toHexString(parameterInfo.u2accessFlags) + " = " +
918                ClassUtil.externalParameterAccessFlags(parameterInfo.u2accessFlags) + " [" +
919                (parameterInfo.u2nameIndex == 0 ? "" : parameterInfo.getName(clazz)) + "]");
920    }
921
922
923    // Implementations for LocalVariableInfoVisitor.
924
925    public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
926    {
927        println("v" + localVariableInfo.u2index + ": " +
928                localVariableInfo.u2startPC + " -> " +
929                (localVariableInfo.u2startPC + localVariableInfo.u2length) + " [" +
930                localVariableInfo.getDescriptor(clazz) + " " +
931                localVariableInfo.getName(clazz) + "]");
932    }
933
934
935    // Implementations for LocalVariableTypeInfoVisitor.
936
937    public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
938    {
939        println("v" + localVariableTypeInfo.u2index + ": " +
940                localVariableTypeInfo.u2startPC + " -> " +
941                (localVariableTypeInfo.u2startPC + localVariableTypeInfo.u2length) + " [" +
942                localVariableTypeInfo.getSignature(clazz) + " " +
943                localVariableTypeInfo.getName(clazz) + "]");
944    }
945
946
947    // Implementations for AnnotationVisitor.
948
949    public void visitAnnotation(Clazz clazz, Annotation annotation)
950    {
951        println(visitorInfo(annotation) +
952                " Annotation [" + annotation.getType(clazz) + "]:");
953
954        indent();
955        annotation.elementValuesAccept(clazz, this);
956        outdent();
957    }
958
959
960    // Implementations for TypeAnnotationVisitor.
961
962    public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation)
963    {
964        println(visitorInfo(typeAnnotation) +
965                " Type annotation [" + typeAnnotation.getType(clazz) + "]:");
966
967        indent();
968        typeAnnotation.targetInfoAccept(clazz, this);
969
970        println("Type path (count = " + typeAnnotation.typePath.length + "):");
971        indent();
972        typeAnnotation.typePathInfosAccept(clazz, this);
973        outdent();
974
975        typeAnnotation.elementValuesAccept(clazz, this);
976
977        outdent();
978    }
979
980
981    // Implementations for TargetInfoVisitor.
982
983    public void visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo)
984    {
985        println("Target (type = 0x" + Integer.toHexString(typeParameterTargetInfo.u1targetType) + "): Parameter #" +
986                typeParameterTargetInfo.u1typeParameterIndex);
987    }
988
989
990    public void visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo)
991    {
992        println("Target (type = 0x" + Integer.toHexString(superTypeTargetInfo.u1targetType) + "): " +
993                (superTypeTargetInfo.u2superTypeIndex == 0xffff ?
994                     "super class" :
995                     "interface #" + superTypeTargetInfo.u2superTypeIndex));
996    }
997
998
999    public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo)
1000    {
1001        println("Target (type = 0x" + Integer.toHexString(typeParameterBoundTargetInfo.u1targetType) + "): parameter #" +
1002                typeParameterBoundTargetInfo.u1typeParameterIndex + ", bound #" + typeParameterBoundTargetInfo.u1boundIndex);
1003    }
1004
1005
1006    public void visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo)
1007    {
1008        println("Target (type = 0x" + Integer.toHexString(emptyTargetInfo.u1targetType) + ")");
1009    }
1010
1011
1012    public void visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo)
1013    {
1014        println("Target (type = 0x" + Integer.toHexString(formalParameterTargetInfo.u1targetType) + "): formal parameter #" +
1015                formalParameterTargetInfo.u1formalParameterIndex);
1016    }
1017
1018
1019    public void visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo)
1020    {
1021        println("Target (type = 0x" + Integer.toHexString(throwsTargetInfo.u1targetType) + "): throws #" +
1022                throwsTargetInfo.u2throwsTypeIndex);
1023    }
1024
1025
1026    public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo)
1027    {
1028        println("Target (type = 0x" + Integer.toHexString(localVariableTargetInfo.u1targetType) + "): local variables (count = " +
1029                localVariableTargetInfo.u2tableLength + ")");
1030
1031        indent();
1032        localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this);
1033        outdent();
1034    }
1035
1036
1037    public void visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo)
1038    {
1039        println("Target (type = 0x" + Integer.toHexString(catchTargetInfo.u1targetType) + "): catch #" +
1040                catchTargetInfo.u2exceptionTableIndex);
1041    }
1042
1043
1044    public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo)
1045    {
1046        println("Target (type = 0x" + Integer.toHexString(offsetTargetInfo.u1targetType) + "): offset " +
1047                offsetTargetInfo.u2offset);
1048    }
1049
1050
1051    public void visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo)
1052    {
1053        println("Target (type = 0x" + Integer.toHexString(typeArgumentTargetInfo.u1targetType) + "): offset " +
1054                typeArgumentTargetInfo.u2offset + ", type argument " +
1055                typeArgumentTargetInfo.u1typeArgumentIndex);
1056    }
1057
1058
1059    // Implementations for TypePathInfoVisitor.
1060
1061    public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo)
1062    {
1063        println("kind = " +
1064                typePathInfo.u1typePathKind + ", argument index = " +
1065                typePathInfo.u1typeArgumentIndex);
1066    }
1067
1068
1069    // Implementations for LocalVariableTargetElementVisitor.
1070
1071    public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement)
1072    {
1073        println("v" +
1074                localVariableTargetElement.u2index + ": " +
1075                localVariableTargetElement.u2startPC + " -> " +
1076                (localVariableTargetElement.u2startPC + localVariableTargetElement.u2length));
1077    }
1078
1079
1080    // Implementations for ElementValueVisitor.
1081
1082    public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
1083    {
1084        println(visitorInfo(constantElementValue) +
1085                " Constant element value [" +
1086                (constantElementValue.u2elementNameIndex == 0 ? "(default)" :
1087                constantElementValue.getMethodName(clazz)) + " '" +
1088                constantElementValue.u1tag + "']");
1089
1090        indent();
1091        clazz.constantPoolEntryAccept(constantElementValue.u2constantValueIndex, this);
1092        outdent();
1093    }
1094
1095
1096    public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
1097    {
1098        println(visitorInfo(enumConstantElementValue) +
1099                " Enum constant element value [" +
1100                (enumConstantElementValue.u2elementNameIndex == 0 ? "(default)" :
1101                enumConstantElementValue.getMethodName(clazz)) + ", " +
1102                enumConstantElementValue.getTypeName(clazz)  + ", " +
1103                enumConstantElementValue.getConstantName(clazz) + "]");
1104    }
1105
1106
1107    public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
1108    {
1109        println(visitorInfo(classElementValue) +
1110                " Class element value [" +
1111                (classElementValue.u2elementNameIndex == 0 ? "(default)" :
1112                classElementValue.getMethodName(clazz)) + ", " +
1113                classElementValue.getClassName(clazz) + "]");
1114    }
1115
1116
1117    public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
1118    {
1119        println(visitorInfo(annotationElementValue) +
1120                " Annotation element value [" +
1121                (annotationElementValue.u2elementNameIndex == 0 ? "(default)" :
1122                annotationElementValue.getMethodName(clazz)) + "]:");
1123
1124        indent();
1125        annotationElementValue.annotationAccept(clazz, this);
1126        outdent();
1127    }
1128
1129
1130    public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
1131    {
1132        println(visitorInfo(arrayElementValue) +
1133                " Array element value [" +
1134                (arrayElementValue.u2elementNameIndex == 0 ? "(default)" :
1135                arrayElementValue.getMethodName(clazz)) + "]:");
1136
1137        indent();
1138        arrayElementValue.elementValuesAccept(clazz, annotation, this);
1139        outdent();
1140    }
1141
1142
1143    // Small utility methods.
1144
1145    private void indent()
1146    {
1147        indentation++;
1148    }
1149
1150    private void outdent()
1151    {
1152        indentation--;
1153    }
1154
1155    private void println(String string)
1156    {
1157        print(string);
1158        println();
1159
1160    }
1161
1162    private void print(String string)
1163    {
1164        for (int index = 0; index < indentation; index++)
1165        {
1166            ps.print(INDENTATION);
1167        }
1168
1169        ps.print(string);
1170    }
1171
1172    private void println()
1173    {
1174        ps.println();
1175    }
1176
1177
1178    private String visitorInfo(VisitorAccepter visitorAccepter)
1179    {
1180        return visitorAccepter.getVisitorInfo() == null ? "-" : "+";
1181    }
1182}
1183