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;
24 ChainHashMap mandatoryImports;
25 ChainHashMap multiImports;
27 int numstaticblocks = 0;
28 int numstaticfields = 0;
31 Vector<String> superinterfaces;
32 SymbolTable superIFdesc;
33 private int interfaceid;
36 boolean isInnerClass=false;
38 // inner classes/enum can have these
39 String surroundingclass=null;
40 //adding another variable to indicate depth of this inner class
42 ClassDescriptor surroudingdesc=null;
43 SymbolTable innerdescs;
46 boolean isEnum = false;
47 SymbolTable enumdescs;
48 HashMap<String, Integer> enumConstantTbl;
49 int enumconstantid = 0;
51 String sourceFileName;
53 public ClassDescriptor(String classname, boolean isInterface) {
54 this("", classname, isInterface);
57 public ClassDescriptor(String packagename, String classname, boolean isInterface) {
58 //make the name canonical by class file path (i.e. package)
59 super(packagename!=null?packagename+"."+classname:classname);
60 this.classname=classname;
62 flags=new SymbolTable();
63 fields=new SymbolTable();
64 fieldvec=new Vector();
65 methods=new SymbolTable();
68 this.interfaceid = -1;
72 this.packagename=packagename;
73 superinterfaces = new Vector<String>();
74 superIFdesc = new SymbolTable();
75 this.innerdescs = new SymbolTable();
76 this.enumdescs = new SymbolTable();
80 if(this.isInterface()) {
81 return this.interfaceid;
86 public Iterator getMethods() {
87 return methods.getDescriptorsIterator();
90 public Iterator getFields() {
91 return fields.getDescriptorsIterator();
94 public Iterator getFlags() {
95 return flags.getDescriptorsIterator();
98 public Iterator getSuperInterfaces() {
99 return this.superIFdesc.getDescriptorsIterator();
102 public SymbolTable getFieldTable() {
106 public Vector getFieldVec() {
110 public String getClassName() {
114 public String getPackage() {
118 public SymbolTable getFlagTable() {
122 public SymbolTable getMethodTable() {
126 public SymbolTable getSuperInterfaceTable() {
127 return this.superIFdesc;
130 public String getSafeDescriptor() {
131 return "L"+safename.replace(".","___________");
134 public String getSafeSymbol() {
135 return safename.replace(".","___________").replace("$","___DOLLAR___");
138 public String printTree(State state) {
140 String st=modifiers.toString()+"class "+getSymbol();
141 if (superclass!=null)
142 st+="extends "+superclass.toString();
143 if(this.superinterfaces != null) {
145 boolean needcomma = false;
146 for(int i = 0; i < this.superinterfaces.size(); i++) {
150 st += this.superinterfaces.elementAt(i);
155 indent=TreeNode.INDENT;
156 boolean printcr=false;
158 for(Iterator it=getFlags(); it.hasNext(); ) {
159 FlagDescriptor fd=(FlagDescriptor)it.next();
160 st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
168 for(Iterator it=getFields(); it.hasNext(); ) {
169 FieldDescriptor fd=(FieldDescriptor)it.next();
170 st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
176 for(Iterator it=this.getInnerClasses(); it.hasNext(); ) {
177 ClassDescriptor icd=(ClassDescriptor)it.next();
178 st+=icd.printTree(state)+"\n";
184 for(Iterator it=this.getEnum(); it.hasNext(); ) {
185 ClassDescriptor icd = (ClassDescriptor)it.next();
186 st += icd.getModifier().toString() + " enum " + icd.getSymbol() + " {\n ";
187 Set keys = icd.getEnumConstantTbl().keySet();
188 String[] econstants = new String[keys.size()];
189 Iterator it_keys = keys.iterator();
190 while(it_keys.hasNext()) {
191 String key = (String)it_keys.next();
192 econstants[icd.getEnumConstant(key)] = key;
194 for(int i = 0; i < econstants.length; i++) {
196 if(i < econstants.length-1) {
206 for(Iterator it=getMethods(); it.hasNext(); ) {
207 MethodDescriptor md=(MethodDescriptor)it.next();
208 st+=TreeNode.printSpace(indent)+md.toString()+" ";
209 BlockNode bn=state.getMethodBody(md);
210 st+=bn.printNode(indent)+"\n\n";
216 public MethodDescriptor getCalledMethod(MethodDescriptor md) {
217 ClassDescriptor cn=this;
220 // TODO: the original code returned "null" if no super class
221 // ever defines the method. Is there a situation where this is
222 // fine and the client should take other actions? If not, we should
223 // change this warning to an error.
224 System.out.println("ClassDescriptor.java: WARNING "+md+
225 " did not resolve to an actual method.");
228 Set possiblematches=cn.getMethodTable().getSetFromSameScope(md.getSymbol());
229 for(Iterator matchit=possiblematches.iterator(); matchit.hasNext(); ) {
230 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
232 if (md.matches(matchmd)) {
237 //Not found...walk one level up
238 cn=cn.getSuperDesc();
242 public void addFlag(FlagDescriptor fd) {
243 if (flags.contains(fd.getSymbol()))
244 throw new Error(fd.getSymbol()+" already defined");
249 public boolean hasFlags() {
250 return hasFlags||getSuperDesc()!=null&&getSuperDesc().hasFlags();
253 public void addField(FieldDescriptor fd) {
254 if (fields.contains(fd.getSymbol()))
255 throw new Error(fd.getSymbol()+" already defined");
259 this.incStaticFields();
261 fd.setClassDescriptor(this);
264 public void addMethod(MethodDescriptor md) {
268 public void setModifiers(Modifiers modifiers) {
269 this.modifiers=modifiers;
272 public void setInline() {
276 public boolean getInline() {
280 public void setSuper(String superclass) {
281 this.superclass=superclass;
284 public ClassDescriptor getSuperDesc() {
288 public void setSuperDesc(ClassDescriptor scd) {
292 public String getSuper() {
296 public void addSuperInterface(String superif) {
297 this.superinterfaces.addElement(superif);
300 public Vector<String> getSuperInterface() {
301 return this.superinterfaces;
304 public void addSuperInterfaces(ClassDescriptor sif) {
305 this.superIFdesc.add(sif);
308 public void incStaticBlocks() {
309 this.numstaticblocks++;
312 public int getNumStaticBlocks() {
313 return this.numstaticblocks;
316 public void incStaticFields() {
317 this.numstaticfields++;
320 public int getNumStaticFields() {
321 return this.numstaticfields;
324 public boolean isAbstract() {
325 return this.modifiers.isAbstract();
328 public boolean isInterface() {
329 return (this.classid == -2);
332 public void setInterfaceId(int id) {
333 this.interfaceid = id;
336 public boolean isStatic() {
337 return this.modifiers.isStatic();
340 public void setAsInnerClass() {
341 this.isInnerClass = true;
343 //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.
344 public void setInnerDepth( int theDepth ) {
345 innerDepth = theDepth;
348 public int getInnerDepth() {
352 public boolean isInnerClass() {
353 return this.isInnerClass;
356 public void setSurroundingClass(String sclass) {
357 this.surroundingclass=sclass;
360 public String getSurrounding() {
361 return this.surroundingclass;
364 public ClassDescriptor getSurroundingDesc() {
365 return this.surroudingdesc;
368 public void setSurrounding(ClassDescriptor scd) {
369 this.surroudingdesc=scd;
372 public void addInnerClass(ClassDescriptor icd) {
373 this.innerdescs.add(icd);
376 public Iterator getInnerClasses() {
377 return this.innerdescs.getDescriptorsIterator();
380 public SymbolTable getInnerClassTable() {
381 return this.innerdescs;
384 public void setAsEnum() {
388 public boolean isEnum() {
392 public void addEnum(ClassDescriptor icd) {
393 this.enumdescs.add(icd);
396 public Iterator getEnum() {
397 return this.enumdescs.getDescriptorsIterator();
400 public SymbolTable getEnumTable() {
401 return this.enumdescs;
404 public void addEnumConstant(String econstant) {
405 if(this.enumConstantTbl == null) {
406 this.enumConstantTbl = new HashMap<String, Integer>();
408 if(this.enumConstantTbl.containsKey(econstant)) {
411 this.enumConstantTbl.put(econstant, this.enumconstantid++);
416 public int getEnumConstant(String econstant) {
417 if(this.enumConstantTbl.containsKey(econstant)) {
418 return this.enumConstantTbl.get(econstant).intValue();
424 public HashMap<String, Integer> getEnumConstantTbl() {
425 return this.enumConstantTbl;
428 public Modifiers getModifier() {
429 return this.modifiers;
432 public void setSourceFileName(String sourceFileName) {
433 this.sourceFileName=sourceFileName;
436 public void setImports(ChainHashMap singleImports, ChainHashMap multiImports) {
437 this.mandatoryImports = singleImports;
438 this.multiImports = multiImports;
441 public String getSourceFileName() {
442 return this.sourceFileName;
445 public ChainHashMap getSingleImportMappings() {
446 return this.mandatoryImports;
449 public ChainHashMap getMultiImportMappings() {
450 return this.multiImports;
453 //Returns the full name/path of another class referenced from this class via imports.
454 public String getCanonicalImportMapName(String otherClassname) {
455 if(mandatoryImports.containsKey(otherClassname)) {
456 return (String) mandatoryImports.get(otherClassname);
457 } else if(multiImports.containsKey(otherClassname)) {
459 Object o = multiImports.get(otherClassname);
460 if(o instanceof Error) {
461 throw new Error("Class " + otherClassname + " is ambiguous. Cause: more than 1 package import contain the same class.");
463 //At this point, if we found a unique class
464 //we can treat it as a single, mandatory import.
465 mandatoryImports.put(otherClassname, o);
469 return otherClassname;