Package de.loskutov.bco.asm

Source Code of de.loskutov.bco.asm.CommentedClassVisitor$CommentedMethodVisitor

package de.loskutov.bco.asm;

import java.util.BitSet;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.util.AbstractVisitor;
import org.objectweb.asm.util.TraceAnnotationVisitor;
import org.objectweb.asm.util.TraceClassVisitor;
import org.objectweb.asm.util.TraceFieldVisitor;
import org.objectweb.asm.util.TraceMethodVisitor;

import de.loskutov.bco.preferences.BCOConstants;

/**
* @author Eric Bruneton
*/

public class CommentedClassVisitor extends TraceClassVisitor {

    protected boolean raw;
    protected BitSet modes;
    protected boolean showLines;
    protected boolean showLocals;
    protected boolean showStackMap;
    protected boolean showHex;

    public CommentedClassVisitor(final BitSet modes) {
        super(null);
        this.modes = modes;
        raw = !modes.get(BCOConstants.F_SHOW_RAW_BYTECODE);
        showLines = modes.get(BCOConstants.F_SHOW_LINE_INFO);
        showLocals = modes.get(BCOConstants.F_SHOW_VARIABLES);
        showStackMap = modes.get(BCOConstants.F_SHOW_STACKMAP);
        showHex = modes.get(BCOConstants.F_SHOW_HEX_VALUES);
    }

    public void visitEnd() {
        text.add("}\n");
    }

    protected TraceAnnotationVisitor createTraceAnnotationVisitor() {
        return new CommentedAnnotationVisitor();
    }

    protected TraceFieldVisitor createTraceFieldVisitor() {
        return new CommentedFieldVisitor();
    }

    protected TraceMethodVisitor createTraceMethodVisitor() {
        return new CommentedMethodVisitor();
    }

    protected void appendDescriptor(final int type, final String desc) {
        appendDescriptor(buf, type, desc, raw);
    }

    protected void appendDescriptor(final StringBuffer buf1, final int type,
        final String desc, final boolean raw1) {
        if (desc == null) {
            return;
        }
        if (raw1) {
            if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE
                || type == METHOD_SIGNATURE) {
                buf1.append("// signature ").append(desc).append('\n');
            } else {
                buf1.append(desc);
            }
        } else {
            switch (type) {
                case INTERNAL_NAME :
                    buf1.append(eatPackageNames(desc, '/'));
                    break;
                case FIELD_DESCRIPTOR :
                    if ("T".equals(desc)) {
                        buf1.append("top");
                    } else if ("N".equals(desc)) {
                        buf1.append("null");
                    } else if ("U".equals(desc)) {
                        buf1.append("uninitialized_this");
                    } else {
                        buf1.append(getSimpleName(Type.getType(desc)));
                    }
                    break;
                case METHOD_DESCRIPTOR :
                    Type[] args = Type.getArgumentTypes(desc);
                    Type res = Type.getReturnType(desc);
                    buf1.append('(');
                    for (int i = 0; i < args.length; ++i) {
                        if (i > 0) {
                            buf1.append(',');
                        }
                        buf1.append(getSimpleName(args[i]));
                    }
                    buf1.append(") : ");
                    buf1.append(getSimpleName(res));
                    break;

                case METHOD_SIGNATURE :
                case FIELD_SIGNATURE :
                    // fine tuning of identation - we have two tabs in this case
                    if (buf.lastIndexOf(tab) == buf.length() - tab.length()) {
                        buf.delete(buf.lastIndexOf(tab), buf.length());
                    }
                    break;

                case CLASS_SIGNATURE :
                    // ignore - show only in "raw" mode
                    break;
                case TYPE_DECLARATION :
                    buf1.append(eatPackageNames(desc, '.'));
                    break;
                case CLASS_DECLARATION :
                    buf1.append(eatPackageNames(desc, '.'));
                    break;
                case PARAMETERS_DECLARATION :
                    buf1.append(eatPackageNames(desc, '.'));
                    break;
                default :
                    buf1.append(desc);
            }
        }
    }

    /**
     * @param t
     * @return simply class name without any package/outer class information
     */
    public static String getSimpleName(Type t) {
        String name = t.getClassName();
        return eatPackageNames(name, '.');
    }

    /**
     * @param name Java type name(s).
     * @return simply class name(s) without any package/outer class information, but with
     * "generics" information from given name parameter.
     */
    private static String eatPackageNames(String name, char separator) {
        int lastPoint = name.lastIndexOf(separator);
        if (lastPoint < 0) {
            return name;
        }
        StringBuffer sb = new StringBuffer(name);
        do {
            int start = getPackageStartIndex(sb, separator, lastPoint);
            sb.delete(start, lastPoint + 1);
            lastPoint = lastIndexOf(sb, separator, start);
        } while (lastPoint > 0);

        return sb.toString();
    }

    private static int lastIndexOf(StringBuffer chars, char c, int lastPoint) {
        for (int i = lastPoint - 1; i > 0; i--) {
            if (chars.charAt(i) == c) {
                return i;
            }
        }
        return -1;
    }

    private static int getPackageStartIndex(StringBuffer chars, char c,
        int firstPoint) {
        for (int i = firstPoint - 1; i >= 0; i--) {
            char curr = chars.charAt(i);
            if (curr != c && !Character.isJavaIdentifierPart(curr)) {
                return i + 1;
            }
        }
        return 0;
    }

    class CommentedAnnotationVisitor extends TraceAnnotationVisitor {

        public void setAnnotationVisitor(AnnotationVisitor av) {
            this.av = av;
        }

        protected TraceAnnotationVisitor createTraceAnnotationVisitor() {
            return new CommentedAnnotationVisitor();
        }

        protected void appendDescriptor(final int type, final String desc) {
            CommentedClassVisitor.this.appendDescriptor(buf, type, desc, raw);
        }
    }

    class CommentedFieldVisitor extends TraceFieldVisitor {

        public void setFieldVisitor(FieldVisitor fv) {
            this.fv = fv;
        }

        protected void appendDescriptor(final int type, final String desc) {
            CommentedClassVisitor.this.appendDescriptor(buf, type, desc, raw);
        }

        protected TraceAnnotationVisitor createTraceAnnotationVisitor() {
            return new CommentedAnnotationVisitor();
        }
    }

    /**
     * control chars names
     */
    private static final String[] CHAR_NAMES = {"NUL", "SOH", "STX", "ETX",
        "EOT", "ENQ", "ACK", "BEL", "BS", "HT", "LF", "VT", "FF", "CR", "SO",
        "SI", "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", "CAN",
        "EM", "SUB", "ESC", "FS", "GS", "RS", "US", // "Sp"
    };

    class CommentedMethodVisitor extends TraceMethodVisitor {

        private Index getIndex(Label label) {
            Index index;
            for (int i = 0; i < text.size(); i++) {
                Object o = text.get(i);
                if (o instanceof Index) {
                    index = (Index) o;
                    if (index.labelNode != null
                        && index.labelNode.getLabel() == label) {
                        return index;
                    }
                }
            }
            return null;
        }

        public void visitFrame(int type, int nLocal, Object[] local,
            int nStack, Object[] stack) {
            if (showStackMap) {
                super.visitFrame(type, nLocal, local, nStack, stack);
            }
        }

        public void visitMethodInsn(final int opcode, final String owner,
            final String name, final String desc) {
            buf.setLength(0);
            buf.append(tab2).append(OPCODES[opcode]).append(' ');
            appendDescriptor(INTERNAL_NAME, owner);
            buf.append('.').append(name);
            appendDescriptor(METHOD_DESCRIPTOR, desc);
            buf.append('\n');
            text.add(buf.toString());
        }

        public void visitVarInsn(final int opcode, final int var) {
            text.add(tab2 + OPCODES[opcode] + " " + var);
            if (!raw) {
                text.add(new Integer(var));
            }
            text.add("\n");
        }

        public void visitLabel(Label label) {
            buf.setLength(0);
            buf.append(ltab);
            appendLabel(label);
            Index index = getIndex(label);
            if (index != null) {
                buf.append(" (").append(index.insn).append(")");
            }
            buf.append('\n');
            text.add(buf.toString());
        }

        public void visitIincInsn(final int var, final int increment) {
            text.add(tab2 + "IINC " + var);
            if (!raw) {
                text.add(new Integer(var));
            }
            text.add(" " + increment + "\n");
        }

        public void visitIntInsn(int opcode, int operand) {
            buf.setLength(0);
            buf.append(tab2).append(OPCODES[opcode]).append(' ').append(
                opcode == Opcodes.NEWARRAY
                    ? TYPES[operand]
                    : formatValue(operand)).append('\n');
            text.add(buf.toString());

            if (mv != null) {
                mv.visitIntInsn(opcode, operand);
            }
        }

        private String formatValue(int operand) {
            if (showHex) {
                String intStr = Integer.toHexString(operand).toUpperCase();
                return intStr + getAsCharComment(operand);
            }
            return Integer.toString(operand);
        }

        /**
         * @param value
         * @return char value from int, together with char name if it is a control char,
         * or an empty string
         */
        private String getAsCharComment(int value) {
            if (Character.MAX_VALUE < value || Character.MIN_VALUE > value) {
                return "";
            }
            StringBuffer sb = new StringBuffer("    // '");
            switch (value) {
                case '\t' :
                    sb.append("\\t");
                    break;
                case '\r' :
                    sb.append("\\r");
                    break;
                case '\n' :
                    sb.append("\\n");
                    break;
                case '\f' :
                    sb.append("\\f");
                    break;
                default :
                    sb.append((char) value);
                    break;
            }

            if (value >= CHAR_NAMES.length) {
                if (value == 127) {
                    return sb.append("' (DEL)").toString();
                }
                return sb.append("'").toString();
            }
            return sb.append("' (").append(CHAR_NAMES[value]).append(")")
                .toString();
        }

        private String formatValue(Object operand) {
            if (operand == null) {
                return "null";
            }
            if (showHex) {
                if (operand instanceof Integer) {
                    String intStr = Integer.toHexString(
                        ((Integer) operand).intValue()).toUpperCase();
                    return intStr
                        + getAsCharComment(((Integer) operand).intValue());
                } else if (operand instanceof Long) {
                    return Long.toHexString(((Long) operand).longValue())
                        .toUpperCase();
                } else if (operand instanceof Double) {
                    return Double.toHexString(((Double) operand).doubleValue());
                } else if (operand instanceof Float) {
                    return Float.toHexString(((Float) operand).floatValue());
                }
            }
            return operand.toString();
        }

        public void visitLocalVariable(final String name, final String desc,
            final String signature, final Label start, final Label end,
            final int index) {
            if (showLocals) {
                super.visitLocalVariable(
                    name, desc, signature, start, end, index);
            }
        }

        public void visitLdcInsn(Object cst) {
            buf.setLength(0);
            buf.append(tab2).append("LDC ");
            if (cst instanceof String) {
                AbstractVisitor.appendString(buf, (String) cst);
            } else if (cst instanceof Type) {
                buf.append(((Type) cst).getDescriptor() + ".class");
            } else {
                buf.append(formatValue(cst));
            }
            buf.append('\n');
            text.add(buf.toString());

            if (mv != null) {
                mv.visitLdcInsn(cst);
            }
        }

        public void visitLineNumber(final int line, final Label start) {
            if (showLines) {
                super.visitLineNumber(line, start);
            }
        }

        public void visitMaxs(final int maxStack, final int maxLocals) {
            if (showLocals) {
                super.visitMaxs(maxStack, maxLocals);
            }
        }

        protected TraceAnnotationVisitor createTraceAnnotationVisitor() {
            return new CommentedAnnotationVisitor();
        }

        protected void appendDescriptor(final int type, final String desc) {
            CommentedClassVisitor.this.appendDescriptor(buf, type, desc, raw);
        }
    }

}
TOP

Related Classes of de.loskutov.bco.asm.CommentedClassVisitor$CommentedMethodVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.