KickJava   Java API By Example, From Geeks To Geeks.

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


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.Attribute;
22 import com.sun.tools.javac.code.Attribute.Compound;
23 import com.sun.tools.javac.code.BoundKind;
24 import com.sun.tools.javac.code.Flags;
25 import static com.sun.tools.javac.code.Flags.*;
26 import static com.sun.tools.javac.code.Kinds.*;
27 import com.sun.tools.javac.code.Scope;
28 import com.sun.tools.javac.code.Source;
29 import com.sun.tools.javac.code.Symbol;
30 import com.sun.tools.javac.code.Symbol.ClassSymbol;
31 import com.sun.tools.javac.code.Symbol.CompletionFailure;
32 import com.sun.tools.javac.code.Symbol.MethodSymbol;
33 import com.sun.tools.javac.code.Symbol.PackageSymbol;
34 import com.sun.tools.javac.code.Symbol.VarSymbol;
35 import com.sun.tools.javac.code.Symtab;
36 import com.sun.tools.javac.code.Type;
37 import com.sun.tools.javac.code.Type.ArrayType;
38 import com.sun.tools.javac.code.Type.ClassType;
39 import com.sun.tools.javac.code.Type.ErrorType;
40 import com.sun.tools.javac.code.Type.ForAll;
41 import com.sun.tools.javac.code.Type.MethodType;
42 import com.sun.tools.javac.code.Type.TypeVar;
43 import com.sun.tools.javac.code.Type.WildcardType;
44 import com.sun.tools.javac.code.Types;
45 import static com.sun.tools.javac.code.TypeTags.*;
46 import com.sun.tools.javac.jvm.ClassReader;
47 import com.sun.tools.javac.model.JavacTypes;
48 import com.sun.tools.javac.util.Context;
49 import com.sun.tools.javac.util.List;
50 import com.sun.tools.javac.util.ListBuffer;
51 import com.sun.tools.javac.util.Log;
52 import com.sun.tools.javac.util.Name;
53 import com.sun.tools.javac.util.Name.Table;
54 import com.sun.tools.javac.util.Pair;
55 import com.sun.tools.javadoc.JavadocClassReader;
56
57 import java.io.BufferedReader JavaDoc;
58 import java.io.IOException JavaDoc;
59 import java.io.InputStreamReader JavaDoc;
60 import java.io.Reader JavaDoc;
61 import java.util.ArrayList JavaDoc;
62
63 import javax.lang.model.element.ElementKind;
64 import javax.lang.model.element.TypeElement;
65 import javax.lang.model.type.TypeMirror;
66 import javax.tools.JavaFileObject;
67
68 import org.netbeans.modules.java.source.parsing.FileObjects;
69 import org.openide.ErrorManager;
70
71 /**
72  *
73  * @author Jan Lahoda
74  */

75 public class SymbolClassReader extends JavadocClassReader {
76     
77     public static void preRegister(final Context context, final boolean loadDocEnv) {
78         context.put(classReaderKey, new Context.Factory<ClassReader>() {
79             public ClassReader make() {
80                 return new SymbolClassReader(context, loadDocEnv);
81             }
82         });
83     }
84     
85     private Symtab syms;
86     private Table table;
87     private Types types;
88     private JavacTypes jTypes;
89     private Log logger;
90     private Source source;
91     
92     private char[] buffer;
93     private int currentBufferIndex;
94     
95     private boolean readingClassSignature = false;
96     private boolean readingEnclMethod = false;
97     private List<Type> missingTypeVariables = List.nil();
98     private List<Type> foundTypeVariables = List.nil();
99
100     protected SymbolClassReader(Context context, boolean loadDocEnv) {
101         super(context, loadDocEnv);
102         syms = Symtab.instance(context);
103         table = Table.instance(context);
104         types = Types.instance(context);
105         jTypes = JavacTypes.instance(context);
106         logger = Log.instance(context);
107         source = Source.instance(context);
108         
109         buffer = new char[127];
110     }
111     
112     private void addCharToBuffer(char c) {
113         if (currentBufferIndex >= buffer.length) {
114             char[] newBuffer = new char[buffer.length * 2];
115             
116             System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
117             buffer = newBuffer;
118         }
119         buffer[currentBufferIndex++] = c;
120     }
121     
122     private void clearBuffer() {
123         currentBufferIndex = 0;
124     }
125     
126     private int bufferLength() {
127         return currentBufferIndex;
128     }
129
130     protected @Override JavaDoc void fillIn(ClassSymbol c) {
131         Symbol oldCurrentOwner = currentOwner;
132         try {
133             fillInImpl(c);
134         } finally {
135             currentOwner = oldCurrentOwner;
136         }
137     }
138     
139     private boolean isSignatureFile (final JavaFileObject jfo) {
140         if (jfo instanceof FileObjects.Base) {
141             return ((FileObjects.Base)jfo).getExt().equals(FileObjects.SIG);
142         }
143         else {
144             //Should never happen, but for sure
145
return jfo.toUri().toString().endsWith('.'+FileObjects.SIG);
146         }
147     }
148     
149     private void fillInImpl(ClassSymbol c) {
150         if (c.classfile == null ||
151             c.classfile.getKind() != JavaFileObject.Kind.CLASS ||
152             !isSignatureFile(c.classfile)) {
153             //will throw a CompletionFailure
154
super.fillIn(c);
155             return ;
156         }
157         
158         try {
159             final BufferedReader JavaDoc r = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(c.classfile.openInputStream(), "UTF-8")); // NOI18N
160
try {
161                 int magic = r.read();
162                 if ( magic != 'G') {
163                     throw new IOException JavaDoc ("Wrong signature file: " + c.classfile.toUri());
164                 }
165                 fillInFromSig(c, r);
166                 if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
167                     List<Type> missing = missingTypeVariables;
168                     List<Type> found = foundTypeVariables;
169                     missingTypeVariables = List.nil();
170                     foundTypeVariables = List.nil();
171                     ClassType ct = (ClassType)currentOwner.type;
172                     ct.supertype_field =
173                             types.subst(ct.supertype_field, missing, found);
174                     ct.interfaces_field =
175                             types.subst(ct.interfaces_field, missing, found);
176                 } else if (missingTypeVariables.isEmpty() !=
177                         foundTypeVariables.isEmpty()) {
178                     Name name = missingTypeVariables.head.tsym.name;
179                     throw badClassFile("undecl.type.var", name);
180                 }
181             } finally {
182                 try {
183                     r.close();
184                 } catch (IOException JavaDoc ex) {
185                     ErrorManager.getDefault().notify(ex);
186                 }
187                 missingTypeVariables = List.nil();
188                 foundTypeVariables = List.nil();
189             }
190         } catch (IOException JavaDoc e) {
191             throw new CompletionFailure(c, e.getMessage()).initCause(e);
192         }
193     }
194     
195     private void fillInFromSig(ClassSymbol c, Reader r) throws IOException JavaDoc {
196         ClassType ct = (ClassType)c.type;
197
198         // allocate scope for members
199
c.members_field = new Scope(c);
200
201         currentOwner = c;
202         
203         // prepare type variable table
204
typevars = typevars.dup(currentOwner);
205         if (ct.getEnclosingType().tag == CLASS) enterTypevars(ct.getEnclosingType());
206
207         // read flags, or skip if this is an inner class
208
long flags = readFlags(r) | Flags.FROMCLASS;
209         c.flags_field = flags;
210
211         int read = r.read();
212         readingClassSignature = true;
213         try {
214             //read type variables:
215
List<TypeVar> typevarsList;
216             
217             if (read == '<') {
218                 typevarsList = readTypeParamsWithName(r, c);
219                 read = r.read();
220             } else {
221                 typevarsList = List.<TypeVar>nil();
222             }
223             
224             for (TypeVar tvar : typevarsList) {
225                 typevars.enter(tvar.tsym);
226             }
227             
228             ct.typarams_field = (List<Type>) ((List<?>) typevarsList);
229             
230             assert read == 'N' : read;
231             
232             Name name = readPlainNameIntoTable(r);
233             
234             if (name != c.flatname) {
235                 throw badClassFile("class.file.wrong.class",
236                         name);
237             }
238             
239             // handle enclosing method for anonymous and local classes
240
if ((read = r.read()) != ';') {
241                 readEnclosingMethodAttr(r, c, read);
242             }
243             
244             read = r.read();
245             
246             if (read != ';') {
247                 ct.supertype_field = readType(r, read); //XXX: Maybe add ct.supertype_field.tsym.erase () as the ClassReader does
248
} else {
249                 //noType as the parent, for j.l.Object:
250
ct.supertype_field = Type.noType;
251             }
252             
253             if (ct.supertype_field.getClass() == Type.class) {
254                 if (!ct.supertype_field.isPrimitive()) {
255                     System.err.println("PROBLEM");
256                     System.err.println("c=" + c.flatname.toString());
257                 }
258             }
259             
260             //read super interfaces:
261
List<Type> superInterfaces = List.nil();
262             
263             while ((read = r.read()) != ';') {
264                 superInterfaces = superInterfaces.prepend(readType(r, read)); //XXX: Maybe add erase () as the ClassReader does
265
}
266             
267             ct.interfaces_field = superInterfaces.reverse();
268             
269         } finally {
270             readingClassSignature = false;
271         }
272         
273         //handle innerclasses
274
while ((read = r.read()) != ';') {
275             assert read == 'N';
276             
277             String JavaDoc innerClassName = readPlainName(r);
278             ClassSymbol innerClass = enterClass(findName(innerClassName), c);
279             
280             markInnerClassOwner(c, innerClass);
281         }
282         
283         read = r.read();
284         
285         assert read == '\n' || read == (-1) : c.classfile + ", char: " + ((char) read) + read;
286         
287         Symbol s;
288         
289         while ((s = readMember(r)) != null) {
290             enterMember(c, s);
291         }
292         
293         c.attributes_field = readAnnotations(r);
294         
295         typevars = typevars.leave();
296     }
297     
298     void readEnclosingMethodAttr(Reader r, ClassSymbol self, int read) throws IOException JavaDoc {
299         readingEnclMethod = true;
300         try{
301             assert read == 'N' : read;
302             // sym is a nested class with an "Enclosing Method" attribute
303
// remove sym from it's current owners scope and place it in
304
// the scope specified by the attribute
305
//jlahoda: the owner may already be set correctly, do not remove from it in such a case:
306
if (self.owner.kind == PCK) {
307                 self.owner.members().remove(self);
308             }
309             ClassSymbol c = enterClass(readPlainNameIntoTable(r));
310             MethodSymbol m = null;
311             read = r.read();
312             if (read == 'N') {
313                 Name methodName = readPlainNameIntoTable(r);
314                 read = r.read();
315                 assert read == '(' : read;
316                 List<Type> paramsTypes = List.nil();
317                 while ((read = r.read()) != ')') {
318                     paramsTypes = paramsTypes.prepend(readType(r, read));
319                 }
320                 paramsTypes = paramsTypes.reverse();
321                 read = r.read();
322                 assert read == '(' : read;
323                 List<Type> throwsTypes = List.nil();
324                 while ((read = r.read()) != ')') {
325                     throwsTypes = throwsTypes.prepend(readType(r, read));
326                 }
327                 throwsTypes = throwsTypes.reverse();
328                 Type returnType = readType(r, r.read());
329                 assert (read = r.read()) == ';' : read;
330                 MethodType methodType = new MethodType(paramsTypes, returnType, throwsTypes, syms.methodClass);
331                 
332                 m = findMethod(methodName, methodType, c.members_field, self.flags());
333                 if (methodName != null && methodType != null && m == null)
334                     throw badClassFile("bad.enclosing.method", self);
335             }
336             self.name = simpleBinaryName(self.flatname, c.flatname) ;
337             self.owner = m != null ? m : c;
338             if (self.name.len == 0)
339                 self.fullname = null;
340             else
341                 self.fullname = ClassSymbol.formFullName(self.name, self.owner);
342             
343             if (m != null) {
344                 ((ClassType)self.type).setEnclosingType(m.type);
345             } else if ((self.flags_field & STATIC) == 0) {
346                 ((ClassType)self.type).setEnclosingType(c.type);
347             } else {
348                 ((ClassType)self.type).setEnclosingType(Type.noType);
349             }
350             enterTypevars(self);
351             if (!missingTypeVariables.isEmpty()) {
352                 ListBuffer<Type> typeVars = new ListBuffer<Type>();
353                 for (Type typevar : missingTypeVariables) {
354                     typeVars.append(findTypeVar(typevar.tsym.name));
355                 }
356                 foundTypeVariables = typeVars.toList();
357             } else {
358                 foundTypeVariables = List.nil();
359             }
360         } finally {
361             readingEnclMethod = false;
362         }
363     }
364     
365     private MethodSymbol findMethod(Name name, MethodType type, Scope scope, long flags) {
366         if (name == null || type == null)
367             return null;
368
369         for (Scope.Entry e = scope.lookup(name); e.scope != null; e = e.next())
370             if (e.sym.kind == MTH && isSameBinaryType(e.sym.type.asMethodType(), type))
371                 return (MethodSymbol)e.sym;
372
373         if (name != table.init)
374             // not a constructor
375
return null;
376         if ((flags & INTERFACE) != 0)
377             // no enclosing instance
378
return null;
379         if (type.getParameterTypes().isEmpty())
380             // no parameters
381
return null;
382
383         // A constructor of an inner class.
384
// Remove the first argument (the enclosing instance)
385
type = new MethodType(type.getParameterTypes().tail,
386                                  type.getReturnType(),
387                                  type.getThrownTypes(),
388                                  syms.methodClass);
389         // Try searching again
390
return findMethod(name, type, scope, flags);
391     }
392     
393     private void markInnerClassOwner(ClassSymbol owner, ClassSymbol innerClass) {
394         innerClass.complete();
395         enterMember(owner, innerClass);
396         
397         if ((innerClass.flags_field & STATIC) == 0) {
398             ((ClassType)innerClass.type).setEnclosingType(owner.type);
399             if (innerClass.erasure_field != null)
400                 ((ClassType)innerClass.erasure_field).setEnclosingType(types.erasure(owner.type));
401         }
402     }
403
404     private List<TypeVar> readTypeParamsWithName(Reader r, Symbol owner) throws IOException JavaDoc {
405         List<TypeVar> result = List.<TypeVar>nil();
406         int read;
407         
408         while ((read =r.read()) != '>') {
409             clearBuffer();
410             
411             addCharToBuffer((char) read);
412             
413             while ((read = r.read()) != ':') {
414                 addCharToBuffer((char) read);
415             }
416             
417             Name typeName = findName(buffer, bufferLength());
418             
419             TypeVar tvar = null;
420             List<Type> last = null;
421             for (List<Type> l = missingTypeVariables; l.nonEmpty(); l = l.tail) {
422                 if (typeName == l.head.tsym.name) {
423                     tvar = (TypeVar)l.head;
424                     if (last != null)
425                         last.tail = l.tail;
426                     else
427                         missingTypeVariables = l.tail;
428                     break;
429                 }
430                 last = l;
431             }
432             if (tvar == null)
433                 tvar = new TypeVar(typeName, owner, syms.botType);
434             
435             typevars.enter(tvar.tsym);
436             
437             List<Type> bounds = List.<Type>nil();
438             
439             while ((read = r.read()) != ';') {
440                 bounds = bounds.prepend(readType(r, read));
441             }
442             
443             bounds = bounds.reverse();
444             
445             types.setBounds(tvar, bounds, null);
446             
447             result = result.prepend(tvar);
448         }
449         
450         return result.reverse();
451     }
452     
453     private java.util.List JavaDoc<? extends TypeMirror> readTypeParams(Reader r) throws IOException JavaDoc {
454         java.util.List JavaDoc<TypeMirror> params = new java.util.ArrayList JavaDoc<TypeMirror>();
455         int read;
456         
457         while ((read = r.read()) != '>') {
458             params.add(readType(r, read));
459         }
460         
461         return params;
462     }
463     
464     private String JavaDoc readPlainName(Reader r) throws IOException JavaDoc {
465         clearBuffer();
466         
467         int read;
468         
469         while ((read = r.read()) != ';') {
470             addCharToBuffer((char) read);
471         }
472         
473         return new String JavaDoc(buffer, 0, bufferLength());
474     }
475     
476     private String JavaDoc readName(Reader r) throws IOException JavaDoc {
477         int read = r.read();
478         
479         assert read == 'N' : (char) read;
480         
481         return readPlainName(r);
482     }
483     
484     private Name readPlainNameIntoTable(Reader r) throws IOException JavaDoc {
485         clearBuffer();
486         
487         int read;
488         
489         while ((read = r.read()) != ';') {
490             addCharToBuffer((char) read);
491         }
492         
493         return findName(buffer, bufferLength());
494     }
495     
496     private Name readNameIntoTable(Reader r) throws IOException JavaDoc {
497         int read = r.read();
498         
499         assert read == 'N' : (char) read;
500         
501         return readPlainNameIntoTable(r);
502     }
503     
504     private long readPlainFlags(Reader r) throws IOException JavaDoc {
505         return Long.parseLong(readPlainName(r), 16);
506     }
507     
508     private long readFlags(Reader r) throws IOException JavaDoc {
509         int read = r.read();
510         
511         assert read == 'M';
512         
513         return readPlainFlags(r);
514     }
515     
516     private Type readType(Reader r, int read) throws IOException JavaDoc {
517         switch (read) {
518             case 'Z':
519                 return syms.booleanType;
520             case 'B':
521                 return syms.byteType;
522             case 'S':
523                 return syms.shortType;
524             case 'I':
525                 return syms.intType;
526             case 'J':
527                 return syms.longType;
528             case 'C':
529                 return syms.charType;
530             case 'F':
531                 return syms.floatType;
532             case 'D':
533                 return syms.doubleType;
534             case 'V':
535                 return syms.voidType;
536             case 'L':
537                 return readReferenceType(r);
538             case '[':
539                 return (Type) jTypes.getArrayType(readType(r, r.read()));
540             case 'R':
541                 return new ErrorType(readPlainNameIntoTable(r), syms.noSymbol);
542             case 'Q':
543                 return findTypeVar(readPlainNameIntoTable(r));
544             case '+':
545                 return new WildcardType(readType(r, r.read()), BoundKind.EXTENDS, syms.boundClass);
546             case '-':
547                 return new WildcardType(readType(r, r.read()), BoundKind.SUPER, syms.boundClass);
548             case '?':
549                 return new WildcardType(syms.objectType, BoundKind.UNBOUND, syms.boundClass);
550             default:
551                 throw new IllegalArgumentException JavaDoc("Completing: " + ((ClassSymbol) currentOwner).flatname.toString() + ", read=" + ((char) read) + ":" + read);
552         }
553     }
554     
555     /** Find type variable with given name in `typevars' scope.
556      */

557     Type findTypeVar(Name name) {
558         Scope.Entry e = typevars.lookup(name);
559         if (e.scope != null) {
560             return e.sym.type;
561         } else {
562             if (readingClassSignature || readingEnclMethod) {
563                 // While reading the class attribute, the supertypes
564
// might refer to a type variable from an enclosing element
565
// (method or class).
566
// If the type variable is defined in the enclosing class,
567
// we can actually find it in
568
// currentOwner.owner.type.getTypeArguments()
569
// However, until we have read the enclosing method attribute
570
// we don't know for sure if this owner is correct. It could
571
// be a method and there is no way to tell before reading the
572
// enclosing method attribute.
573
TypeVar t = new TypeVar(name, currentOwner, syms.botType);
574                 missingTypeVariables = missingTypeVariables.prepend(t);
575                 // System.err.println("Missing type var " + name);
576
return t;
577             }
578             throw badClassFile("undecl.type.var", name);
579         }
580     }
581
582     private Name findName(CharSequence JavaDoc s) {
583         char[] data = s.toString().toCharArray();
584         
585         return findName(data, data.length);
586     }
587     
588     private Name findName(char[] data, int len) {
589         return Name.fromChars(table, data, 0, len);
590     }
591
592     private Type readReferenceType(Reader r) throws IOException JavaDoc {
593         clearBuffer();
594         
595         int read;
596         
597         while (";<".indexOf(read = r.read()) == (-1)) {
598             addCharToBuffer((char) read);
599         }
600         
601         Name name = findName(buffer, bufferLength());
602         ClassSymbol symbol = enterClass(name);
603         
604         Symbol oldCurrentOwner = currentOwner;
605         java.util.List JavaDoc<? extends TypeMirror> typeParams = read == '<' ? readTypeParams(r) : null;//Collections.<TypeMirror>emptyList();
606
Type result;
607         
608         if (source.allowGenerics() && typeParams != null) {
609             result = new ClassType(symbol.type, List.from(typeParams.toArray(new Type[0])), symbol) {
610                 boolean completed = false;
611                 public Type getEnclosingType() {
612                     if (!completed) {
613                         completed = true;
614                         tsym.complete();
615                         Type enclosingType = tsym.type.getEnclosingType();
616                         if (enclosingType != Type.noType) {
617                             List<Type> typeArgs =
618                                     super.getEnclosingType().allparams();
619                             List<Type> typeParams =
620                                     enclosingType.allparams();
621                             if (typeParams.length() != typeArgs.length()) {
622                                 // no "rare" types
623
super.setEnclosingType(types.erasure(enclosingType));
624                             } else {
625                                 super.setEnclosingType(types.subst(enclosingType,
626                                         typeParams,
627                                         typeArgs));
628                             }
629                         } else {
630                             super.setEnclosingType(Type.noType);
631                         }
632                     }
633                     return super.getEnclosingType();
634                 }
635                 public void setEnclosingType(Type outer) {
636                     throw new UnsupportedOperationException JavaDoc();
637                 }
638             };
639         } else {
640             result = symbol.erasure(types);
641         }
642         
643         currentOwner = oldCurrentOwner;
644         
645         if (read == '<') {
646             read = r.read();
647             assert read == ';' : (char) read;
648         }
649         
650         return result;
651     }
652     
653     private Symbol readMember(Reader r) throws IOException JavaDoc {
654         int read = r.read();
655         
656         if ('E' == read) {
657             return readExecutableMember(r);
658         }
659         
660         if ('A' == read) {
661             return readField(r);
662         }
663         
664         if ('W' == read)
665             return null;
666         
667         if (read == (-1))
668             return null;
669         
670         throw new IllegalArgumentException JavaDoc("Unknown type: " + read);
671     }
672
673     private Symbol readExecutableMember(Reader r) throws IOException JavaDoc {
674         long flags = readFlags(r);
675         
676         typevars = typevars.dup(currentOwner);
677         
678         List<TypeVar> typevarsList = null;
679         int read = r.read();
680         
681         if (read == '<') {
682             typevarsList = readTypeParamsWithName(r, null);
683             
684             read = r.read();
685         }
686         
687         assert read == 'N' : read;
688         
689         Name symbolName = readPlainNameIntoTable(r);
690         
691         read = r.read();
692         
693         assert read == '(' : read;
694         
695         List<VarSymbol> params = List.nil();
696         List<Type> paramsTypes = List.nil();
697         
698         while ((read = r.read()) != ')') {
699             assert read == 'M';
700             
701             long argFlags = readPlainFlags(r);
702             Type argType = readType(r, r.read());
703             Name argName = readNameIntoTable(r);
704             
705             paramsTypes = paramsTypes.prepend(argType);
706             
707             params = params.prepend(new VarSymbol(argFlags, argName, argType, null));
708         }
709         
710         paramsTypes = paramsTypes.reverse();
711         params = params.reverse();
712         read = r.read();
713         
714         assert read == '(' : read;
715         
716         List<Type> throwsTypes = List.nil();
717         
718         while ((read = r.read()) != ')') {
719             throwsTypes = throwsTypes.prepend(readType(r, read));
720         }
721         
722         Type returnType = readType(r, r.read());
723         Type methodType = new MethodType(paramsTypes, returnType, throwsTypes.reverse(), syms.methodClass/*???*/);;
724         
725         if (typevarsList != null) {
726             methodType = new ForAll((List<Type>) ((List<?>) typevarsList), methodType);
727         }
728         
729         MethodSymbol method = new MethodSymbol(flags, symbolName, methodType, currentOwner);
730         
731         method.params = params;
732         
733         //change owner for all arguments:
734
for (VarSymbol s : params) {
735             s.owner = method;
736         }
737         
738         method.attributes_field = readAnnotations(r);
739
740         if ((read = r.read()) != ';') {
741             method.defaultValue = readAnnotationValue(methodType.getReturnType(), r, read);
742         }
743         
744         typevars = typevars.leave();
745         
746         read = r.read();
747         
748         while (read == ' ')
749             read = r.read();
750         
751         assert read == '\n' || read == (-1) : read;
752         
753         return method;
754     }
755     
756     private Symbol readField(Reader r) throws IOException JavaDoc {
757         long flags = readFlags(r);
758         
759         Type type = readType(r, r.read());
760         Name name = readNameIntoTable(r);
761         
762         Object JavaDoc constantValue = readConstantField(r);
763         
764         VarSymbol field = new VarSymbol(flags, name, type, currentOwner);
765         
766         field.setData(constantValue);
767         
768         field.attributes_field = readAnnotations(r);
769         
770         int read = r.read();
771         
772         while (read == ' ')
773             read = r.read();
774         
775         assert read == '\n' || read == (-1) : read;
776         
777         return field;
778     }
779     
780     private String JavaDoc readEscapedString(Reader r) throws IOException JavaDoc {
781         String JavaDoc value = readPlainName(r);
782         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
783         
784         for (int cntr = 0; cntr < value.length(); cntr++) {
785             char c = value.charAt(cntr);
786             
787             if (c == '\\') {
788                 char next = value.charAt(cntr + 1);
789                 
790                 switch (next) {
791                     case '0': case '1': case '2': case '3':
792                     case '4': case '5': case '6': case '7':
793                     case '8': case '9':
794                         result.append((char) Integer.parseInt(value.substring(cntr + 1, cntr + 5), 16));
795                         cntr += 4;
796                         break;
797                     case 'a':
798                         result.append('@');
799                         cntr++;
800                         break;
801                     case 'b':
802                         result.append(';');
803                         cntr++;
804                         break;
805                     case '\\':
806                         result.append('\\');
807                         cntr++;
808                         break;
809                     default:
810                         throw new IllegalStateException JavaDoc("Unsupported escape: " + next);
811                 }
812             } else {
813                 result.append(c);
814             }
815         }
816         
817         return result.toString();
818     }
819     
820     private Object JavaDoc readConstantField(Reader r) throws IOException JavaDoc {
821         Object JavaDoc result = null;
822         int read = r.read();
823         
824         switch (read) {
825             case 'Z': result = Boolean.parseBoolean(readPlainName(r)) ? Integer.valueOf(1) : Integer.valueOf(0); break;
826             case 'B': result = Integer.valueOf(readPlainName(r)); break;
827             case 'S': result = Integer.valueOf(readPlainName(r)); break;
828             case 'I': result = Integer.valueOf(readPlainName(r)); break;
829             case 'J': result = Long.valueOf(readPlainName(r)); break;
830             case 'C': result = new Integer JavaDoc(Character.valueOf(readEscapedString(r).charAt(0))); break;
831             case 'F': result = Float.valueOf(readPlainName(r)); break;
832             case 'D': result = Double.valueOf(readPlainName(r)); break;
833             case 'L': result = readEscapedString(r); break;
834             case 'X':
835                 read = r.read();
836                 
837                 assert read == ';';
838                 break;
839             default:
840                 throw badClassFile("Unknown constant type: " + (char) read); //TODO: key!
841
}
842         
843         return result;
844     }
845     
846     private List<Compound> readAnnotations(Reader r) throws IOException JavaDoc {
847         List<Compound> attributes = List.nil();
848         int read;
849         
850         while ((read = r.read()) != ';') {
851             attributes = attributes.prepend(readAnnotation(r, read));
852         }
853         
854         return attributes.reverse();
855     }
856     
857     private Compound readAnnotation(Reader r, int read) throws IOException JavaDoc {
858         Type annotationType = readType(r, read);
859         
860         annotationType.complete(); //well, we may need to do this lazy...
861

862         List<Pair<MethodSymbol, Attribute>> values = List.nil();
863         
864         while ((read = r.read()) != ';') {
865             assert read == 'N';
866             
867             String JavaDoc attributeName = readPlainName(r);
868             MethodSymbol ms = null;
869             
870             for (Symbol m : ((ClassType) annotationType).asElement().getEnclosedElements()) {
871                 if (m.getKind() == ElementKind.METHOD && attributeName.equals(m.getSimpleName().toString())) {
872                     ms = (MethodSymbol) m;
873                     break;
874                 }
875             }
876             
877             if (ms == null) {
878                 throw new IllegalStateException JavaDoc("invalid sig file: " + ((ClassSymbol) currentOwner).classfile + ", cannot find annotation attribute \"" + attributeName + " in " + ((TypeElement) ((ClassType) annotationType).asElement()).getQualifiedName());
879             }
880             
881             Attribute a = readAnnotationValue(ms.getReturnType(), r, r.read());
882             values = values.prepend(new Pair<MethodSymbol, Attribute>(ms, a));
883         }
884         
885         return new Compound(annotationType, values.reverse());
886     }
887     
888     private Attribute readEnum(Reader r) throws IOException JavaDoc {
889         Type enumType = readType(r, r.read());
890         Name constantName = readNameIntoTable(r);
891         VarSymbol constant = null;
892         
893         for (Scope.Entry e = ((ClassType) enumType).tsym.members().lookup(constantName); e.scope != null; e = e.next()) {
894             if (e.sym.kind == VAR) {
895                 constant = (VarSymbol)e.sym;
896                 break;
897             }
898         }
899         if (constant == null) {
900             logger.error("unknown.enum.constant", currentClassFile, enumType, constant);
901             return new Attribute.Error(enumType);
902         } else {
903             return new Attribute.Enum(enumType, constant);
904         }
905     }
906     
907     private Attribute readAnnotationValue(Type expectedType, Reader r, int read) throws IOException JavaDoc {
908         switch (read) {
909             case 'Z': return new Attribute.Constant(syms.booleanType, Boolean.parseBoolean(readPlainName(r)) ? Integer.valueOf(1) : Integer.valueOf(0));
910             case 'B': return new Attribute.Constant(syms.byteType, Integer.parseInt(readPlainName(r)));
911             case 'S': return new Attribute.Constant(syms.shortType, Integer.parseInt(readPlainName(r)));
912             case 'I': return new Attribute.Constant(syms.intType, Integer.parseInt(readPlainName(r)));
913             case 'J': return new Attribute.Constant(syms.longType, Long.parseLong(readPlainName(r)));
914             case 'C': return new Attribute.Constant(syms.charType, Integer.valueOf(Character.valueOf(readEscapedString(r).charAt(0))));
915             case 'F': return new Attribute.Constant(syms.floatType, Float.parseFloat(readPlainName(r)));
916             case 'D': return new Attribute.Constant(syms.doubleType, Double.parseDouble(readPlainName(r)));
917             case 'L': return new Attribute.Constant(syms.stringType, readEscapedString(r));
918             case 'O': return readEnum(r);
919             case 'P': return readAnnotation(r, r.read());
920             case '[':
921                 java.util.List JavaDoc<Attribute> items = new ArrayList JavaDoc<Attribute>();
922                 
923                 while ((read = r.read()) != ';') {
924                     items.add(readAnnotationValue(expectedType, r, read));
925                 }
926                 
927                 return new Attribute.Array(((ArrayType) expectedType).getComponentType(), (Attribute[]) items.toArray(new Attribute[0]));
928             case 'Y':
929                 return new Attribute.Class(types, readType(r, r.read()));
930         }
931         
932         throw new IllegalStateException JavaDoc("Completing: " + ((ClassSymbol) currentOwner).flatname.toString() + ", read=" + ((char) read) + ":" + read);
933     }
934
935     //for tests:
936
protected @Override JavaDoc void includeClassFile(PackageSymbol p, JavaFileObject file) {
937         super.includeClassFile(p, file);
938     }
939
940 }
941
Popular Tags