cz.vutbr.fit.xhriba01.bc.BytecodeCodeVisitor.java Source code

Java tutorial

Introduction

Here is the source code for cz.vutbr.fit.xhriba01.bc.BytecodeCodeVisitor.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Jaromr Hibal.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Jaromr Hibal <jaromirhribal@gmail.com> - initial API and implementation
 *******************************************************************************/
package cz.vutbr.fit.xhriba01.bc;

import java.util.HashMap;

import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.IincInsnNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.LineNumberNode;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.LookupSwitchInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.MultiANewArrayInsnNode;
import org.objectweb.asm.tree.TableSwitchInsnNode;
import org.objectweb.asm.tree.TypeInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
import org.objectweb.asm.util.Printer;

import cz.vutbr.fit.xhriba01.bc.algorithms.AbstractBytecodeCodeVisitor;
import cz.vutbr.fit.xhriba01.bc.algorithms.BytecodeCodeAlgorithm.ClassSourceResult.NodeClass;
import cz.vutbr.fit.xhriba01.bc.algorithms.BytecodeCodeAlgorithm.ClassSourceResult.NodeField;
import cz.vutbr.fit.xhriba01.bc.algorithms.BytecodeCodeAlgorithm.ClassSourceResult.NodeInstruction;
import cz.vutbr.fit.xhriba01.bc.algorithms.BytecodeCodeAlgorithm.ClassSourceResult.NodeMethod;
import cz.vutbr.fit.xhriba01.bc.io.LineNumberStringWriter;

public class BytecodeCodeVisitor extends AbstractBytecodeCodeVisitor {

    private LineNumberStringWriter fWriter = new LineNumberStringWriter();

    private int fCurrentLine;

    private HashMap<Integer, Integer> fLineMap = new HashMap<>();

    private int fMaxLineNumber = 0;

    public String getText() {
        return fWriter.getText();
    }

    @Override
    public void beforeVisitNodeClass(NodeClass nodeClass) {

    }

    @Override
    public void visitNodeClass(NodeClass nodeClass) {
        ClassNode classNode = nodeClass.getAsmClassNode();
        String accesses = Utils.formatClassAccessFlags(classNode.access);
        if (!accesses.isEmpty())
            accesses += " ";
        fWriter.addLineWithIndentation(accesses + classNode.name + "\t{");
        fWriter.newLine();
        fWriter.increaseIndentationLevel();
    }

    @Override
    public void afterVisitNodeClass(NodeClass nodeClass) {
        fWriter.decreaseIndentationLevel();
        fWriter.addLineWithIndentation("}");
        fWriter.newLine();
    }

    @Override
    public void beforeVisitNodeMethod(NodeMethod nodeMethod) {
    }

    @Override
    public void visitNodeMethod(NodeMethod nodeMethod) {
        MethodNode method = nodeMethod.getAsmMethodNode();
        Type type = Type.getMethodType(method.desc);
        String returnType = type.getReturnType().getClassName();
        Type[] argumentTypes = type.getArgumentTypes();
        String accesses = Utils.formatMethodAccessFlags(method.access);
        if (!accesses.isEmpty())
            accesses += " ";
        fWriter.addLineWithIndentation(accesses + returnType + " " + method.name + "("
                + formatMethodArguments(argumentTypes) + ")" + "\t{");
    }

    private String formatMethodArguments(Type[] arguments) {
        StringBuffer sb = new StringBuffer();
        int length = arguments.length;
        for (int i = 0; i < length; i++) {
            sb.append(arguments[i].getClassName());
            if (i + 1 < length) {
                sb.append(", ");
            }
        }
        return sb.toString();
    }

    @Override
    public void afterVisitNodeMethod(NodeMethod nodeMethod) {
        fWriter.addLineWithIndentation("}");
        fWriter.newLine();
    }

    @Override
    public void beforeVisitNodeField(NodeField nodeField) {
    }

    @Override
    public void visitNodeField(NodeField nodeField) {
    }

    @Override
    public void afterVisitNodeField(NodeField nodeField) {
    }

    @Override
    public void beforeVisitNodeInstruction(NodeInstruction nodeInstruction) {
        fWriter.increaseIndentationLevel();
    }

    @Override
    public void afterVisitNodeInstruction(NodeInstruction nodeInstruction) {
        fWriter.decreaseIndentationLevel();
    }

    private void addToLineMap(int classLine, int sourceLine) {
        fLineMap.put(classLine, sourceLine);
        if (sourceLine > fMaxLineNumber) {
            fMaxLineNumber = sourceLine;
        }
    }

    public int getMaxLineNumber() {
        return fMaxLineNumber;
    }

    public HashMap<Integer, Integer> getLineMap() {
        return fLineMap;
    }

    private String getOpcodeLabel(AbstractInsnNode insn) {
        return Printer.OPCODES[insn.getOpcode()];
    }

    protected void visitLineNumberNode(LineNumberNode node, NodeInstruction nodeInstruction) {
        fCurrentLine = node.line;
    }

    protected void visitFieldInsn(FieldInsnNode insn, NodeInstruction nodeInstruction) {
        int line = fWriter.addLineWithIndentation(getOpcodeLabel(insn));
        addToLineMap(line, fCurrentLine);
    }

    protected void visitIincInsn(IincInsnNode insn, NodeInstruction nodeInstruction) {
        int line = fWriter.addLineWithIndentation(getOpcodeLabel(insn));
        addToLineMap(line, fCurrentLine);
    }

    protected void visitInsn(InsnNode insn, NodeInstruction nodeInstruction) {
        int line = fWriter.addLineWithIndentation(getOpcodeLabel(insn));
        addToLineMap(line, fCurrentLine);
    }

    protected void visitIntInsn(IntInsnNode insn, NodeInstruction nodeInstruction) {
        int line = fWriter.addLineWithIndentation(getOpcodeLabel(insn));
        addToLineMap(line, fCurrentLine);
    }

    protected void visitInvokeDynamicInsn(InvokeDynamicInsnNode insn, NodeInstruction nodeInstruction) {
        int line = fWriter.addLineWithIndentation(getOpcodeLabel(insn));
        addToLineMap(line, fCurrentLine);
    }

    protected void visitJumpInsn(JumpInsnNode insn, NodeInstruction nodeInstruction) {
        int line = fWriter.addLineWithIndentation(getOpcodeLabel(insn));
        addToLineMap(line, fCurrentLine);
    }

    protected void visitLdcInsn(LdcInsnNode insn, NodeInstruction nodeInstruction) {
        int line = fWriter.addLineWithIndentation(getOpcodeLabel(insn));
        addToLineMap(line, fCurrentLine);
    }

    protected void visitLookupSwitchInsn(LookupSwitchInsnNode insn, NodeInstruction nodeInstruction) {
        int line = fWriter.addLineWithIndentation(getOpcodeLabel(insn));
        addToLineMap(line, fCurrentLine);
    }

    protected void visitMethodInsn(MethodInsnNode insn, NodeInstruction nodeInstruction) {
        int line = fWriter.addLineWithIndentation(getOpcodeLabel(insn));
        addToLineMap(line, fCurrentLine);
    }

    protected void visitMultiANewArrayInsn(MultiANewArrayInsnNode insn, NodeInstruction nodeInstruction) {
        int line = fWriter.addLineWithIndentation(getOpcodeLabel(insn));
        addToLineMap(line, fCurrentLine);
    }

    protected void visitTableSwitchInsn(TableSwitchInsnNode insn, NodeInstruction nodeInstruction) {
        int line = fWriter.addLineWithIndentation(getOpcodeLabel(insn));
        addToLineMap(line, fCurrentLine);
    }

    protected void visitTypeInsn(TypeInsnNode insn, NodeInstruction nodeInstruction) {
        int line = fWriter.addLineWithIndentation(getOpcodeLabel(insn));
        addToLineMap(line, fCurrentLine);
    }

    protected void visitVarInsn(VarInsnNode insn, NodeInstruction nodeInstruction) {
        int line = fWriter.addLineWithIndentation(getOpcodeLabel(insn));
        addToLineMap(line, fCurrentLine);
    }

}