| /* |
| * 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.ClassVisitor; |
| import org.objectweb.asm.FieldVisitor; |
| import org.objectweb.asm.MethodVisitor; |
| import org.objectweb.asm.Opcodes; |
| import org.objectweb.asm.signature.SignatureReader; |
| |
| /** |
| * A class visitor that rewrites a java source |
| */ |
| public class ClassSourcer implements ClassVisitor { |
| |
| private final Output mOutput; |
| private final AccessSourcer mAccessSourcer; |
| private String mClassName; |
| |
| public ClassSourcer(Output output) { |
| mOutput = output; |
| mAccessSourcer = new AccessSourcer(mOutput); |
| } |
| |
| /* Examples: |
| * name = com/foo/MyClass |
| * signature = null (if not generic) |
| * superName = java/lang/Object |
| * interfaces = [ java/lang/Runnable ... ] |
| */ |
| public void visit(int version, int access, String name, String signature, |
| String superName, String[] interfaces) { |
| |
| String pkg = name.substring(0, name.lastIndexOf('/')).replace('/', '.'); |
| mClassName = name.substring(name.lastIndexOf('/') + 1); |
| |
| mOutput.write("package %s;\n", pkg); |
| |
| // dump access keywords. Note: do not dump "super" here |
| mAccessSourcer.write(access & ~Opcodes.ACC_SUPER, AccessSourcer.IS_CLASS); |
| |
| // write class name |
| mOutput.write(" class %s", mClassName); |
| |
| if (signature != null) { |
| // write template formal definition and super type |
| SignatureReader sigReader = new SignatureReader(signature); |
| SignatureSourcer sigSourcer = new SignatureSourcer(); |
| sigReader.accept(sigSourcer); |
| |
| if (sigSourcer.hasFormalsContent()) { |
| mOutput.write(sigSourcer.formalsToString()); |
| } |
| |
| mOutput.write(" extends %s", sigSourcer.getSuperClass().toString()); |
| |
| } else { |
| // write non-generic super type |
| mOutput.write(" extends %s", superName.replace('/', '.')); |
| } |
| |
| // write interfaces defined, if any |
| if (interfaces != null && interfaces.length > 0) { |
| mOutput.write(" implements "); |
| boolean need_sep = false; |
| for (String i : interfaces) { |
| if (need_sep) { |
| mOutput.write(", "); |
| } |
| mOutput.write(i.replace('/', '.')); |
| need_sep = true; |
| } |
| } |
| |
| // open class body |
| mOutput.write(" {\n"); |
| } |
| |
| public void visitEnd() { |
| mOutput.write("}\n"); |
| } |
| |
| public AnnotationVisitor visitAnnotation(String desc, boolean visible) { |
| mOutput.write("@%s", desc); |
| return new AnnotationSourcer(mOutput); |
| } |
| |
| public void visitAttribute(Attribute attr) { |
| mOutput.write("%s /* non-standard class attribute */ ", attr.type); |
| } |
| |
| |
| public FieldVisitor visitField(int access, String name, String desc, String signature, |
| Object value) { |
| // skip synthetic fields |
| if ((access & Opcodes.ACC_SYNTHETIC) != 0) { |
| return null; |
| } |
| |
| return new FieldSourcer(mOutput, access, name, desc, signature); |
| } |
| |
| public MethodVisitor visitMethod(int access, String name, String desc, String signature, |
| String[] exceptions) { |
| |
| // Visit the method and dump its stub. |
| return new MethodSourcer(mOutput, mClassName, access, name, desc, signature, exceptions); |
| } |
| |
| public void visitInnerClass(String name, String outerName, String innerName, int access) { |
| // Skip inner classes. This just indicates there's an inner class definition but |
| // they are visited at the top level as separate classes. |
| } |
| |
| public void visitOuterClass(String owner, String name, String desc) { |
| // Skip outer classes. |
| } |
| |
| public void visitSource(String source, String debug) { |
| // Skip source information. |
| } |
| |
| } |