• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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