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;
43 MethodDescriptor surroundingBlock=null;
44 boolean inStaticContext=false;
46 SymbolTable innerdescs;
49 boolean isEnum = false;
50 SymbolTable enumdescs;
51 HashMap<String, Integer> enumConstantTbl;
52 int enumconstantid = 0;
54 String sourceFileName;
56 public ClassDescriptor(String classname, boolean isInterface) {
57 this("", classname, isInterface);
60 public ClassDescriptor(String packagename, String classname, boolean isInterface) {
61 //make the name canonical by class file path (i.e. package)
62 super(packagename!=null?packagename+"."+classname:classname);
63 this.classname=classname;
65 flags=new SymbolTable();
66 fields=new SymbolTable();
67 fieldvec=new Vector();
68 methods=new SymbolTable();
71 this.interfaceid = -1;
75 this.packagename=packagename;
76 superinterfaces = new Vector<String>();
77 superIFdesc = new SymbolTable();
78 this.innerdescs = new SymbolTable();
79 this.enumdescs = new SymbolTable();
83 if(this.isInterface()) {
84 return this.interfaceid;
89 public Iterator getMethods() {
90 return methods.getDescriptorsIterator();
93 public Iterator getFields() {
94 return fields.getDescriptorsIterator();
97 public Iterator getFlags() {
98 return flags.getDescriptorsIterator();
101 public Iterator getSuperInterfaces() {
102 return this.superIFdesc.getDescriptorsIterator();
105 public SymbolTable getFieldTable() {
109 public Vector getFieldVec() {
113 public String getClassName() {
117 public String getPackage() {
121 public SymbolTable getFlagTable() {
125 public SymbolTable getMethodTable() {
129 public SymbolTable getSuperInterfaceTable() {
130 return this.superIFdesc;
133 public String getSafeDescriptor() {
134 return "L"+safename.replace(".","___________");
137 public String getSafeSymbol() {
138 return safename.replace(".","___________").replace("$","___DOLLAR___");
141 public String printTree(State state) {
143 String st=modifiers.toString()+"class "+getSymbol();
144 if (superclass!=null)
145 st+="extends "+superclass.toString();
146 if(this.superinterfaces != null) {
148 boolean needcomma = false;
149 for(int i = 0; i < this.superinterfaces.size(); i++) {
153 st += this.superinterfaces.elementAt(i);
158 indent=TreeNode.INDENT;
159 boolean printcr=false;
161 for(Iterator it=getFlags(); it.hasNext(); ) {
162 FlagDescriptor fd=(FlagDescriptor)it.next();
163 st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
171 for(Iterator it=getFields(); it.hasNext(); ) {
172 FieldDescriptor fd=(FieldDescriptor)it.next();
173 st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
179 for(Iterator it=this.getInnerClasses(); it.hasNext(); ) {
180 ClassDescriptor icd=(ClassDescriptor)it.next();
181 st+=icd.printTree(state)+"\n";
187 for(Iterator it=this.getEnum(); it.hasNext(); ) {
188 ClassDescriptor icd = (ClassDescriptor)it.next();
189 st += icd.getModifier().toString() + " enum " + icd.getSymbol() + " {\n ";
190 Set keys = icd.getEnumConstantTbl().keySet();
191 String[] econstants = new String[keys.size()];
192 Iterator it_keys = keys.iterator();
193 while(it_keys.hasNext()) {
194 String key = (String)it_keys.next();
195 econstants[icd.getEnumConstant(key)] = key;
197 for(int i = 0; i < econstants.length; i++) {
199 if(i < econstants.length-1) {
209 for(Iterator it=getMethods(); it.hasNext(); ) {
210 MethodDescriptor md=(MethodDescriptor)it.next();
211 st+=TreeNode.printSpace(indent)+md.toString()+" ";
212 BlockNode bn=state.getMethodBody(md);
213 st+=bn.printNode(indent)+"\n\n";
219 public MethodDescriptor getCalledMethod(MethodDescriptor md) {
220 ClassDescriptor cn=this;
223 // TODO: the original code returned "null" if no super class
224 // ever defines the method. Is there a situation where this is
225 // fine and the client should take other actions? If not, we should
226 // change this warning to an error.
227 System.out.println("ClassDescriptor.java: WARNING "+md+
228 " did not resolve to an actual method.");
231 Set possiblematches=cn.getMethodTable().getSetFromSameScope(md.getSymbol());
232 for(Iterator matchit=possiblematches.iterator(); matchit.hasNext(); ) {
233 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
235 if (md.matches(matchmd)) {
240 //Not found...walk one level up
241 cn=cn.getSuperDesc();
245 public void addFlag(FlagDescriptor fd) {
246 if (flags.contains(fd.getSymbol()))
247 throw new Error(fd.getSymbol()+" already defined");
252 public boolean hasFlags() {
253 return hasFlags||getSuperDesc()!=null&&getSuperDesc().hasFlags();
256 public void addField(FieldDescriptor fd) {
257 if (fields.contains(fd.getSymbol()))
258 throw new Error(fd.getSymbol()+" already defined");
262 this.incStaticFields();
264 fd.setClassDescriptor(this);
267 public void addMethod(MethodDescriptor md) {
271 public void setModifiers(Modifiers modifiers) {
272 this.modifiers=modifiers;
275 public void setInline() {
279 public boolean getInline() {
283 public void setSuper(String superclass) {
284 this.superclass=superclass;
287 public ClassDescriptor getSuperDesc() {
291 public void setSuperDesc(ClassDescriptor scd) {
295 public String getSuper() {
299 public void addSuperInterface(String superif) {
300 this.superinterfaces.addElement(superif);
303 public Vector<String> getSuperInterface() {
304 return this.superinterfaces;
307 public void addSuperInterfaces(ClassDescriptor sif) {
308 this.superIFdesc.add(sif);
311 public void incStaticBlocks() {
312 this.numstaticblocks++;
315 public int getNumStaticBlocks() {
316 return this.numstaticblocks;
319 public void incStaticFields() {
320 this.numstaticfields++;
323 public int getNumStaticFields() {
324 return this.numstaticfields;
327 public boolean isAbstract() {
328 return this.modifiers.isAbstract();
331 public boolean isInterface() {
332 return (this.classid == -2);
335 public void setInterfaceId(int id) {
336 this.interfaceid = id;
339 public boolean isStatic() {
340 return this.modifiers.isStatic();
343 public void setAsInnerClass() {
344 this.isInnerClass = true;
346 //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.
347 public void setInnerDepth( int theDepth ) {
348 innerDepth = theDepth;
351 public int getInnerDepth() {
355 public boolean isInnerClass() {
356 return this.isInnerClass;
359 public void setSurroundingClass(String sclass) {
360 this.surroundingclass=sclass;
363 public String getSurrounding() {
364 return this.surroundingclass;
367 public ClassDescriptor getSurroundingDesc() {
368 return this.surroundingdesc;
371 public void setSurrounding(ClassDescriptor scd) {
372 this.surroundingdesc=scd;
375 public void addInnerClass(ClassDescriptor icd) {
376 this.innerdescs.add(icd);
379 public Iterator getInnerClasses() {
380 return this.innerdescs.getDescriptorsIterator();
383 public SymbolTable getInnerClassTable() {
384 return this.innerdescs;
387 public void setAsEnum() {
391 public boolean isEnum() {
395 public void addEnum(ClassDescriptor icd) {
396 this.enumdescs.add(icd);
399 public Iterator getEnum() {
400 return this.enumdescs.getDescriptorsIterator();
403 public SymbolTable getEnumTable() {
404 return this.enumdescs;
407 public void addEnumConstant(String econstant) {
408 if(this.enumConstantTbl == null) {
409 this.enumConstantTbl = new HashMap<String, Integer>();
411 if(this.enumConstantTbl.containsKey(econstant)) {
414 this.enumConstantTbl.put(econstant, this.enumconstantid++);
419 public int getEnumConstant(String econstant) {
420 if(this.enumConstantTbl.containsKey(econstant)) {
421 return this.enumConstantTbl.get(econstant).intValue();
427 public HashMap<String, Integer> getEnumConstantTbl() {
428 return this.enumConstantTbl;
431 public Modifiers getModifier() {
432 return this.modifiers;
435 public void setSourceFileName(String sourceFileName) {
436 this.sourceFileName=sourceFileName;
439 public void setImports(ChainHashMap singleImports, ChainHashMap multiImports) {
440 this.mandatoryImports = singleImports;
441 this.multiImports = multiImports;
444 public String getSourceFileName() {
445 return this.sourceFileName;
448 public ChainHashMap getSingleImportMappings() {
449 return this.mandatoryImports;
452 public ChainHashMap getMultiImportMappings() {
453 return this.multiImports;
456 //Returns the full name/path of another class referenced from this class via imports.
457 public String getCanonicalImportMapName(String otherClassname) {
458 if(mandatoryImports.containsKey(otherClassname)) {
459 return (String) mandatoryImports.get(otherClassname);
460 } else if(multiImports.containsKey(otherClassname)) {
462 Object o = multiImports.get(otherClassname);
463 if(o instanceof Error) {
464 throw new Error("Class " + otherClassname + " is ambiguous. Cause: more than 1 package import contain the same class.");
466 //At this point, if we found a unique class
467 //we can treat it as a single, mandatory import.
468 mandatoryImports.put(otherClassname, o);
472 return otherClassname;
476 public void setSurroundingNameTable(SymbolTable nametable) {
477 this.surroundingNameTable = nametable;
480 public SymbolTable getSurroundingNameTable() {
481 return this.surroundingNameTable;
484 public void setSurroundingBlock(MethodDescriptor md) {
485 this.surroundingBlock = md;
488 public MethodDescriptor getSurroundingBlock() {
489 return this.surroundingBlock;
492 public void setInStaticContext() {
493 this.inStaticContext = true;
496 public boolean getInStaticContext() {
497 return this.inStaticContext;