Java tutorial
/******************************************************************************* * 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); } }