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