blob: f58de32494714916a7c527042d6a7ff27cdcf5e9 [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.mkstubs.sourcer;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureReader;
import java.util.ArrayList;
/**
* A method visitor that generates the Java source for a whole method.
*/
class MethodSourcer implements MethodVisitor {
private final Output mOutput;
private final int mAccess;
private final String mClassName;
private final String mName;
private final String mDesc;
private final String mSignature;
private final String[] mExceptions;
private boolean mNeedDeclaration;
private boolean mIsConstructor;
public MethodSourcer(Output output, String className, int access, String name,
String desc, String signature, String[] exceptions) {
mOutput = output;
mClassName = className;
mAccess = access;
mName = name;
mDesc = desc;
mSignature = signature;
mExceptions = exceptions;
mNeedDeclaration = true;
mIsConstructor = "<init>".equals(name);
}
private void writeHeader() {
if (!mNeedDeclaration) {
return;
}
AccessSourcer as = new AccessSourcer(mOutput);
as.write(mAccess, AccessSourcer.IS_METHOD);
// preprocess the signature to get the return type and the arguments
SignatureSourcer sigSourcer = null;
if (mSignature != null) {
SignatureReader sigReader = new SignatureReader(mSignature);
sigSourcer = new SignatureSourcer();
sigReader.accept(sigSourcer);
if (sigSourcer.hasFormalsContent()) {
// dump formal template parameter definitions
mOutput.write(" %s", sigSourcer.formalsToString());
}
}
// output return type (constructor have no return type)
if (!mIsConstructor) {
// The signature overrides desc, if present
if (sigSourcer == null || sigSourcer.getReturnType() == null) {
mOutput.write(" %s", Type.getReturnType(mDesc).getClassName());
} else {
mOutput.write(" %s", sigSourcer.getReturnType().toString());
}
}
// output name
mOutput.write(" %s(", mIsConstructor ? mClassName : mName);
// output arguments. The signature overrides desc, if present
if (mSignature == null) {
Type[] types = Type.getArgumentTypes(mDesc);
for(int i = 0; i < types.length; i++) {
if (i > 0) {
mOutput.write(", ");
}
mOutput.write("%s arg%d", types[i].getClassName(), i);
}
} else {
ArrayList<SignatureSourcer> params = sigSourcer.getParameters();
for(int i = 0; i < params.size(); i++) {
if (i > 0) {
mOutput.write(", ");
}
mOutput.write("%s arg%d", params.get(i).toString(), i);
}
}
mOutput.write(")");
// output throwable exceptions
if (mExceptions != null && mExceptions.length > 0) {
mOutput.write(" throws ");
for (int i = 0; i < mExceptions.length; i++) {
if (i > 0) {
mOutput.write(", ");
}
mOutput.write(mExceptions[i].replace('/', '.'));
}
}
mOutput.write(" {\n");
mNeedDeclaration = false;
}
public void visitCode() {
writeHeader();
// write the stub itself
mOutput.write("throw new RuntimeException(\"Stub\");");
}
public void visitEnd() {
writeHeader();
mOutput.write("\n}\n");
}
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
mOutput.write("@%s", desc);
return new AnnotationSourcer(mOutput);
}
public AnnotationVisitor visitAnnotationDefault() {
// pass
return null;
}
public void visitAttribute(Attribute attr) {
mOutput.write("%s /* non-standard method attribute */ ", attr.type);
}
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
// pass
}
public void visitFrame(int type, int local, Object[] local2, int stack, Object[] stack2) {
// pass
}
public void visitIincInsn(int var, int increment) {
// pass
}
public void visitInsn(int opcode) {
// pass
}
public void visitIntInsn(int opcode, int operand) {
// pass
}
public void visitJumpInsn(int opcode, Label label) {
// pass
}
public void visitLabel(Label label) {
// pass
}
public void visitLdcInsn(Object cst) {
// pass
}
public void visitLineNumber(int line, Label start) {
// pass
}
public void visitLocalVariable(String name, String desc, String signature,
Label start, Label end, int index) {
// pass
}
public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
// pass
}
public void visitMaxs(int maxStack, int maxLocals) {
// pass
}
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
// pass
}
public void visitMultiANewArrayInsn(String desc, int dims) {
// pass
}
public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
// pass
return null;
}
public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
// pass
}
public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
// pass
}
public void visitTypeInsn(int opcode, String type) {
// pass
}
public void visitVarInsn(int opcode, int var) {
// pass
}
}