1 /* 2 * Copyright (C) 2009 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.mkstubs.sourcer; 18 19 import com.android.mkstubs.Main; 20 21 import org.objectweb.asm.AnnotationVisitor; 22 import org.objectweb.asm.Attribute; 23 import org.objectweb.asm.Label; 24 import org.objectweb.asm.MethodVisitor; 25 import org.objectweb.asm.Type; 26 import org.objectweb.asm.signature.SignatureReader; 27 28 import java.util.ArrayList; 29 30 /** 31 * A method visitor that generates the Java source for a whole method. 32 */ 33 class MethodSourcer extends MethodVisitor { 34 35 private final Output mOutput; 36 private final int mAccess; 37 private final String mClassName; 38 private final String mName; 39 private final String mDesc; 40 private final String mSignature; 41 private final String[] mExceptions; 42 private boolean mNeedDeclaration; 43 private boolean mIsConstructor; 44 MethodSourcer(Output output, String className, int access, String name, String desc, String signature, String[] exceptions)45 public MethodSourcer(Output output, String className, int access, String name, 46 String desc, String signature, String[] exceptions) { 47 super(Main.ASM_VERSION); 48 mOutput = output; 49 mClassName = className; 50 mAccess = access; 51 mName = name; 52 mDesc = desc; 53 mSignature = signature; 54 mExceptions = exceptions; 55 56 mNeedDeclaration = true; 57 mIsConstructor = "<init>".equals(name); 58 } 59 writeHeader()60 private void writeHeader() { 61 if (!mNeedDeclaration) { 62 return; 63 } 64 65 AccessSourcer as = new AccessSourcer(mOutput); 66 as.write(mAccess, AccessSourcer.IS_METHOD); 67 68 // preprocess the signature to get the return type and the arguments 69 SignatureSourcer sigSourcer = null; 70 if (mSignature != null) { 71 SignatureReader sigReader = new SignatureReader(mSignature); 72 sigSourcer = new SignatureSourcer(); 73 sigReader.accept(sigSourcer); 74 75 if (sigSourcer.hasFormalsContent()) { 76 // dump formal template parameter definitions 77 mOutput.write(" %s", sigSourcer.formalsToString()); 78 } 79 } 80 81 // output return type (constructor have no return type) 82 if (!mIsConstructor) { 83 // The signature overrides desc, if present 84 if (sigSourcer == null || sigSourcer.getReturnType() == null) { 85 mOutput.write(" %s", Type.getReturnType(mDesc).getClassName()); 86 87 } else { 88 mOutput.write(" %s", sigSourcer.getReturnType().toString()); 89 } 90 } 91 92 // output name 93 mOutput.write(" %s(", mIsConstructor ? mClassName : mName); 94 95 // output arguments. The signature overrides desc, if present 96 if (mSignature == null) { 97 Type[] types = Type.getArgumentTypes(mDesc); 98 99 for(int i = 0; i < types.length; i++) { 100 if (i > 0) { 101 mOutput.write(", "); 102 } 103 mOutput.write("%s arg%d", types[i].getClassName(), i); 104 } 105 } else { 106 ArrayList<SignatureSourcer> params = sigSourcer.getParameters(); 107 108 for(int i = 0; i < params.size(); i++) { 109 if (i > 0) { 110 mOutput.write(", "); 111 } 112 mOutput.write("%s arg%d", params.get(i).toString(), i); 113 } 114 } 115 mOutput.write(")"); 116 117 // output throwable exceptions 118 if (mExceptions != null && mExceptions.length > 0) { 119 mOutput.write(" throws "); 120 121 for (int i = 0; i < mExceptions.length; i++) { 122 if (i > 0) { 123 mOutput.write(", "); 124 } 125 mOutput.write(mExceptions[i].replace('/', '.')); 126 } 127 } 128 129 mOutput.write(" {\n"); 130 131 mNeedDeclaration = false; 132 } 133 134 @Override visitCode()135 public void visitCode() { 136 writeHeader(); 137 138 // write the stub itself 139 mOutput.write("throw new RuntimeException(\"Stub\");"); 140 } 141 142 @Override visitEnd()143 public void visitEnd() { 144 writeHeader(); 145 mOutput.write("\n}\n"); 146 } 147 148 @Override visitAnnotation(String desc, boolean visible)149 public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 150 mOutput.write("@%s", desc); 151 return new AnnotationSourcer(mOutput); 152 } 153 154 @Override visitAnnotationDefault()155 public AnnotationVisitor visitAnnotationDefault() { 156 // pass 157 return null; 158 } 159 160 @Override visitAttribute(Attribute attr)161 public void visitAttribute(Attribute attr) { 162 mOutput.write("%s /* non-standard method attribute */ ", attr.type); 163 } 164 165 @Override visitFieldInsn(int opcode, String owner, String name, String desc)166 public void visitFieldInsn(int opcode, String owner, String name, String desc) { 167 // pass 168 } 169 170 @Override visitFrame(int type, int local, Object[] local2, int stack, Object[] stack2)171 public void visitFrame(int type, int local, Object[] local2, int stack, Object[] stack2) { 172 // pass 173 } 174 175 @Override visitIincInsn(int var, int increment)176 public void visitIincInsn(int var, int increment) { 177 // pass 178 } 179 180 @Override visitInsn(int opcode)181 public void visitInsn(int opcode) { 182 // pass 183 } 184 185 @Override visitIntInsn(int opcode, int operand)186 public void visitIntInsn(int opcode, int operand) { 187 // pass 188 } 189 190 @Override visitJumpInsn(int opcode, Label label)191 public void visitJumpInsn(int opcode, Label label) { 192 // pass 193 } 194 195 @Override visitLabel(Label label)196 public void visitLabel(Label label) { 197 // pass 198 } 199 200 @Override visitLdcInsn(Object cst)201 public void visitLdcInsn(Object cst) { 202 // pass 203 } 204 205 @Override visitLineNumber(int line, Label start)206 public void visitLineNumber(int line, Label start) { 207 // pass 208 } 209 210 @Override visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index)211 public void visitLocalVariable(String name, String desc, String signature, 212 Label start, Label end, int index) { 213 // pass 214 } 215 216 @Override visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels)217 public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { 218 // pass 219 } 220 221 @Override visitMaxs(int maxStack, int maxLocals)222 public void visitMaxs(int maxStack, int maxLocals) { 223 // pass 224 } 225 226 @Override visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf)227 public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { 228 // pass 229 } 230 231 @Override visitMultiANewArrayInsn(String desc, int dims)232 public void visitMultiANewArrayInsn(String desc, int dims) { 233 // pass 234 } 235 236 @Override visitParameterAnnotation(int parameter, String desc, boolean visible)237 public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) { 238 // pass 239 return null; 240 } 241 242 @Override visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels)243 public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) { 244 // pass 245 } 246 247 @Override visitTryCatchBlock(Label start, Label end, Label handler, String type)248 public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { 249 // pass 250 } 251 252 @Override visitTypeInsn(int opcode, String type)253 public void visitTypeInsn(int opcode, String type) { 254 // pass 255 } 256 257 @Override visitVarInsn(int opcode, int var)258 public void visitVarInsn(int opcode, int var) { 259 // pass 260 } 261 262 } 263