KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > source > usages > SymbolDumper


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.java.source.usages;
20
21 import com.sun.tools.javac.code.Flags;
22 import com.sun.tools.javac.code.Symbol;
23 import com.sun.tools.javac.code.Type;
24 import com.sun.tools.javac.code.Types;
25 import java.io.PrintWriter JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.Map.Entry;
28 import java.util.logging.Logger JavaDoc;
29 import javax.lang.model.element.AnnotationMirror;
30 import javax.lang.model.element.AnnotationValue;
31 import javax.lang.model.element.Element;
32 import javax.lang.model.element.ElementKind;
33 import javax.lang.model.element.ExecutableElement;
34 import javax.lang.model.element.Modifier;
35 import javax.lang.model.element.TypeElement;
36 import javax.lang.model.element.TypeParameterElement;
37 import javax.lang.model.element.VariableElement;
38 import javax.lang.model.type.ArrayType;
39 import javax.lang.model.type.DeclaredType;
40 import javax.lang.model.type.ErrorType;
41 import javax.lang.model.type.ExecutableType;
42 import javax.lang.model.type.NoType;
43 import javax.lang.model.type.NullType;
44 import javax.lang.model.type.PrimitiveType;
45 import javax.lang.model.type.TypeKind;
46 import javax.lang.model.type.TypeMirror;
47 import javax.lang.model.type.TypeVariable;
48 import javax.lang.model.type.WildcardType;
49 import javax.lang.model.util.ElementFilter;
50 import javax.lang.model.util.SimpleAnnotationValueVisitor6;
51 import javax.lang.model.util.SimpleTypeVisitor6;
52
53 /**TODO: the format below is obsolete:
54  * <pre>
55  * methodSignature ::= 'E' flags methodtype '@' attributes
56  * fieldSignature ::= 'A' flags type realname '@' attributes
57  * classSignature ::= 'G' flags [ typeparams ] realname supertype { interfacetype } '@' attributes
58  * type ::= ... | classtype | methodtype | typevar | error
59  * classtype ::= classsig { '.' classsig }
60  * classig ::= 'L' name [typeargs] ';'
61  * methodtype ::= [ typeparams ] realname '(' { flags type realname } ')' '(' { /throws/type } ')' type
62  * typevar ::= 'T' name ';'
63  * typeargs ::= '<' type { type } '>'
64  * typeparams ::= '<' typeparam { typeparam } '>'
65  * typeparam ::= name ':' type
66  * realname ::= 'N' name ';'
67  * error ::= 'R' name ;
68  *
69  * flags ::= 'M' modifiers specification ';'
70  * inner-class ::= 'O' /inner-class/realname
71  * </pre>
72  *
73  * @author Jan Lahoda
74  */

75 public class SymbolDumper extends SimpleTypeVisitor6<Void JavaDoc, Boolean JavaDoc> {
76     
77     private PrintWriter JavaDoc output;
78     private Types types;
79     
80     /** Creates a new instance of SymbolDumper */
81     public SymbolDumper(PrintWriter JavaDoc output, Types types) {
82         this.output = output;
83         this.types = types;
84     }
85
86     public Void JavaDoc visitPrimitive(PrimitiveType t, Boolean JavaDoc p) {
87         switch (t.getKind()) {
88             case BOOLEAN:
89                 output.append('Z'); // NOI18N
90
break;
91             case BYTE:
92                 output.append('B'); // NOI18N
93
break;
94             case SHORT:
95                 output.append('S'); // NOI18N
96
break;
97             case INT:
98                 output.append('I'); // NOI18N
99
break;
100             case LONG:
101                 output.append('J'); // NOI18N
102
break;
103             case CHAR:
104                 output.append('C'); // NOI18N
105
break;
106             case FLOAT:
107                 output.append('F'); // NOI18N
108
break;
109             case DOUBLE:
110                 output.append('D'); // NOI18N
111
break;
112             default:
113                 throw new IllegalArgumentException JavaDoc("Should not happend. Or can it?");
114         }
115         return null;
116     }
117
118     public Void JavaDoc visitNoType(NoType t, Boolean JavaDoc p) {
119         switch (t.getKind()) {
120             case VOID:
121                 output.append('V');
122                 break;
123             case PACKAGE:
124                 new Exception JavaDoc("what should be printed here?").printStackTrace();
125                 break;
126         }
127         return null;
128     }
129
130     public Void JavaDoc visitNull(NullType t, Boolean JavaDoc p) {
131         new Exception JavaDoc("what should be printed here?").printStackTrace();
132         return null;
133     }
134
135     public Void JavaDoc visitArray(ArrayType t, Boolean JavaDoc p) {
136         output.append('['); // NOI18N
137
visit(t.getComponentType());
138         return null;
139     }
140
141     public Void JavaDoc visitDeclared(DeclaredType t, Boolean JavaDoc p) {
142         output.append('L');
143         output.append(ClassFileUtil.encodeClassName((TypeElement) t.asElement()));
144         List JavaDoc<? extends TypeMirror> actualTypeParameters = t.getTypeArguments();
145         
146         if (!actualTypeParameters.isEmpty()) {
147             output.append('<');
148             for (TypeMirror param : actualTypeParameters) {
149                 visit(param);
150             }
151             output.append('>');
152         }
153         output.append(';');
154         return null;
155     }
156
157     public Void JavaDoc visitError(ErrorType t, Boolean JavaDoc p) {
158         TypeElement te = (TypeElement) t.asElement();
159         
160         output.append('R');
161         
162         if (te != null) {
163             output.append(te.getSimpleName().toString());
164         }
165         
166         output.append(';');
167         
168         return null;
169     }
170
171     public Void JavaDoc visitTypeVariable(TypeVariable t, Boolean JavaDoc p) {
172         if (p == Boolean.TRUE) {
173             output.append(t.asElement().getSimpleName().toString());
174             output.append(':');
175             assert t.getLowerBound().getKind() == TypeKind.NULL : "currently not handled!" ;
176             Type boundImpl = ((Type) t.getUpperBound());
177             
178             if (boundImpl.isCompound()) {
179                 if (boundImpl.getKind() == TypeKind.EXECUTABLE || boundImpl.getKind() == TypeKind.PACKAGE)
180                     throw new IllegalArgumentException JavaDoc(boundImpl.toString());
181                 Type sup = types.supertype(boundImpl);
182                 visit((sup == Type.noType || sup == boundImpl || sup == null)
183                 ? types.interfaces(boundImpl)
184                 : types.interfaces(boundImpl).prepend(sup));
185             } else {
186                 visit(t.getUpperBound());
187             }
188             
189             output.append(';');
190         } else {
191             output.append('Q');
192             output.append(t.asElement().getSimpleName().toString());
193             output.append(';');
194         }
195         
196         return null;
197     }
198
199     public Void JavaDoc visitWildcard(WildcardType t, Boolean JavaDoc p) {
200         boolean wasSomething = false;
201         
202         if (t.getExtendsBound() != null) {
203             output.append("+");
204             visit(t.getExtendsBound());
205             wasSomething = true;
206         }
207         if (t.getSuperBound() != null) {
208             output.append("-");
209             visit(t.getSuperBound());
210             wasSomething = true;
211         }
212         
213         if (!wasSomething) {
214             output.append('?');
215         }
216         return null;
217     }
218
219     public Void JavaDoc visitExecutable(ExecutableType t, Boolean JavaDoc p) {
220         throw new IllegalStateException JavaDoc("This cannot be handled correctly, and should hopefully never happen...");
221     }
222
223     public Void JavaDoc visitUnknown(TypeMirror t, Boolean JavaDoc p) {
224         new Exception JavaDoc("what should be printed here?").printStackTrace();
225         return null;
226     }
227
228     public void visit(List JavaDoc<? extends TypeMirror> l) {
229         for (TypeMirror t : l) {
230             visit(t);
231         }
232     }
233     
234     public void visit(List JavaDoc<? extends TypeMirror> l, Boolean JavaDoc p) {
235         for (TypeMirror t : l) {
236             visit(t, p);
237         }
238     }
239     
240     public static void dump(PrintWriter JavaDoc output, Types types, TypeElement type, Element enclosingElement) {
241         SymbolDumper.dumpImpl(output, types, type, enclosingElement);
242         
243         output.append('\n');
244         
245         for (Element e : type.getEnclosedElements()) {
246             if (e.getKind().isClass() || e.getKind().isInterface()) {
247                 //ignore innerclasses:
248
continue;
249             }
250             SymbolDumper.dumpImpl(output, types, e);
251         }
252         
253         output.append('W');
254                 
255         dumpAnnotations(new SymbolDumper(output, types), type);
256     }
257     
258     private static void dumpImpl(PrintWriter JavaDoc output, Types types, TypeElement type, Element enclosingElement) {
259         SymbolDumper d = new SymbolDumper(output, types);
260         
261         output.append('G');
262         dumpFlags(output, ((Symbol) type).flags_field & ~ (Flags.FROMCLASS|Flags.UNATTRIBUTED));
263         List JavaDoc<? extends TypeParameterElement> params = type.getTypeParameters();
264         
265         if (!params.isEmpty()) {
266             output.append('<');
267             for (TypeParameterElement e : params) {
268                 d.visit(e.asType(), Boolean.TRUE);
269             }
270             output.append('>');
271         }
272         dumpName(output, ClassFileUtil.encodeClassName(type));
273         dumpEnclosingElement(d, enclosingElement);
274         
275         TypeMirror tm = type.getSuperclass();
276         
277         if (tm.getKind() != TypeKind.NONE) {
278             d.visit(tm);
279         } else {
280             //tm.getKind() == TypeKind.NONE also for interfaces, but interface's supertype is j.l.Object, so dump it as such:
281
if (!"java.lang.Object".equals(type.getQualifiedName().toString())) {
282                 output.append("Ljava.lang.Object;");
283             } else {
284                 output.append(";");
285             }
286         }
287         
288         d.visit(type.getInterfaces());
289         output.append(';');
290         
291         dumpInnerclasses(output, ElementFilter.typesIn(type.getEnclosedElements()));
292     }
293     
294     private static void dumpEnclosingElement(SymbolDumper dumper, Element enclosingElement) {
295         if (enclosingElement != null) {
296             if (enclosingElement.getKind().isClass() || enclosingElement.getKind().isInterface()) {
297                 dumpName(dumper.output, ClassFileUtil.encodeClassName((TypeElement)enclosingElement));
298             } else {
299                 dumpName(dumper.output, ClassFileUtil.encodeClassName((TypeElement)enclosingElement.getEnclosingElement()));
300                 ExecutableElement enclosingMethod = (ExecutableElement)enclosingElement;
301                 dumpName(dumper.output, enclosingMethod.getSimpleName());
302                 ExecutableType enclosingMethodType = (ExecutableType)((Symbol)enclosingMethod).externalType(dumper.types);
303                 dumper.output.append('(');
304                 dumper.visit(enclosingMethodType.getParameterTypes());
305                 dumper.output.append(')');
306                 dumper.output.append('(');
307                 dumper.visit(enclosingMethodType.getThrownTypes());
308                 dumper.output.append(')');
309                 dumper.visit(enclosingMethodType.getReturnType());
310             }
311         }
312         dumper.output.append(';');
313     }
314     
315     private static void dumpInnerclasses(PrintWriter JavaDoc output, List JavaDoc<TypeElement> innerClasses) {
316         for (TypeElement innerClass : innerClasses) {
317             dumpName(output, innerClass.getSimpleName());
318         }
319         output.append(';');
320     }
321     
322     private static void dumpImpl(PrintWriter JavaDoc output, Types types, Element el) {
323         if (el.getKind().isField()) {
324             dumpImpl(output, types, (VariableElement) el);
325             output.append('\n');
326             return;
327         }
328         if (el.getKind() == ElementKind.METHOD || el.getKind() == ElementKind.CONSTRUCTOR) {
329             dumpImpl(output, types, (ExecutableElement) el);
330             output.append('\n');
331             return;
332         }
333         
334         Logger.getLogger(SymbolDumper.class.getName()).info("Unhandled ElementKind: " + el.getKind());
335     }
336     
337     private static void dumpImpl(PrintWriter JavaDoc output, Types types, VariableElement variable) {
338         SymbolDumper d = new SymbolDumper(output, types);
339         
340         output.append('A');
341         dumpFlags(output, ((Symbol) variable).flags_field);
342         d.visit(variable.asType());
343         dumpName(output, variable.getSimpleName());
344
345         if (variable.getModifiers().contains(Modifier.STATIC) && variable.getConstantValue() != null) {
346             switch (variable.asType().getKind()) {
347             case BOOLEAN:
348                 output.append('Z'); // NOI18N
349
output.append(String.valueOf(variable.getConstantValue()));
350                 break;
351             case BYTE:
352                 output.append('B'); // NOI18N
353
output.append(String.valueOf(variable.getConstantValue()));
354                 break;
355             case SHORT:
356                 output.append('S'); // NOI18N
357
output.append(String.valueOf(variable.getConstantValue()));
358                 break;
359             case INT:
360                 output.append('I'); // NOI18N
361
output.append(String.valueOf(variable.getConstantValue()));
362                 break;
363             case LONG:
364                 output.append('J'); // NOI18N
365
output.append(String.valueOf(variable.getConstantValue()));
366                 break;
367             case CHAR:
368                 output.append('C'); // NOI18N
369
appendEscapedString(output, String.valueOf(variable.getConstantValue()));
370                 break;
371             case FLOAT:
372                 output.append('F'); // NOI18N
373
output.append(String.valueOf(variable.getConstantValue()));
374                 break;
375             case DOUBLE:
376                 output.append('D'); // NOI18N
377
output.append(String.valueOf(variable.getConstantValue()));
378                 break;
379             case DECLARED:
380                 output.append('L');
381                 TypeMirror varType = variable.asType();
382                 if (varType.getKind() == TypeKind.DECLARED && "java.lang.String".equals(((TypeElement)((DeclaredType)varType).asElement()).getQualifiedName().toString())) {
383                     appendEscapedString(output, String.valueOf(variable.getConstantValue()));
384                 }
385                 break;
386                 default:
387                     output.append("X");
388             }
389         } else {
390             output.append("X");
391         }
392         
393         output.append(";");
394         
395         dumpAnnotations(d, variable);
396     }
397     
398     private static void dumpImpl(PrintWriter JavaDoc output, Types types, ExecutableElement executable) {
399         SymbolDumper d = new SymbolDumper(output, types);
400         ExecutableType type = (ExecutableType) executable.asType();
401         
402         output.append('E');
403         dumpFlags(output, ((Symbol) executable).flags_field);
404         dumpTypeVariables(d, type.getTypeVariables());
405         dumpName(output, executable.getSimpleName());
406         output.append('(');
407         List JavaDoc<? extends TypeMirror> paramTypes = type.getParameterTypes();
408         List JavaDoc<? extends VariableElement> paramElems = executable.getParameters();
409         
410         assert paramElems.size() == paramTypes.size();
411         
412         for (int cntr = 0; cntr < paramTypes.size(); cntr++) {
413             dumpFlags(output, ((Symbol) paramElems.get(cntr)).flags_field);
414             d.visit(paramTypes.get(cntr), Boolean.FALSE);
415             dumpName(output, paramElems.get(cntr).getSimpleName());
416         }
417         output.append(')');
418         
419         output.append('(');
420         
421         for (TypeMirror t : executable.getThrownTypes()) {
422             d.visit(t);
423         }
424         
425         output.append(')');
426         
427         d.visit(type.getReturnType());
428         
429         dumpAnnotations(d, executable);
430         
431         //dump default value (for annotation's attributes):
432
AnnotationValue value = executable.getDefaultValue();
433         
434         if (value != null) {
435             new AnnotationValueVisitorImpl().visit(value, d);
436         } else {
437             output.append(';');
438         }
439     }
440     
441     private static void appendEscapedString(PrintWriter JavaDoc output, String JavaDoc value) {
442         value = value.replaceAll("\\\\", "\\\\\\\\");
443         value = value.replaceAll("@", "\\\\a");
444         value = value.replaceAll(";", "\\\\b");
445         
446         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
447         
448         for (int cntr = 0; cntr < value.length(); cntr++) {
449             char c = value.charAt(cntr);
450             
451             if (c < 32) {
452                 result.append('\\');
453                 
454                 String JavaDoc v = Integer.toHexString(c);
455                 
456                 result.append("0000".substring(0, 4 - v.length()));
457                 result.append(v);
458             } else {
459                 result.append(c);
460             }
461         }
462         
463         output.append(result.toString());
464     }
465     
466     private static void dumpName(PrintWriter JavaDoc output, CharSequence JavaDoc name) {
467         output.append('N');
468         output.append(name.toString());
469         output.append(';');
470     }
471     
472     private static void dumpTypeVariables(SymbolDumper dumper, List JavaDoc<? extends TypeVariable> params) {
473         if (params.isEmpty())
474             return ;
475         
476         dumper.output.append('<');
477         
478         dumper.visit(params, Boolean.TRUE);
479         
480         dumper.output.append('>');
481     }
482     
483     private static void dumpFlags(PrintWriter JavaDoc output, long flags) {
484         output.append('M');
485         output.append(Long.toHexString(flags));
486         output.append(';');
487     }
488     
489     private static void dumpAnnotations(SymbolDumper d, Element e) {
490         for (AnnotationMirror m : e.getAnnotationMirrors()) {
491             dumpAnnotation(d, m);
492         }
493         
494         d.output.append(';');
495     }
496     
497     private static void dumpAnnotation(SymbolDumper d, AnnotationMirror m) {
498         d.visit(m.getAnnotationType());
499         
500         for (Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : m.getElementValues().entrySet()) {
501             dumpName(d.output, entry.getKey().getSimpleName().toString());
502             new AnnotationValueVisitorImpl().visit(entry.getValue(), d);
503         }
504         
505         d.output.append(';');
506     }
507     
508     private static class AnnotationValueVisitorImpl extends SimpleAnnotationValueVisitor6<Void JavaDoc, SymbolDumper> {
509         
510         @Override JavaDoc
511         public Void JavaDoc visitBoolean(boolean b, SymbolDumper d) {
512             d.output.append('Z'); // NOI18N
513
d.output.append(String.valueOf(b));
514             d.output.append(';');
515             
516             return null;
517         }
518
519         @Override JavaDoc
520         public Void JavaDoc visitByte(byte b, SymbolDumper d) {
521             d.output.append('B'); // NOI18N
522
d.output.append(String.valueOf(b));
523             d.output.append(';');
524             
525             return null;
526         }
527
528         @Override JavaDoc
529         public Void JavaDoc visitChar(char c, SymbolDumper d) {
530             d.output.append('C'); // NOI18N
531
appendEscapedString(d.output, String.valueOf(c));
532             d.output.append(';');
533             
534             return null;
535         }
536
537         @Override JavaDoc
538         public Void JavaDoc visitDouble(double v, SymbolDumper d) {
539             d.output.append('D'); // NOI18N
540
d.output.append(String.valueOf(v));
541             d.output.append(';');
542             
543             return null;
544         }
545
546         @Override JavaDoc
547         public Void JavaDoc visitFloat(float f, SymbolDumper d) {
548             d.output.append('F'); // NOI18N
549
d.output.append(String.valueOf(f));
550             d.output.append(';');
551             
552             return null;
553         }
554
555         @Override JavaDoc
556         public Void JavaDoc visitInt(int i, SymbolDumper d) {
557             d.output.append('I'); // NOI18N
558
d.output.append(String.valueOf(i));
559             d.output.append(';');
560             
561             return null;
562         }
563
564         @Override JavaDoc
565         public Void JavaDoc visitLong(long i, SymbolDumper d) {
566             d.output.append('J'); // NOI18N
567
d.output.append(String.valueOf(i));
568             d.output.append(';');
569             
570             return null;
571         }
572
573         @Override JavaDoc
574         public Void JavaDoc visitShort(short s, SymbolDumper d) {
575             d.output.append('S'); // NOI18N
576
d.output.append(String.valueOf(s));
577             d.output.append(';');
578             
579             return null;
580         }
581
582         @Override JavaDoc
583         public Void JavaDoc visitString(String JavaDoc s, SymbolDumper d) {
584             d.output.append('L');
585             appendEscapedString(d.output, String.valueOf(s));
586             d.output.append(';');
587             
588             return null;
589         }
590
591         @Override JavaDoc
592         public Void JavaDoc visitType(TypeMirror t, SymbolDumper p) {
593             p.output.append('Y');
594             p.visit(t);
595             
596             return null;
597         }
598
599         @Override JavaDoc
600         public Void JavaDoc visitEnumConstant(VariableElement c, SymbolDumper d) {
601             d.output.append('O');
602             d.visit(c.getEnclosingElement().asType());
603             dumpName(d.output, c.getSimpleName());
604             
605             return null;
606         }
607
608         @Override JavaDoc
609         public Void JavaDoc visitAnnotation(AnnotationMirror a, SymbolDumper d) {
610             d.output.append('P');
611             dumpAnnotation(d, a);
612             
613             return null;
614         }
615
616         @Override JavaDoc
617         public Void JavaDoc visitArray(List JavaDoc<? extends AnnotationValue> vals, SymbolDumper d) {
618             d.output.append('[');
619             for (AnnotationValue v : vals) {
620                 visit(v, d);
621             }
622             d.output.append(';');
623             
624             return null;
625         }
626
627         @Override JavaDoc
628         public Void JavaDoc visitUnknown(AnnotationValue av, SymbolDumper p) {
629             throw new UnsupportedOperationException JavaDoc("SymbolDumper should be fixed to incorporate unknown value: " + av);
630         }
631         
632     }
633     
634 }
635
Popular Tags