annotate src/clojure/asm/commons/Method.java @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
rev   line source
rlm@10 1 /***
rlm@10 2 * ASM: a very small and fast Java bytecode manipulation framework
rlm@10 3 * Copyright (c) 2000-2005 INRIA, France Telecom
rlm@10 4 * All rights reserved.
rlm@10 5 *
rlm@10 6 * Redistribution and use in source and binary forms, with or without
rlm@10 7 * modification, are permitted provided that the following conditions
rlm@10 8 * are met:
rlm@10 9 * 1. Redistributions of source code must retain the above copyright
rlm@10 10 * notice, this list of conditions and the following disclaimer.
rlm@10 11 * 2. Redistributions in binary form must reproduce the above copyright
rlm@10 12 * notice, this list of conditions and the following disclaimer in the
rlm@10 13 * documentation and/or other materials provided with the distribution.
rlm@10 14 * 3. Neither the name of the copyright holders nor the names of its
rlm@10 15 * contributors may be used to endorse or promote products derived from
rlm@10 16 * this software without specific prior written permission.
rlm@10 17 *
rlm@10 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
rlm@10 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
rlm@10 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
rlm@10 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
rlm@10 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
rlm@10 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
rlm@10 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
rlm@10 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
rlm@10 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
rlm@10 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
rlm@10 28 * THE POSSIBILITY OF SUCH DAMAGE.
rlm@10 29 */
rlm@10 30 package clojure.asm.commons;
rlm@10 31
rlm@10 32 import java.util.HashMap;
rlm@10 33 import java.util.Map;
rlm@10 34
rlm@10 35 import clojure.asm.Type;
rlm@10 36
rlm@10 37 /**
rlm@10 38 * A named method descriptor.
rlm@10 39 *
rlm@10 40 * @author Juozas Baliuka
rlm@10 41 * @author Chris Nokleberg
rlm@10 42 * @author Eric Bruneton
rlm@10 43 */
rlm@10 44 public class Method{
rlm@10 45
rlm@10 46 /**
rlm@10 47 * The method name.
rlm@10 48 */
rlm@10 49 private final String name;
rlm@10 50
rlm@10 51 /**
rlm@10 52 * The method descriptor.
rlm@10 53 */
rlm@10 54 private final String desc;
rlm@10 55
rlm@10 56 /**
rlm@10 57 * Maps primitive Java type names to their descriptors.
rlm@10 58 */
rlm@10 59 private final static Map DESCRIPTORS;
rlm@10 60
rlm@10 61 static
rlm@10 62 {
rlm@10 63 DESCRIPTORS = new HashMap();
rlm@10 64 DESCRIPTORS.put("void", "V");
rlm@10 65 DESCRIPTORS.put("byte", "B");
rlm@10 66 DESCRIPTORS.put("char", "C");
rlm@10 67 DESCRIPTORS.put("double", "D");
rlm@10 68 DESCRIPTORS.put("float", "F");
rlm@10 69 DESCRIPTORS.put("int", "I");
rlm@10 70 DESCRIPTORS.put("long", "J");
rlm@10 71 DESCRIPTORS.put("short", "S");
rlm@10 72 DESCRIPTORS.put("boolean", "Z");
rlm@10 73 }
rlm@10 74
rlm@10 75 /**
rlm@10 76 * Creates a new {@link Method}.
rlm@10 77 *
rlm@10 78 * @param name the method's name.
rlm@10 79 * @param desc the method's descriptor.
rlm@10 80 */
rlm@10 81 public Method(final String name, final String desc){
rlm@10 82 this.name = name;
rlm@10 83 this.desc = desc;
rlm@10 84 }
rlm@10 85
rlm@10 86 /**
rlm@10 87 * Creates a new {@link Method}.
rlm@10 88 *
rlm@10 89 * @param name the method's name.
rlm@10 90 * @param returnType the method's return type.
rlm@10 91 * @param argumentTypes the method's argument types.
rlm@10 92 */
rlm@10 93 public Method(
rlm@10 94 final String name,
rlm@10 95 final Type returnType,
rlm@10 96 final Type[] argumentTypes){
rlm@10 97 this(name, Type.getMethodDescriptor(returnType, argumentTypes));
rlm@10 98 }
rlm@10 99
rlm@10 100 /**
rlm@10 101 * Returns a {@link Method} corresponding to the given Java method
rlm@10 102 * declaration.
rlm@10 103 *
rlm@10 104 * @param method a Java method declaration, without argument names, of the
rlm@10 105 * form "returnType name (argumentType1, ... argumentTypeN)", where
rlm@10 106 * the types are in plain Java (e.g. "int", "float",
rlm@10 107 * "java.util.List", ...). Classes of the java.lang package can be
rlm@10 108 * specified by their unqualified name; all other classes names must
rlm@10 109 * be fully qualified.
rlm@10 110 * @return a {@link Method} corresponding to the given Java method
rlm@10 111 * declaration.
rlm@10 112 * @throws IllegalArgumentException if <code>method</code> could not get
rlm@10 113 * parsed.
rlm@10 114 */
rlm@10 115 public static Method getMethod(final String method)
rlm@10 116 throws IllegalArgumentException{
rlm@10 117 return getMethod(method, false);
rlm@10 118 }
rlm@10 119
rlm@10 120 /**
rlm@10 121 * Returns a {@link Method} corresponding to the given Java method
rlm@10 122 * declaration.
rlm@10 123 *
rlm@10 124 * @param method a Java method declaration, without argument names, of the
rlm@10 125 * form "returnType name (argumentType1, ... argumentTypeN)", where
rlm@10 126 * the types are in plain Java (e.g. "int", "float",
rlm@10 127 * "java.util.List", ...). Classes of the java.lang package may be
rlm@10 128 * specified by their unqualified name, depending on the
rlm@10 129 * defaultPackage argument; all other classes names must be fully
rlm@10 130 * qualified.
rlm@10 131 * @param defaultPackage true if unqualified class names belong to the
rlm@10 132 * default package, or false if they correspond to java.lang classes.
rlm@10 133 * For instance "Object" means "Object" if this option is true, or
rlm@10 134 * "java.lang.Object" otherwise.
rlm@10 135 * @return a {@link Method} corresponding to the given Java method
rlm@10 136 * declaration.
rlm@10 137 * @throws IllegalArgumentException if <code>method</code> could not get
rlm@10 138 * parsed.
rlm@10 139 */
rlm@10 140 public static Method getMethod(
rlm@10 141 final String method,
rlm@10 142 final boolean defaultPackage) throws IllegalArgumentException{
rlm@10 143 int space = method.indexOf(' ');
rlm@10 144 int start = method.indexOf('(', space) + 1;
rlm@10 145 int end = method.indexOf(')', start);
rlm@10 146 if(space == -1 || start == -1 || end == -1)
rlm@10 147 {
rlm@10 148 throw new IllegalArgumentException();
rlm@10 149 }
rlm@10 150 // TODO: Check validity of returnType, methodName and arguments.
rlm@10 151 String returnType = method.substring(0, space);
rlm@10 152 String methodName = method.substring(space + 1, start - 1).trim();
rlm@10 153 StringBuffer sb = new StringBuffer();
rlm@10 154 sb.append('(');
rlm@10 155 int p;
rlm@10 156 do
rlm@10 157 {
rlm@10 158 String s;
rlm@10 159 p = method.indexOf(',', start);
rlm@10 160 if(p == -1)
rlm@10 161 {
rlm@10 162 s = map(method.substring(start, end).trim(), defaultPackage);
rlm@10 163 }
rlm@10 164 else
rlm@10 165 {
rlm@10 166 s = map(method.substring(start, p).trim(), defaultPackage);
rlm@10 167 start = p + 1;
rlm@10 168 }
rlm@10 169 sb.append(s);
rlm@10 170 } while(p != -1);
rlm@10 171 sb.append(')');
rlm@10 172 sb.append(map(returnType, defaultPackage));
rlm@10 173 return new Method(methodName, sb.toString());
rlm@10 174 }
rlm@10 175
rlm@10 176 private static String map(final String type, final boolean defaultPackage){
rlm@10 177 if(type.equals(""))
rlm@10 178 {
rlm@10 179 return type;
rlm@10 180 }
rlm@10 181
rlm@10 182 StringBuffer sb = new StringBuffer();
rlm@10 183 int index = 0;
rlm@10 184 while((index = type.indexOf("[]", index) + 1) > 0)
rlm@10 185 {
rlm@10 186 sb.append('[');
rlm@10 187 }
rlm@10 188
rlm@10 189 String t = type.substring(0, type.length() - sb.length() * 2);
rlm@10 190 String desc = (String) DESCRIPTORS.get(t);
rlm@10 191 if(desc != null)
rlm@10 192 {
rlm@10 193 sb.append(desc);
rlm@10 194 }
rlm@10 195 else
rlm@10 196 {
rlm@10 197 sb.append('L');
rlm@10 198 if(t.indexOf('.') < 0)
rlm@10 199 {
rlm@10 200 if(!defaultPackage)
rlm@10 201 {
rlm@10 202 sb.append("java/lang/");
rlm@10 203 }
rlm@10 204 sb.append(t);
rlm@10 205 }
rlm@10 206 else
rlm@10 207 {
rlm@10 208 sb.append(t.replace('.', '/'));
rlm@10 209 }
rlm@10 210 sb.append(';');
rlm@10 211 }
rlm@10 212 return sb.toString();
rlm@10 213 }
rlm@10 214
rlm@10 215 /**
rlm@10 216 * Returns the name of the method described by this object.
rlm@10 217 *
rlm@10 218 * @return the name of the method described by this object.
rlm@10 219 */
rlm@10 220 public String getName(){
rlm@10 221 return name;
rlm@10 222 }
rlm@10 223
rlm@10 224 /**
rlm@10 225 * Returns the descriptor of the method described by this object.
rlm@10 226 *
rlm@10 227 * @return the descriptor of the method described by this object.
rlm@10 228 */
rlm@10 229 public String getDescriptor(){
rlm@10 230 return desc;
rlm@10 231 }
rlm@10 232
rlm@10 233 /**
rlm@10 234 * Returns the return type of the method described by this object.
rlm@10 235 *
rlm@10 236 * @return the return type of the method described by this object.
rlm@10 237 */
rlm@10 238 public Type getReturnType(){
rlm@10 239 return Type.getReturnType(desc);
rlm@10 240 }
rlm@10 241
rlm@10 242 /**
rlm@10 243 * Returns the argument types of the method described by this object.
rlm@10 244 *
rlm@10 245 * @return the argument types of the method described by this object.
rlm@10 246 */
rlm@10 247 public Type[] getArgumentTypes(){
rlm@10 248 return Type.getArgumentTypes(desc);
rlm@10 249 }
rlm@10 250
rlm@10 251 public String toString(){
rlm@10 252 return name + desc;
rlm@10 253 }
rlm@10 254
rlm@10 255 public boolean equals(final Object o){
rlm@10 256 if(!(o instanceof Method))
rlm@10 257 {
rlm@10 258 return false;
rlm@10 259 }
rlm@10 260 Method other = (Method) o;
rlm@10 261 return name.equals(other.name) && desc.equals(other.desc);
rlm@10 262 }
rlm@10 263
rlm@10 264 public int hashCode(){
rlm@10 265 return name.hashCode() ^ desc.hashCode();
rlm@10 266 }
rlm@10 267 }