6 public class ClassDescriptor extends Descriptor {
7 private static int UIDCount=1; // start from 1 instead of 0 for multicore gc
8 private final int classid;
10 ClassDescriptor superdesc;
11 boolean hasFlags=false;
22 ChainHashMap mandatoryImports;
23 ChainHashMap multiImports;
25 int numstaticblocks = 0;
26 int numstaticfields = 0;
29 Vector<String> superinterfaces;
30 SymbolTable superIFdesc;
31 private int interfaceid;
34 boolean isInnerClass=false;
36 // inner classes/enum can have these
37 String surroundingclass=null;
38 ClassDescriptor surroudingdesc=null;
39 SymbolTable innerdescs;
42 boolean isEnum = false;
43 SymbolTable enumdescs;
44 HashMap<String, Integer> enumConstantTbl;
45 int enumconstantid = 0;
47 String sourceFileName;
49 public ClassDescriptor(String classname, boolean isInterface) {
50 this("", classname, isInterface);
53 public ClassDescriptor(String packagename, String classname, boolean isInterface) {
54 //make the name canonical by class file path (i.e. package)
55 super(packagename!=null?packagename+"."+classname:classname);
56 this.classname=classname;
58 flags=new SymbolTable();
59 fields=new SymbolTable();
60 fieldvec=new Vector();
61 methods=new SymbolTable();
64 this.interfaceid = -1;
68 this.packagename=packagename;
69 superinterfaces = new Vector<String>();
70 superIFdesc = new SymbolTable();
71 this.innerdescs = new SymbolTable();
72 this.enumdescs = new SymbolTable();
76 if(this.isInterface()) {
77 return this.interfaceid;
82 public Iterator getMethods() {
83 return methods.getDescriptorsIterator();
86 public Iterator getFields() {
87 return fields.getDescriptorsIterator();
90 public Iterator getFlags() {
91 return flags.getDescriptorsIterator();
94 public Iterator getSuperInterfaces() {
95 return this.superIFdesc.getDescriptorsIterator();
98 public SymbolTable getFieldTable() {
102 public Vector getFieldVec() {
106 public String getClassName() {
110 public String getPackage() {
114 public SymbolTable getFlagTable() {
118 public SymbolTable getMethodTable() {
122 public SymbolTable getSuperInterfaceTable() {
123 return this.superIFdesc;
126 public String getSafeDescriptor() {
127 return "L"+safename.replace(".","___________");
130 public String getSafeSymbol() {
131 return safename.replace(".","___________");
134 public String printTree(State state) {
136 String st=modifiers.toString()+"class "+getSymbol();
137 if (superclass!=null)
138 st+="extends "+superclass.toString();
139 if(this.superinterfaces != null) {
141 boolean needcomma = false;
142 for(int i = 0; i < this.superinterfaces.size(); i++) {
146 st += this.superinterfaces.elementAt(i);
151 indent=TreeNode.INDENT;
152 boolean printcr=false;
154 for(Iterator it=getFlags(); it.hasNext(); ) {
155 FlagDescriptor fd=(FlagDescriptor)it.next();
156 st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
164 for(Iterator it=getFields(); it.hasNext(); ) {
165 FieldDescriptor fd=(FieldDescriptor)it.next();
166 st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
172 for(Iterator it=this.getInnerClasses(); it.hasNext(); ) {
173 ClassDescriptor icd=(ClassDescriptor)it.next();
174 st+=icd.printTree(state)+"\n";
180 for(Iterator it=this.getEnum(); it.hasNext(); ) {
181 ClassDescriptor icd = (ClassDescriptor)it.next();
182 st += icd.getModifier().toString() + " enum " + icd.getSymbol() + " {\n ";
183 Set keys = icd.getEnumConstantTbl().keySet();
184 String[] econstants = new String[keys.size()];
185 Iterator it_keys = keys.iterator();
186 while(it_keys.hasNext()) {
187 String key = (String)it_keys.next();
188 econstants[icd.getEnumConstant(key)] = key;
190 for(int i = 0; i < econstants.length; i++) {
192 if(i < econstants.length-1) {
202 for(Iterator it=getMethods(); it.hasNext(); ) {
203 MethodDescriptor md=(MethodDescriptor)it.next();
204 st+=TreeNode.printSpace(indent)+md.toString()+" ";
205 BlockNode bn=state.getMethodBody(md);
206 st+=bn.printNode(indent)+"\n\n";
212 public MethodDescriptor getCalledMethod(MethodDescriptor md) {
213 ClassDescriptor cn=this;
216 // TODO: the original code returned "null" if no super class
217 // ever defines the method. Is there a situation where this is
218 // fine and the client should take other actions? If not, we should
219 // change this warning to an error.
220 System.out.println("ClassDescriptor.java: WARNING "+md+
221 " did not resolve to an actual method.");
224 Set possiblematches=cn.getMethodTable().getSetFromSameScope(md.getSymbol());
225 for(Iterator matchit=possiblematches.iterator(); matchit.hasNext(); ) {
226 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
228 if (md.matches(matchmd)) {
233 //Not found...walk one level up
234 cn=cn.getSuperDesc();
238 public void addFlag(FlagDescriptor fd) {
239 if (flags.contains(fd.getSymbol()))
240 throw new Error(fd.getSymbol()+" already defined");
245 public boolean hasFlags() {
246 return hasFlags||getSuperDesc()!=null&&getSuperDesc().hasFlags();
249 public void addField(FieldDescriptor fd) {
250 if (fields.contains(fd.getSymbol()))
251 throw new Error(fd.getSymbol()+" already defined");
255 this.incStaticFields();
257 fd.setClassDescriptor(this);
260 public void addMethod(MethodDescriptor md) {
264 public void setModifiers(Modifiers modifiers) {
265 this.modifiers=modifiers;
268 public void setSuper(String superclass) {
269 this.superclass=superclass;
272 public ClassDescriptor getSuperDesc() {
276 public void setSuper(ClassDescriptor scd) {
280 public String getSuper() {
284 public void addSuperInterface(String superif) {
285 this.superinterfaces.addElement(superif);
288 public Vector<String> getSuperInterface() {
289 return this.superinterfaces;
292 public void addSuperInterfaces(ClassDescriptor sif) {
293 this.superIFdesc.add(sif);
296 public void incStaticBlocks() {
297 this.numstaticblocks++;
300 public int getNumStaticBlocks() {
301 return this.numstaticblocks;
304 public void incStaticFields() {
305 this.numstaticfields++;
308 public int getNumStaticFields() {
309 return this.numstaticfields;
312 public boolean isAbstract() {
313 return this.modifiers.isAbstract();
316 public boolean isInterface() {
317 return (this.classid == -2);
320 public void setInterfaceId(int id) {
321 this.interfaceid = id;
324 public boolean isStatic() {
325 return this.modifiers.isStatic();
328 public void setAsInnerClass() {
329 this.isInnerClass = true;
332 public boolean isInnerClass() {
333 return this.isInnerClass;
336 public void setSurroundingClass(String sclass) {
337 this.surroundingclass=sclass;
340 public String getSurrounding() {
341 return this.surroundingclass;
344 public ClassDescriptor getSurroundingDesc() {
345 return this.surroudingdesc;
348 public void setSurrounding(ClassDescriptor scd) {
349 this.surroudingdesc=scd;
352 public void addInnerClass(ClassDescriptor icd) {
353 this.innerdescs.add(icd);
356 public Iterator getInnerClasses() {
357 return this.innerdescs.getDescriptorsIterator();
360 public SymbolTable getInnerClassTable() {
361 return this.innerdescs;
364 public void setAsEnum() {
368 public boolean isEnum() {
372 public void addEnum(ClassDescriptor icd) {
373 this.enumdescs.add(icd);
376 public Iterator getEnum() {
377 return this.enumdescs.getDescriptorsIterator();
380 public SymbolTable getEnumTable() {
381 return this.enumdescs;
384 public void addEnumConstant(String econstant) {
385 if(this.enumConstantTbl == null) {
386 this.enumConstantTbl = new HashMap<String, Integer>();
388 if(this.enumConstantTbl.containsKey(econstant)) {
391 this.enumConstantTbl.put(econstant, this.enumconstantid++);
396 public int getEnumConstant(String econstant) {
397 if(this.enumConstantTbl.containsKey(econstant)) {
398 return this.enumConstantTbl.get(econstant).intValue();
404 public HashMap<String, Integer> getEnumConstantTbl() {
405 return this.enumConstantTbl;
408 public Modifiers getModifier() {
409 return this.modifiers;
412 public void setSourceFileName(String sourceFileName) {
413 this.sourceFileName=sourceFileName;
416 public void setImports(ChainHashMap singleImports, ChainHashMap multiImports) {
417 this.mandatoryImports = singleImports;
418 this.multiImports = multiImports;
421 public String getSourceFileName() {
422 return this.sourceFileName;
425 public ChainHashMap getSingleImportMappings() {
426 return this.mandatoryImports;
429 public ChainHashMap getMultiImportMappings() {
430 return this.multiImports;
433 //Returns the full name/path of another class referenced from this class via imports.
434 public String getCannonicalImportMapName(String otherClassname) {
435 if(mandatoryImports.containsKey(otherClassname)) {
436 return (String) mandatoryImports.get(otherClassname);
437 } else if(multiImports.containsKey(otherClassname)) {
439 Object o = multiImports.get(otherClassname);
440 if(o instanceof Error) {
441 throw new Error("Class " + otherClassname + " is ambiguous. Cause: more than 1 package import contain the same class.");
443 //At this point, if we found a unique class
444 //we can treat it as a single, mandatory import.
445 mandatoryImports.put(otherClassname, o);
449 return otherClassname;