1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.dx; 18 19 import com.android.dx.rop.cst.CstMethodRef; 20 import com.android.dx.rop.cst.CstNat; 21 import com.android.dx.rop.cst.CstString; 22 import com.android.dx.rop.type.Prototype; 23 import java.util.List; 24 25 /** 26 * Identifies a method or constructor. 27 * 28 * @param <D> the type declaring this field 29 * @param <R> the return type of this method 30 */ 31 public final class MethodId<D, R> { 32 final TypeId<D> declaringType; 33 final TypeId<R> returnType; 34 final String name; 35 final TypeList parameters; 36 37 /** cached converted state */ 38 final CstNat nat; 39 final CstMethodRef constant; 40 41 MethodId(TypeId<D> declaringType, TypeId<R> returnType, String name, TypeList parameters) { 42 if (declaringType == null || returnType == null || name == null || parameters == null) { 43 throw new NullPointerException(); 44 } 45 this.declaringType = declaringType; 46 this.returnType = returnType; 47 this.name = name; 48 this.parameters = parameters; 49 this.nat = new CstNat(new CstString(name), new CstString(descriptor(false))); 50 this.constant = new CstMethodRef(declaringType.constant, nat); 51 } 52 53 public TypeId<D> getDeclaringType() { 54 return declaringType; 55 } 56 57 public TypeId<R> getReturnType() { 58 return returnType; 59 } 60 61 /** 62 * Returns true if this method is a constructor for its declaring class. 63 */ 64 public boolean isConstructor() { 65 return name.equals("<init>"); 66 } 67 68 /** 69 * Returns true if this method is the static initializer for its declaring class. 70 */ 71 public boolean isStaticInitializer() { 72 return name.equals("<clinit>"); 73 } 74 75 /** 76 * Returns the method's name. This is "<init>" if this is a constructor 77 * or "<clinit>" if a static initializer 78 */ 79 public String getName() { 80 return name; 81 } 82 83 public List<TypeId<?>> getParameters() { 84 return parameters.asList(); 85 } 86 87 /** 88 * Returns a descriptor like "(Ljava/lang/Class;[I)Ljava/lang/Object;". 89 */ 90 String descriptor(boolean includeThis) { 91 StringBuilder result = new StringBuilder(); 92 result.append("("); 93 if (includeThis) { 94 result.append(declaringType.name); 95 } 96 for (TypeId t : parameters.types) { 97 result.append(t.name); 98 } 99 result.append(")"); 100 result.append(returnType.name); 101 return result.toString(); 102 } 103 104 Prototype prototype(boolean includeThis) { 105 return Prototype.intern(descriptor(includeThis)); 106 } 107 108 @Override 109 public boolean equals(Object o) { 110 return o instanceof MethodId 111 && ((MethodId<?, ?>) o).declaringType.equals(declaringType) 112 && ((MethodId<?, ?>) o).name.equals(name) 113 && ((MethodId<?, ?>) o).parameters.equals(parameters) 114 && ((MethodId<?, ?>) o).returnType.equals(returnType); 115 } 116 117 @Override 118 public int hashCode() { 119 int result = 17; 120 result = 31 * result + declaringType.hashCode(); 121 result = 31 * result + name.hashCode(); 122 result = 31 * result + parameters.hashCode(); 123 result = 31 * result + returnType.hashCode(); 124 return result; 125 } 126 127 @Override 128 public String toString() { 129 return declaringType + "." + name + "(" + parameters + ")"; 130 } 131 } 132