1 cananian 1.6.2.2  // HMethodSyn.java, created Fri Oct 16  2:21:03 1998 by cananian
  2 cananian 1.1      // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu>
  3 cananian 1.1      // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 cananian 1.1      package harpoon.ClassFile;
  5 cananian 1.1      
  6 cananian 1.6.2.6  import harpoon.Util.Util;
  7 cananian 1.6.2.6  
  8 cananian 1.1      import java.lang.reflect.Modifier;
  9 cananian 1.6      import java.util.Enumeration;
 10 cananian 1.1      import java.util.Hashtable;
 11 cananian 1.1      import java.util.Vector;
 12 cananian 1.1      /**
 13 cananian 1.1       * An <code>HMethodSyn</code> provides information about, and access to, a 
 14 cananian 1.1       * single method on a class or interface.  The reflected method
 15 cananian 1.1       * may be a class method or an instance method (including an abstract
 16 cananian 1.1       * method).
 17 cananian 1.1       * 
 18 cananian 1.1       * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 19 cananian 1.9       * @version $Id: HMethodSyn.java,v 1.9 2002/04/10 03:04:15 cananian Exp $
 20 cananian 1.1       * @see HMember
 21 cananian 1.1       * @see HClass
 22 cananian 1.1       */
 23 cananian 1.6.2.6  class HMethodSyn extends HMethodImpl implements HMethodMutator {
 24 cananian 1.1      
 25 cananian 1.6.2.6    /** Create a new method like the <code>template</code>, but named
 26 cananian 1.6.2.6     *  <code>name</code>.
 27 cananian 1.6         *  The new method will be added to class <code>parent</code>. */
 28 cananian 1.6.2.6    HMethodSyn(HClassSyn parent, String name, HMethod template) {
 29 cananian 1.6.2.11     this ((HClass)parent, name, template);
 30 cananian 1.6.2.11   }
 31 cananian 1.6.2.11   HMethodSyn(HClassArraySyn parent, String name, HMethod template) {
 32 cananian 1.6.2.11     this ((HClass)parent, name, template);
 33 cananian 1.6        }
 34 cananian 1.6.2.11   // private, not-as-type-safe implementation.
 35 cananian 1.6.2.11   private HMethodSyn(HClass parent, String name, HMethod template) {
 36 cananian 1.6          this.parent = parent;
 37 cananian 1.6.2.6      this.name = name;
 38 cananian 1.1          this.modifiers = template.getModifiers();
 39 cananian 1.1          this.returnType = template.getReturnType();
 40 cananian 1.1          this.parameterTypes = template.getParameterTypes();
 41 cananian 1.1          this.parameterNames = template.getParameterNames();
 42 cananian 1.1          this.exceptionTypes = template.getExceptionTypes();
 43 cananian 1.1          this.isSynthetic = template.isSynthetic();
 44 cananian 1.6.2.8      // ensure linker information is consistent.
 45 cananian 1.8.2.1      assert checkLinker((HClass)this.returnType);
 46 cananian 1.6.2.8      for(int i=0; i<this.parameterTypes.length; i++)
 47 cananian 1.8.2.1        assert checkLinker((HClass)this.parameterTypes[i]);
 48 cananian 1.6.2.8      for(int i=0; i<this.exceptionTypes.length; i++)
 49 cananian 1.8.2.1        assert checkLinker((HClass)this.exceptionTypes[i]);
 50 nkushman 1.4        }
 51 nkushman 1.4      
 52 cananian 1.6.2.6    /** Create a new empty method in the specified class
 53 nkushman 1.4         *  with the specified parameter and return types
 54 nkushman 1.4         *  that throws no checked exceptions.
 55 nkushman 1.4         */
 56 cananian 1.6.2.6    HMethodSyn(HClassSyn parent, String name, 
 57 cananian 1.6                          HClass[] paramTypes, HClass returnType) {
 58 nkushman 1.4          this(parent, name, makeDescriptor (paramTypes, returnType));
 59 nkushman 1.4        }
 60 cananian 1.6.2.11   HMethodSyn(HClassArraySyn parent, String name, 
 61 cananian 1.6                          HClass[] paramTypes, HClass returnType) {
 62 nkushman 1.4          this(parent, name, makeDescriptor (paramTypes, returnType));
 63 nkushman 1.4        }
 64 nkushman 1.4        
 65 cananian 1.6.2.6    /** Create a new empty method in the specified class
 66 cananian 1.2         *  with the specified descriptor
 67 cananian 1.2         *  that throws no checked exceptions.
 68 cananian 1.1         */
 69 cananian 1.6.2.6    HMethodSyn(HClassSyn parent, String name, String descriptor) {
 70 cananian 1.6.2.11     this((HClass)parent, name, descriptor);
 71 cananian 1.6.2.11   }
 72 cananian 1.6.2.11   HMethodSyn(HClassArraySyn parent, String name, String descriptor) {
 73 cananian 1.6.2.11     this((HClass)parent, name, descriptor);
 74 cananian 1.6.2.11   }
 75 cananian 1.6.2.11   // private, not-as-type-safe implementation.
 76 cananian 1.6.2.11   private HMethodSyn(HClass parent, String name, String descriptor) {
 77 cananian 1.1          this.parent = parent;
 78 cananian 1.6.2.6      this.name = name;
 79 cananian 1.6.2.6      this.modifiers = 0;
 80 cananian 1.2          { // parse descriptor for return type.
 81 cananian 1.2            String desc = descriptor.substring(descriptor.lastIndexOf(')')+1);
 82 cananian 1.6.2.12       this.returnType = new ClassPointer(parent.getLinker(), desc);
 83 cananian 1.2          }
 84 cananian 1.2          { // parse descriptor for parameter types.
 85 cananian 1.2            String desc = descriptor.substring(1, descriptor.lastIndexOf(')'));
 86 cananian 1.2            Vector v = new Vector();
 87 cananian 1.2            for (int i=0; i<desc.length(); i++) {
 88 cananian 1.6.2.12         int first = i;
 89 cananian 1.2              while (desc.charAt(i)=='[') i++;
 90 cananian 1.2              if (desc.charAt(i)=='L') i=desc.indexOf(';', i);
 91 cananian 1.6.2.12         v.addElement(new ClassPointer(parent.getLinker(),
 92 cananian 1.6.2.12                                       desc.substring(first, i+1)));
 93 cananian 1.2            }
 94 cananian 1.6.2.12       this.parameterTypes = new HPointer[v.size()];
 95 cananian 1.2            v.copyInto(this.parameterTypes);
 96 cananian 1.2          }
 97 cananian 1.2          this.parameterNames = new String[this.parameterTypes.length];
 98 cananian 1.1          this.exceptionTypes = new HClass[0];
 99 cananian 1.1          this.isSynthetic = false;
100 cananian 1.1        }
101 cananian 1.1      
102 cananian 1.6.2.6    public HMethodMutator getMutator() { return this; }
103 cananian 1.1      
104 cananian 1.6.2.6    public void addModifiers(int m) { setModifiers(getModifiers()|m); }
105 cananian 1.6.2.6    public void removeModifiers(int m) { setModifiers(getModifiers()&(~m)); }
106 cananian 1.6.2.6    public void setModifiers(int m) {
107 cananian 1.6.2.6      if (this.modifiers != m) parent.hasBeenModified = true;
108 cananian 1.6.2.6      this.modifiers = m;
109 cananian 1.6.2.6    }
110 cananian 1.1      
111 cananian 1.6.2.6    public void setReturnType(HClass returnType) {
112 cananian 1.8.2.1      assert checkLinker(returnType);
113 cananian 1.6.2.6      if (this.returnType != returnType) parent.hasBeenModified = true;
114 cananian 1.6.2.6      this.returnType = returnType;
115 cananian 1.6.2.6    }
116 cananian 1.1      
117 cananian 1.2        /** Warning: use can cause method name conflicts in class. */
118 cananian 1.1        public void setParameterTypes(HClass[] parameterTypes) {
119 cananian 1.6.2.8      for (int i=0; i<parameterTypes.length; i++)
120 cananian 1.8.2.1        assert checkLinker(parameterTypes[i]);
121 cananian 1.6.2.6      if (this.parameterTypes.length != parameterTypes.length)
122 cananian 1.6.2.6        parent.hasBeenModified = true;
123 cananian 1.6.2.6      else for (int i=0;
124 cananian 1.6.2.6                i<this.parameterTypes.length && i<parameterTypes.length; i++)
125 cananian 1.6.2.6        if (this.parameterTypes[i] != parameterTypes[i])
126 cananian 1.6.2.6          parent.hasBeenModified = true;
127 cananian 1.1          this.parameterTypes = parameterTypes;
128 cananian 1.1        }
129 cananian 1.2        /** Warning: use can cause method name conflicts in class. */
130 cananian 1.1        public void setParameterType(int which, HClass type) {
131 cananian 1.8.2.1      assert checkLinker(type);
132 cananian 1.6.2.6      if (this.parameterTypes[which] != type)
133 cananian 1.6.2.6        parent.hasBeenModified = true;
134 cananian 1.1          this.parameterTypes[which] = type;
135 cananian 1.1        }
136 cananian 1.1      
137 cananian 1.1        public void setParameterNames(String[] parameterNames) {
138 cananian 1.1          this.parameterNames = parameterNames;
139 cananian 1.1        }
140 cananian 1.1        public void setParameterName(int which, String name) {
141 cananian 1.1          this.parameterNames[which] = name;
142 cananian 1.1        }
143 cananian 1.1      
144 cananian 1.6.2.6    public void addExceptionType(HClass exceptionType) {
145 cananian 1.8.2.1      assert checkLinker(exceptionType);
146 cananian 1.6.2.6      for (int i=0; i<exceptionTypes.length; i++)
147 cananian 1.6.2.6        if (exceptionTypes[i]==exceptionType)
148 cananian 1.6.2.6          return;
149 cananian 1.6.2.6      this.exceptionTypes = (HPointer[]) Util.grow(HPointer.arrayFactory,
150 cananian 1.6.2.6                                                   exceptionTypes, exceptionType,
151 cananian 1.6.2.6                                                   exceptionTypes.length);
152 cananian 1.6.2.6      parent.hasBeenModified = true;
153 cananian 1.6.2.6    }
154 cananian 1.1        public void setExceptionTypes(HClass[] exceptionTypes) {
155 cananian 1.6.2.8      for (int i=0; i<exceptionTypes.length; i++)
156 cananian 1.8.2.1        assert checkLinker(exceptionTypes[i]);
157 cananian 1.6.2.6      if (this.exceptionTypes.length != exceptionTypes.length)
158 cananian 1.6.2.6        parent.hasBeenModified = true;
159 cananian 1.6.2.6      else for (int i=0;
160 cananian 1.6.2.6                i<this.exceptionTypes.length && i<exceptionTypes.length; i++)
161 cananian 1.6.2.6        if (this.exceptionTypes[i] != exceptionTypes[i])
162 cananian 1.6.2.6          parent.hasBeenModified = true;
163 cananian 1.1          this.exceptionTypes = exceptionTypes;
164 cananian 1.1        }
165 cananian 1.6.2.6    public void removeExceptionType(HClass exceptionType) {
166 cananian 1.8.2.1      assert checkLinker(exceptionType);
167 cananian 1.6.2.6      for (int i=0; i<exceptionTypes.length; i++)
168 cananian 1.6.2.6        if (exceptionTypes[i].actual().equals(exceptionType)) {
169 cananian 1.6.2.6          exceptionTypes = (HPointer[]) Util.shrink(HPointer.arrayFactory,
170 cananian 1.6.2.6                                                    exceptionTypes, i);
171 cananian 1.6.2.6          parent.hasBeenModified = true;
172 cananian 1.6.2.6          return;
173 cananian 1.6.2.6        }
174 cananian 1.1        }
175 cananian 1.1      
176 cananian 1.1        public void setSynthetic(boolean isSynthetic) {
177 cananian 1.6.2.6      if (this.isSynthetic != isSynthetic) parent.hasBeenModified = true;
178 cananian 1.1          this.isSynthetic = isSynthetic;
179 cananian 1.3        }
180 cananian 1.3      
181 cananian 1.6        //----------------------------------------------------------
182 cananian 1.6      
183 cananian 1.6.2.6    /** Make a method descriptor string given parameter and return value types.
184 cananian 1.6         *  A helper function. */
185 cananian 1.6.2.4    static String makeDescriptor(HClass[] paramTypes, HClass returnType){
186 cananian 1.6          StringBuffer sb = new StringBuffer();
187 cananian 1.6          sb.append ('(');
188 cananian 1.6          for (int i = 0; i < paramTypes.length; i++){
189 cananian 1.6            sb.append (paramTypes[i].getDescriptor());
190 cananian 1.6          }
191 cananian 1.6          sb.append (')');
192 cananian 1.6          sb.append (returnType.getDescriptor());
193 cananian 1.6          return  sb.toString();
194 cananian 1.1        }
195 cananian 1.6.2.3  
196 cananian 1.6.2.9    //----------------------------------------------------------
197 cananian 1.6.2.9    // assertion helper.
198 cananian 1.6.2.9    private boolean checkLinker(HClass hc) {
199 cananian 1.6.2.9      return hc.isPrimitive() || hc.getLinker()==parent.getLinker();
200 cananian 1.6.2.9    }
201 cananian 1.6.2.3    //----------------------------------------------------------
202 cananian 1.1      }
203 cananian 1.1      
204 cananian 1.1      // set emacs indentation style.
205 cananian 1.1      // Local Variables:
206 cananian 1.1      // c-basic-offset:2
207 cananian 1.1      // End: