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;
23 ChainHashMap mandatoryImports;
24 ChainHashMap multiImports;
26 int numstaticblocks = 0;
27 int numstaticfields = 0;
30 Vector<String> superinterfaces;
31 SymbolTable superIFdesc;
32 private int interfaceid;
35 boolean isInnerClass=false;
37 // inner classes/enum can have these
38 String surroundingclass=null;
39 //adding another variable to indicate depth of this inner class
41 ClassDescriptor surroundingdesc=null;
42 SymbolTable surroundingNameTable = null;
44 SymbolTable innerdescs;
47 boolean isEnum = false;
48 SymbolTable enumdescs;
49 HashMap<String, Integer> enumConstantTbl;
50 int enumconstantid = 0;
52 String sourceFileName;
54 public ClassDescriptor(String classname, boolean isInterface) {
55 this("", classname, isInterface);
58 public ClassDescriptor(String packagename, String classname, boolean isInterface) {
59 //make the name canonical by class file path (i.e. package)
60 super(packagename!=null?packagename+"."+classname:classname);
61 this.classname=classname;
63 flags=new SymbolTable();
64 fields=new SymbolTable();
65 fieldvec=new Vector();
66 methods=new SymbolTable();
69 this.interfaceid = -1;
73 this.packagename=packagename;
74 superinterfaces = new Vector<String>();
75 superIFdesc = new SymbolTable();
76 this.innerdescs = new SymbolTable();
77 this.enumdescs = new SymbolTable();
81 if(this.isInterface()) {
82 return this.interfaceid;
87 public Iterator getMethods() {
88 return methods.getDescriptorsIterator();
91 public Iterator getFields() {
92 return fields.getDescriptorsIterator();
95 public Iterator getFlags() {
96 return flags.getDescriptorsIterator();
99 public Iterator getSuperInterfaces() {
100 return this.superIFdesc.getDescriptorsIterator();
103 public SymbolTable getFieldTable() {
107 public Vector getFieldVec() {
111 public String getClassName() {
115 public String getPackage() {
119 public SymbolTable getFlagTable() {
123 public SymbolTable getMethodTable() {
127 public SymbolTable getSuperInterfaceTable() {
128 return this.superIFdesc;
131 public String getSafeDescriptor() {
132 return "L"+safename.replace(".","___________");
135 public String getSafeSymbol() {
136 return safename.replace(".","___________").replace("$","___DOLLAR___");
139 public String printTree(State state) {
141 String st=modifiers.toString()+"class "+getSymbol();
142 if (superclass!=null)
143 st+="extends "+superclass.toString();
144 if(this.superinterfaces != null) {
146 boolean needcomma = false;
147 for(int i = 0; i < this.superinterfaces.size(); i++) {
151 st += this.superinterfaces.elementAt(i);
156 indent=TreeNode.INDENT;
157 boolean printcr=false;
159 for(Iterator it=getFlags(); it.hasNext(); ) {
160 FlagDescriptor fd=(FlagDescriptor)it.next();
161 st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
169 for(Iterator it=getFields(); it.hasNext(); ) {
170 FieldDescriptor fd=(FieldDescriptor)it.next();
171 st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
177 for(Iterator it=this.getInnerClasses(); it.hasNext(); ) {
178 ClassDescriptor icd=(ClassDescriptor)it.next();
179 st+=icd.printTree(state)+"\n";
185 for(Iterator it=this.getEnum(); it.hasNext(); ) {
186 ClassDescriptor icd = (ClassDescriptor)it.next();
187 st += icd.getModifier().toString() + " enum " + icd.getSymbol() + " {\n ";
188 Set keys = icd.getEnumConstantTbl().keySet();
189 String[] econstants = new String[keys.size()];
190 Iterator it_keys = keys.iterator();
191 while(it_keys.hasNext()) {
192 String key = (String)it_keys.next();
193 econstants[icd.getEnumConstant(key)] = key;
195 for(int i = 0; i < econstants.length; i++) {
197 if(i < econstants.length-1) {
207 for(Iterator it=getMethods(); it.hasNext(); ) {
208 MethodDescriptor md=(MethodDescriptor)it.next();
209 st+=TreeNode.printSpace(indent)+md.toString()+" ";
210 BlockNode bn=state.getMethodBody(md);
211 st+=bn.printNode(indent)+"\n\n";
217 public MethodDescriptor getCalledMethod(MethodDescriptor md) {
218 ClassDescriptor cn=this;
221 // TODO: the original code returned "null" if no super class
222 // ever defines the method. Is there a situation where this is
223 // fine and the client should take other actions? If not, we should
224 // change this warning to an error.
225 System.out.println("ClassDescriptor.java: WARNING "+md+
226 " did not resolve to an actual method.");
229 Set possiblematches=cn.getMethodTable().getSetFromSameScope(md.getSymbol());
230 for(Iterator matchit=possiblematches.iterator(); matchit.hasNext(); ) {
231 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
233 if (md.matches(matchmd)) {
238 //Not found...walk one level up
239 cn=cn.getSuperDesc();
243 public void addFlag(FlagDescriptor fd) {
244 if (flags.contains(fd.getSymbol()))
245 throw new Error(fd.getSymbol()+" already defined");
250 public boolean hasFlags() {
251 return hasFlags||getSuperDesc()!=null&&getSuperDesc().hasFlags();
254 public void addField(FieldDescriptor fd) {
255 if (fields.contains(fd.getSymbol()))
256 throw new Error(fd.getSymbol()+" already defined");
260 this.incStaticFields();
262 fd.setClassDescriptor(this);
265 public void addMethod(MethodDescriptor md) {
269 public void setModifiers(Modifiers modifiers) {
270 this.modifiers=modifiers;
273 public void setInline() {
277 public boolean getInline() {
281 public void setSuper(String superclass) {
282 this.superclass=superclass;
285 public ClassDescriptor getSuperDesc() {
289 public void setSuperDesc(ClassDescriptor scd) {
293 public String getSuper() {
297 public void addSuperInterface(String superif) {
298 this.superinterfaces.addElement(superif);
301 public Vector<String> getSuperInterface() {
302 return this.superinterfaces;
305 public void addSuperInterfaces(ClassDescriptor sif) {
306 this.superIFdesc.add(sif);
309 public void incStaticBlocks() {
310 this.numstaticblocks++;
313 public int getNumStaticBlocks() {
314 return this.numstaticblocks;
317 public void incStaticFields() {
318 this.numstaticfields++;
321 public int getNumStaticFields() {
322 return this.numstaticfields;
325 public boolean isAbstract() {
326 return this.modifiers.isAbstract();
329 public boolean isInterface() {
330 return (this.classid == -2);
333 public void setInterfaceId(int id) {
334 this.interfaceid = id;
337 public boolean isStatic() {
338 return this.modifiers.isStatic();
341 public void setAsInnerClass() {
342 this.isInnerClass = true;
344 //Will have to call this whenever we are adding the this$ member, ideally should have used a single entrance to add the field. so that entrance could be used to set this flag.
345 public void setInnerDepth( int theDepth ) {
346 innerDepth = theDepth;
349 public int getInnerDepth() {
353 public boolean isInnerClass() {
354 return this.isInnerClass;
357 public void setSurroundingClass(String sclass) {
358 this.surroundingclass=sclass;
361 public String getSurrounding() {
362 return this.surroundingclass;
365 public ClassDescriptor getSurroundingDesc() {
366 return this.surroundingdesc;
369 public void setSurrounding(ClassDescriptor scd) {
370 this.surroundingdesc=scd;
373 public void addInnerClass(ClassDescriptor icd) {
374 this.innerdescs.add(icd);
377 public Iterator getInnerClasses() {
378 return this.innerdescs.getDescriptorsIterator();
381 public SymbolTable getInnerClassTable() {
382 return this.innerdescs;
385 public void setAsEnum() {
389 public boolean isEnum() {
393 public void addEnum(ClassDescriptor icd) {
394 this.enumdescs.add(icd);
397 public Iterator getEnum() {
398 return this.enumdescs.getDescriptorsIterator();
401 public SymbolTable getEnumTable() {
402 return this.enumdescs;
405 public void addEnumConstant(String econstant) {
406 if(this.enumConstantTbl == null) {
407 this.enumConstantTbl = new HashMap<String, Integer>();
409 if(this.enumConstantTbl.containsKey(econstant)) {
412 this.enumConstantTbl.put(econstant, this.enumconstantid++);
417 public int getEnumConstant(String econstant) {
418 if(this.enumConstantTbl.containsKey(econstant)) {
419 return this.enumConstantTbl.get(econstant).intValue();
425 public HashMap<String, Integer> getEnumConstantTbl() {
426 return this.enumConstantTbl;
429 public Modifiers getModifier() {
430 return this.modifiers;
433 public void setSourceFileName(String sourceFileName) {
434 this.sourceFileName=sourceFileName;
437 public void setImports(ChainHashMap singleImports, ChainHashMap multiImports) {
438 this.mandatoryImports = singleImports;
439 this.multiImports = multiImports;
442 public String getSourceFileName() {
443 return this.sourceFileName;
446 public ChainHashMap getSingleImportMappings() {
447 return this.mandatoryImports;
450 public ChainHashMap getMultiImportMappings() {
451 return this.multiImports;
454 //Returns the full name/path of another class referenced from this class via imports.
455 public String getCanonicalImportMapName(String otherClassname) {
456 if(mandatoryImports.containsKey(otherClassname)) {
457 return (String) mandatoryImports.get(otherClassname);
458 } else if(multiImports.containsKey(otherClassname)) {
460 Object o = multiImports.get(otherClassname);
461 if(o instanceof Error) {
462 throw new Error("Class " + otherClassname + " is ambiguous. Cause: more than 1 package import contain the same class.");
464 //At this point, if we found a unique class
465 //we can treat it as a single, mandatory import.
466 mandatoryImports.put(otherClassname, o);
470 return otherClassname;
474 public void setSurroundingNameTable(SymbolTable nametable) {
475 this.surroundingNameTable = nametable;
478 public SymbolTable getSurroundingNameTable() {
479 return this.surroundingNameTable;