• 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 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