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 ClassDescriptor surroudingdesc=null;
41 SymbolTable innerdescs;
44 boolean isEnum = false;
45 SymbolTable enumdescs;
46 HashMap<String, Integer> enumConstantTbl;
47 int enumconstantid = 0;
49 String sourceFileName;
51 public ClassDescriptor(String classname, boolean isInterface) {
52 this("", classname, isInterface);
55 public ClassDescriptor(String packagename, String classname, boolean isInterface) {
56 //make the name canonical by class file path (i.e. package)
57 super(packagename!=null?packagename+"."+classname:classname);
58 this.classname=classname;
60 flags=new SymbolTable();
61 fields=new SymbolTable();
62 fieldvec=new Vector();
63 methods=new SymbolTable();
66 this.interfaceid = -1;
70 this.packagename=packagename;
71 superinterfaces = new Vector<String>();
72 superIFdesc = new SymbolTable();
73 this.innerdescs = new SymbolTable();
74 this.enumdescs = new SymbolTable();
78 if(this.isInterface()) {
79 return this.interfaceid;
84 public Iterator getMethods() {
85 return methods.getDescriptorsIterator();
88 public Iterator getFields() {
89 return fields.getDescriptorsIterator();
92 public Iterator getFlags() {
93 return flags.getDescriptorsIterator();
96 public Iterator getSuperInterfaces() {
97 return this.superIFdesc.getDescriptorsIterator();
100 public SymbolTable getFieldTable() {
104 public Vector getFieldVec() {
108 public String getClassName() {
112 public String getPackage() {
116 public SymbolTable getFlagTable() {
120 public SymbolTable getMethodTable() {
124 public SymbolTable getSuperInterfaceTable() {
125 return this.superIFdesc;
128 public String getSafeDescriptor() {
129 return "L"+safename.replace(".","___________");
132 public String getSafeSymbol() {
133 return safename.replace(".","___________").replace("$","___DOLLAR___");
136 public String printTree(State state) {
138 String st=modifiers.toString()+"class "+getSymbol();
139 if (superclass!=null)
140 st+="extends "+superclass.toString();
141 if(this.superinterfaces != null) {
143 boolean needcomma = false;
144 for(int i = 0; i < this.superinterfaces.size(); i++) {
148 st += this.superinterfaces.elementAt(i);
153 indent=TreeNode.INDENT;
154 boolean printcr=false;
156 for(Iterator it=getFlags(); it.hasNext(); ) {
157 FlagDescriptor fd=(FlagDescriptor)it.next();
158 st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
166 for(Iterator it=getFields(); it.hasNext(); ) {
167 FieldDescriptor fd=(FieldDescriptor)it.next();
168 st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
174 for(Iterator it=this.getInnerClasses(); it.hasNext(); ) {
175 ClassDescriptor icd=(ClassDescriptor)it.next();
176 st+=icd.printTree(state)+"\n";
182 for(Iterator it=this.getEnum(); it.hasNext(); ) {
183 ClassDescriptor icd = (ClassDescriptor)it.next();
184 st += icd.getModifier().toString() + " enum " + icd.getSymbol() + " {\n ";
185 Set keys = icd.getEnumConstantTbl().keySet();
186 String[] econstants = new String[keys.size()];
187 Iterator it_keys = keys.iterator();
188 while(it_keys.hasNext()) {
189 String key = (String)it_keys.next();
190 econstants[icd.getEnumConstant(key)] = key;
192 for(int i = 0; i < econstants.length; i++) {
194 if(i < econstants.length-1) {
204 for(Iterator it=getMethods(); it.hasNext(); ) {
205 MethodDescriptor md=(MethodDescriptor)it.next();
206 st+=TreeNode.printSpace(indent)+md.toString()+" ";
207 BlockNode bn=state.getMethodBody(md);
208 st+=bn.printNode(indent)+"\n\n";
214 public MethodDescriptor getCalledMethod(MethodDescriptor md) {
215 ClassDescriptor cn=this;
218 // TODO: the original code returned "null" if no super class
219 // ever defines the method. Is there a situation where this is
220 // fine and the client should take other actions? If not, we should
221 // change this warning to an error.
222 System.out.println("ClassDescriptor.java: WARNING "+md+
223 " did not resolve to an actual method.");
226 Set possiblematches=cn.getMethodTable().getSetFromSameScope(md.getSymbol());
227 for(Iterator matchit=possiblematches.iterator(); matchit.hasNext(); ) {
228 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
230 if (md.matches(matchmd)) {
235 //Not found...walk one level up
236 cn=cn.getSuperDesc();
240 public void addFlag(FlagDescriptor fd) {
241 if (flags.contains(fd.getSymbol()))
242 throw new Error(fd.getSymbol()+" already defined");
247 public boolean hasFlags() {
248 return hasFlags||getSuperDesc()!=null&&getSuperDesc().hasFlags();
251 public void addField(FieldDescriptor fd) {
252 if (fields.contains(fd.getSymbol()))
253 throw new Error(fd.getSymbol()+" already defined");
257 this.incStaticFields();
259 fd.setClassDescriptor(this);
262 public void addMethod(MethodDescriptor md) {
266 public void setModifiers(Modifiers modifiers) {
267 this.modifiers=modifiers;
270 public void setInline() {
274 public boolean getInline() {
278 public void setSuper(String superclass) {
279 this.superclass=superclass;
282 public ClassDescriptor getSuperDesc() {
286 public void setSuperDesc(ClassDescriptor scd) {
290 public String getSuper() {
294 public void addSuperInterface(String superif) {
295 this.superinterfaces.addElement(superif);
298 public Vector<String> getSuperInterface() {
299 return this.superinterfaces;
302 public void addSuperInterfaces(ClassDescriptor sif) {
303 this.superIFdesc.add(sif);
306 public void incStaticBlocks() {
307 this.numstaticblocks++;
310 public int getNumStaticBlocks() {
311 return this.numstaticblocks;
314 public void incStaticFields() {
315 this.numstaticfields++;
318 public int getNumStaticFields() {
319 return this.numstaticfields;
322 public boolean isAbstract() {
323 return this.modifiers.isAbstract();
326 public boolean isInterface() {
327 return (this.classid == -2);
330 public void setInterfaceId(int id) {
331 this.interfaceid = id;
334 public boolean isStatic() {
335 return this.modifiers.isStatic();
338 public void setAsInnerClass() {
339 this.isInnerClass = true;
342 public boolean isInnerClass() {
343 return this.isInnerClass;
346 public void setSurroundingClass(String sclass) {
347 this.surroundingclass=sclass;
350 public String getSurrounding() {
351 return this.surroundingclass;
354 public ClassDescriptor getSurroundingDesc() {
355 return this.surroudingdesc;
358 public void setSurrounding(ClassDescriptor scd) {
359 this.surroudingdesc=scd;
362 public void addInnerClass(ClassDescriptor icd) {
363 this.innerdescs.add(icd);
366 public Iterator getInnerClasses() {
367 return this.innerdescs.getDescriptorsIterator();
370 public SymbolTable getInnerClassTable() {
371 return this.innerdescs;
374 public void setAsEnum() {
378 public boolean isEnum() {
382 public void addEnum(ClassDescriptor icd) {
383 this.enumdescs.add(icd);
386 public Iterator getEnum() {
387 return this.enumdescs.getDescriptorsIterator();
390 public SymbolTable getEnumTable() {
391 return this.enumdescs;
394 public void addEnumConstant(String econstant) {
395 if(this.enumConstantTbl == null) {
396 this.enumConstantTbl = new HashMap<String, Integer>();
398 if(this.enumConstantTbl.containsKey(econstant)) {
401 this.enumConstantTbl.put(econstant, this.enumconstantid++);
406 public int getEnumConstant(String econstant) {
407 if(this.enumConstantTbl.containsKey(econstant)) {
408 return this.enumConstantTbl.get(econstant).intValue();
414 public HashMap<String, Integer> getEnumConstantTbl() {
415 return this.enumConstantTbl;
418 public Modifiers getModifier() {
419 return this.modifiers;
422 public void setSourceFileName(String sourceFileName) {
423 this.sourceFileName=sourceFileName;
426 public void setImports(ChainHashMap singleImports, ChainHashMap multiImports) {
427 this.mandatoryImports = singleImports;
428 this.multiImports = multiImports;
431 public String getSourceFileName() {
432 return this.sourceFileName;
435 public ChainHashMap getSingleImportMappings() {
436 return this.mandatoryImports;
439 public ChainHashMap getMultiImportMappings() {
440 return this.multiImports;
443 //Returns the full name/path of another class referenced from this class via imports.
444 public String getCanonicalImportMapName(String otherClassname) {
445 if(mandatoryImports.containsKey(otherClassname)) {
446 return (String) mandatoryImports.get(otherClassname);
447 } else if(multiImports.containsKey(otherClassname)) {
449 Object o = multiImports.get(otherClassname);
450 if(o instanceof Error) {
451 throw new Error("Class " + otherClassname + " is ambiguous. Cause: more than 1 package import contain the same class.");
453 //At this point, if we found a unique class
454 //we can treat it as a single, mandatory import.
455 mandatoryImports.put(otherClassname, o);
459 return otherClassname;