org.fife.rsta.ac.java.classreader.MethodInfo Maven / Gradle / Ivy
/* * 03/21/2010 * * Copyright (C) 2010 Robert Futrell * robert_futrell at users.sourceforge.net * http://fifesoft.com/rsyntaxtextarea * * This code is licensed under the LGPL. See the "license.txt" file included * with this project. */ package org.fife.rsta.ac.java.classreader; import java.io.*; import java.util.*; import org.fife.rsta.ac.java.classreader.attributes.*; import org.fife.rsta.ac.java.classreader.constantpool.ConstantUtf8Info; /** * Implementation of the "
. * * @return The name and parameters of this method. */ public String getNameAndParameters() { if (nameAndParameters==null) { StringBuffer sb = new StringBuffer(getName()); sb.append('('); int paramCount = getParameterCount(); for (int i=0; imethod_info
" structure as defined in * the JVM specification. * * @author Robert Futrell * @version 1.0 */ public class MethodInfo extends MemberInfo implements AccessFlags { /** * An index into the constant pool of a {@link ConstantUtf8Info} structure * representing either one of the special method names ( * "<init>
" or "<clinit>
") or a * valid method name in the Java programming language, stored as a simple * name. */ private int nameIndex; // u2 /** * An index into the constant pool of a {@link ConstantUtf8Info} structure * representing a valid method descriptor. */ private int descriptorIndex; // u2 /** * Attributes of this method. */ private List attributes; /** * The type of all parameters to this method. If this method takes no * parameters, this will be a zero-length array. */ private String[] paramTypes; /** * Cached return type. */ private String returnType; /** * Cached string representing the name and parameters for this method. */ private String nameAndParameters; /** * Used in class files to denote constructors. */ private static final String SPECIAL_NAME_CONSTRUCTOR = ""; public static final String CODE = "Code"; public static final String EXCEPTIONS = "Exceptions"; /** * Constructor. * * @param cf The class file defining this method. */ public MethodInfo(ClassFile cf, int accessFlags, int nameIndex, int descriptorIndex) { super(cf, accessFlags); this.nameIndex = nameIndex; this.descriptorIndex = descriptorIndex; attributes = new ArrayList(1); // Usually only 0 or 1? } /** * Adds the specified attribute to this field. * * @param info Information about the attribute. */ public void addAttribute(AttributeInfo info) { attributes.add(info); } private void appendParamDescriptors(StringBuffer sb) { String[] paramTypes = getParameterTypes(); for (int i=0; i 0) { // Can't do lastIndexOf() as there may be > 1 array parameter // in the descriptors. // int braceCount = paramDescriptors.lastIndexOf('[') + 1; int braceCount = -1; while (paramDescriptors.charAt(++braceCount) == '['); int pos = braceCount; switch (paramDescriptors.charAt(pos)) { // BaseType case 'B': type = "byte"; pos++; break; case 'C': type = "char"; pos++; break; case 'D': type = "double"; pos++; break; case 'F': type = "float"; pos++; break; case 'I': type = "int"; pos++; break; case 'J': type = "long"; pos++; break; case 'S': type = "short"; pos++; break; case 'Z': type = "boolean"; pos++; break; // ObjectType case 'L': String clazz = paramDescriptors.substring(pos + 1, paramDescriptors.indexOf(';')); clazz = clazz.replaceAll("/", "."); type = clazz; pos += clazz.length() + 2; // "+2" for the 'L' & semicolon break; // Invalid method descriptor default: String temp = "INVALID_TYPE_" + paramDescriptors; type = temp; pos += paramDescriptors.length(); break; } for (int i = 0; i < braceCount; i++) { type += "[]"; } paramTypeList.add(type); paramDescriptors = paramDescriptors.substring(pos); } String[] types = new String[paramTypeList.size()]; types = (String[])paramTypeList.toArray(types); return types; } /** * Returns the specified attribute. * * @param index The index of the attribute. * @return The attribute. */ public AttributeInfo getAttribute(int index) { return (AttributeInfo)attributes.get(index); } /** * Returns the number of attributes of this field. * * @return The number of attributes. */ public int getAttributeCount() { return attributes.size(); } /** * Returns the {@link Code} attribute for this method. * * @return The Code
attribute. This may benull
* if this method is abstract or native. */ public Code getCodeAttribute() { for (int i=0; iperformAction(String, int, Runnable) -1) { type = type.substring(dot+1); } } return type; } /** * Returns an array if strings representing the types of all parameters * to this method. If this method takes no parameters, a zero-length * array is returned. * * @return The array. These types will likely be fully qualified. * @see #getParameterCount() * @see #getParameterType(int, boolean) */ public String[] getParameterTypes() { if (paramTypes==null) { paramTypes = createParamTypes(); } return (String[])paramTypes.clone(); } /** * Returns the return type of this method, as determined by a snippet * of the method descriptor. * * @return The return type of this method. */ /* * TODO: This is identical to FieldInfo.getTypeString(), except for the * 'V' case. It is also very similar to #getParameterTypes(). Try * to refactor common code from these methods. */ public String getReturnTypeString() { if (returnType==null) { String descriptor = getDescriptor(); int rparen = descriptor.indexOf(')'); descriptor = descriptor.substring(rparen+1); // return type desc. StringBuffer sb = new StringBuffer(); int braceCount = descriptor.lastIndexOf('[') + 1; switch (descriptor.charAt(braceCount)) { // BaseType case 'B': sb.append("byte"); break; case 'C': sb.append("char"); break; case 'D': sb.append("double"); break; case 'F': sb.append("float"); break; case 'I': sb.append("int"); break; case 'J': sb.append("long"); break; case 'S': sb.append("short"); break; case 'Z': sb.append("boolean"); break; case 'V': sb.append("void"); break; // ObjectType case 'L': String clazz = descriptor.substring(1, descriptor.length()-1); clazz = clazz.replaceAll("/", "."); sb.append(clazz); break; // Invalid field descriptor default: sb.append("UNSUPPORTED_TYPE_").append(descriptor); break; } for (int i=0; i 0; } /** * Returns whether this method is a constructor. * * @return Whether this method is a constructor. */ public boolean isConstructor() { String name = cf.getUtf8ValueFromConstantPool(nameIndex); return SPECIAL_NAME_CONSTRUCTOR.equals(name); } /** * Returns whether this method is native. * * @return Whether this method is native. */ public boolean isNative() { return (getAccessFlags()&ACC_NATIVE)>0; } /** * Returns whether this method is static. * * @return Whether this method is static. */ public boolean isStatic() { return (getAccessFlags()&ACC_STATIC)>0; } /** * Reads a MethodInfo
from an input stream. * * @param cf The class file defining the method. * @param in The input stream to read from. * @return The method information read. * @throws IOException If an IO error occurs. */ public static MethodInfo read(ClassFile cf, DataInputStream in) throws IOException { int accessFlags = in.readUnsignedShort(); int nameIndex = in.readUnsignedShort(); int descriptorIndex = in.readUnsignedShort(); MethodInfo mi = new MethodInfo(cf, accessFlags, nameIndex, descriptorIndex); int attrCount = in.readUnsignedShort(); for (int j=0; j0) { exceptionIndexTable = new int[exceptionCount]; for (int i=0; i >> " + attributeLength); // int u4 = in.readUnsignedShort(); // String sig = cf.getUtf8ValueFromConstantPool(u4); // System.err.println(">>> >>> " + sig); // } // TODO: Handle other Attribute types. // Attributes common to all members, or unhandled attributes. else { ai = super.readAttribute(in, attrName, attributeLength); } return ai; } }