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