Commit 312084e4 authored by andrei's avatar andrei

work in progress: refactored some code in bco view, added diff. modes support to the compare view.

parent 43562d7a
icons/hide_line_info.gif

138 Bytes | W: | H:

icons/hide_line_info.gif

97 Bytes | W: | H:

icons/hide_line_info.gif
icons/hide_line_info.gif
icons/hide_line_info.gif
icons/hide_line_info.gif
  • 2-up
  • Swipe
  • Onion skin
icons/raw_mode.gif

357 Bytes | W: | H:

icons/raw_mode.gif

351 Bytes | W: | H:

icons/raw_mode.gif
icons/raw_mode.gif
icons/raw_mode.gif
icons/raw_mode.gif
  • 2-up
  • Swipe
  • Onion skin
......@@ -60,8 +60,8 @@ action.showAnalyzer.text=Show bytecode analyzer pane
action.showAnalyzer.toolTipText=Show state of the execution stack frames
action.showAnalyzer.image=icons/verify.gif
action.showRawBytecode.text=Show "raw" bytecode
action.showRawBytecode.toolTipText=Show bytecode as is
action.showRawBytecode.text=Show readable bytecode
action.showRawBytecode.toolTipText=Post-process decompiled bytecode for humans
action.showRawBytecode.image=icons/raw_mode.gif
action.showOnlySelectedElement.text=Show current element only
......
......@@ -237,9 +237,7 @@ public class CommentedClassVisitor extends TraceClassVisitor {
}
public void visitLineNumber(final int line, final Label start) {
if (raw) {
super.visitLineNumber(line, start);
}
super.visitLineNumber(line, start);
}
public void visitMaxs(final int maxStack, final int maxLocals) {
......
......@@ -27,26 +27,26 @@ import de.loskutov.bco.preferences.BCOConstants;
public class DecompilerClassVisitor extends ClassAdapter {
private String fieldFilter;
private final String fieldFilter;
private String methodFilter;
private boolean verify;
private final String methodFilter;
private String name;
private List methods;
private final List methods;
private AnnotationVisitor dummyAnnVisitor;
private String javaVersion;
private final BitSet modes;
public DecompilerClassVisitor(final ClassVisitor cv, final String field,
final String method, final boolean verify) {
final String method, final BitSet modes) {
super(cv);
this.fieldFilter = field;
this.methodFilter = method;
this.verify = verify;
this.modes = modes;
this.methods = new ArrayList();
}
......@@ -69,7 +69,7 @@ public class DecompilerClassVisitor extends ClassAdapter {
cv = new CommentedClassVisitor(!modes.get(BCOConstants.F_SHOW_RAW_BYTECODE));
}
DecompilerClassVisitor dcv = new DecompilerClassVisitor(
cv, field, method, modes.get(BCOConstants.F_SHOW_ANALYZER));
cv, field, method, modes);
cr.accept(new ClassAdapter(dcv) {
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
......@@ -79,11 +79,20 @@ public class DecompilerClassVisitor extends ClassAdapter {
super.visitLocalVariable(name1, desc1, signature1, start, end, index);
}
}
public void visitMaxs(int maxStack, int maxLocals) {
if(modes.get(BCOConstants.F_SHOW_VARIABLES)) {
super.visitMaxs(maxStack, maxLocals);
}
}
public void visitLineNumber(int line, Label start) {
if(modes.get(BCOConstants.F_SHOW_LINE_INFO)) {
super.visitLineNumber(line, start);
}
}
public void visitLabel(Label label) {
// TODO Auto-generated method stub
super.visitLabel(label);
}
};
}
}, 0);
......@@ -91,32 +100,6 @@ public class DecompilerClassVisitor extends ClassAdapter {
return dcv.getResult(cl);
}
public static DecompiledClass getDecompiledClass(final InputStream is,
final String field, final String method, final boolean raw,
final boolean asmify, final boolean verify, final ClassLoader cl)
throws IOException {
ClassReader cr = new ClassReader(is);
ClassVisitor cv;
if (asmify) {
cv = new ASMifierClassVisitor(null) {
public void visitEnd() {
text.add("cw.visitEnd();\n\n");
text.add("return cw.toByteArray();\n");
text.add("}\n");
text.add("}\n");
}
};
} else {
cv = new CommentedClassVisitor(raw);
}
DecompilerClassVisitor dcv = new DecompilerClassVisitor(
cv, field, method, verify);
cr.accept(dcv, 0);
return dcv.getResult(cl);
}
public DecompiledClass getResult(final ClassLoader cl) {
List text = new ArrayList();
formatText(((AbstractVisitor) cv).getText(), new StringBuffer(), text, cl);
......@@ -224,7 +207,7 @@ public class DecompilerClassVisitor extends ClassAdapter {
return null;
}
MethodNode meth = null;
if (verify) {
if (modes.get(BCOConstants.F_SHOW_ANALYZER)) {
meth = new MethodNode(access, name1, desc, signature, exceptions);
}
List text = ((AbstractVisitor) cv).getText();
......
......@@ -57,11 +57,12 @@ public class BytecodeCompare extends CompareEditorInput {
this.left = left;
this.right = right;
toggleAsmifierModeAction = new DefaultToggleAction(BCOConstants.SHOW_ASMIFIER_CODE,
toggleAsmifierModeAction = new DefaultToggleAction(BCOConstants.SHOW_ASMIFIER_CODE,
new IPropertyChangeListener(){
public void propertyChange(PropertyChangeEvent event) {
if(IAction.CHECKED.equals(event.getProperty())){
toggleASMifierMode(Boolean.TRUE == event.getNewValue());
boolean asmifier = Boolean.TRUE == event.getNewValue();
toggleMode(BCOConstants.F_SHOW_ASMIFIER_CODE, asmifier, asmifier);
}
}
});
......@@ -69,18 +70,22 @@ public class BytecodeCompare extends CompareEditorInput {
hideLineInfoAction = new DefaultToggleAction(BCOConstants.SHOW_LINE_INFO, new IPropertyChangeListener(){
public void propertyChange(PropertyChangeEvent event) {
if(IAction.CHECKED.equals(event.getProperty())){
// TODO add custom behavoir
// toggleASMifierMode(Boolean.TRUE == event.getNewValue());
toggleMode(
BCOConstants.F_SHOW_LINE_INFO,
Boolean.TRUE == event.getNewValue(),
toggleAsmifierModeAction.isChecked());
}
}
});
hideLocalsAction = new DefaultToggleAction(BCOConstants.SHOW_VARIABLES,
hideLocalsAction = new DefaultToggleAction(BCOConstants.SHOW_VARIABLES,
new IPropertyChangeListener(){
public void propertyChange(PropertyChangeEvent event) {
if(IAction.CHECKED.equals(event.getProperty())){
// TODO add custom behavoir
// toggleASMifierMode(Boolean.TRUE == event.getNewValue());
toggleMode(
BCOConstants.F_SHOW_VARIABLES,
Boolean.TRUE == event.getNewValue(),
toggleAsmifierModeAction.isChecked());
}
}
});
......@@ -188,14 +193,17 @@ public class BytecodeCompare extends CompareEditorInput {
return control;
}
protected void toggleASMifierMode(boolean isASMifierMode) {
protected void toggleMode(int mode, boolean value, boolean isASMifierMode) {
String contentType = isASMifierMode
? TypedElement.TYPE_ASM_IFIER
: TypedElement.TYPE_BYTECODE;
left.setASMifierMode(isASMifierMode);
left.setMode(mode, value);
left.setMode(BCOConstants.F_SHOW_ASMIFIER_CODE, isASMifierMode);
left.setType(contentType);
right.setASMifierMode(isASMifierMode);
right.setMode(mode, value);
right.setMode(BCOConstants.F_SHOW_ASMIFIER_CODE, isASMifierMode);
right.setType(contentType);
CompareUI.reuseCompareEditor(this, myEditor);
}
......
......@@ -11,6 +11,7 @@ package de.loskutov.bco.compare;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.BitSet;
import org.eclipse.compare.BufferedContent;
import org.eclipse.compare.CompareUI;
......@@ -21,6 +22,7 @@ import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import de.loskutov.bco.BytecodeOutlinePlugin;
import de.loskutov.bco.asm.DecompiledClass;
......@@ -41,46 +43,27 @@ public class TypedElement extends BufferedContent
private IJavaElement element;
private boolean isASMifierMode;
/** used by Eclipse to recognize appropriated viewer */
public static final String TYPE_BYTECODE = "bytecode";
/** used by Eclipse to recognize appropriated viewer */
public static final String TYPE_ASM_IFIER = "java";
/**
* Constructor for TypedElement.
*/
public TypedElement() {
super();
}
private final BitSet modes;
/**
* Constructor for TypedElement.
* @param name
* @param type
* @param element
* @param modes
*/
public TypedElement(String name, String type, IJavaElement element) {
this();
public TypedElement(String name, String type, IJavaElement element, BitSet modes) {
super();
this.name = name;
this.type = type;
this.element = element;
}
/**
* @return Returns the isASMifierMode.
*/
protected boolean isASMifierMode() {
return isASMifierMode;
}
/**
* @param isASMifierMode The isASMifierMode to set.
*/
protected void setASMifierMode(boolean isASMifierMode) {
this.isASMifierMode = isASMifierMode;
this.modes = modes;
}
/**
......@@ -137,7 +120,7 @@ public class TypedElement extends BufferedContent
DecompiledClass decompiledClass = null;
try {
decompiledClass = DecompilerClassVisitor.getDecompiledClass(
stream, null, null, true, isASMifierMode(), false, null);
stream, null, null, modes, null);
} catch (IOException e) {
throw new CoreException(new Status(
IStatus.ERROR, "de.loskutov.bco", -1,
......@@ -149,9 +132,25 @@ public class TypedElement extends BufferedContent
BytecodeOutlinePlugin.log(e, IStatus.WARNING);
}
}
byte[] bytes = decompiledClass.getText().getBytes();
final byte[] bytes = decompiledClass.getText().getBytes();
// use internal buffering to prevent multiple calls to this method
setContent(bytes);
Display.getDefault().syncExec(new Runnable(){
public void run() {
setContent(bytes);
}
});
return new ByteArrayInputStream(bytes);
}
/**
*
* @param mode one of BCOConstants.F_* modes
* @param value
*/
public void setMode(int mode, boolean value){
modes.set(mode, value);
// force create new stream
discardBuffer();
}
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ package de.loskutov.bco.editors;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.BitSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
......@@ -141,8 +142,9 @@ public class BytecodeSourceMapper extends SourceMapper {
boolean raw = true;
boolean asmify = false;
boolean verify = false;
// TODO put bitset of modes instead of new BitSet()
DecompiledClass decompiledClass = DecompilerClassVisitor
.getDecompiledClass(is, null, null, raw, asmify, verify, null);
.getDecompiledClass(is, null, null, new BitSet(), null);
source.append(decompiledClass.getText());
}
......
......@@ -65,6 +65,37 @@ public class JdtUtils {
// don't call
}
/**
* @param childEl
* @return method signature, if given java element is either initializer or method,
* otherwise returns null.
*/
public static String getMethodSignature(IJavaElement childEl) {
String methodName = null;
if (childEl.getElementType() == IJavaElement.INITIALIZER) {
IInitializer ini = (IInitializer) childEl;
try {
if (Flags.isStatic(ini.getFlags())) {
methodName = "<clinit>()V";
} else {
methodName = "<init>()";
}
} catch (JavaModelException e) {
// this is compilation problem - don't show the message
BytecodeOutlinePlugin.log(e, IStatus.WARNING);
}
} else if (childEl.getElementType() == IJavaElement.METHOD) {
IMethod iMethod = (IMethod) childEl;
try {
methodName = createMethodSignature(iMethod);
} catch (JavaModelException e) {
// this is compilation problem - don't show the message
BytecodeOutlinePlugin.log(e, IStatus.WARNING);
}
}
return methodName;
}
public static String createMethodSignature(IMethod iMethod)
throws JavaModelException {
StringBuffer sb = new StringBuffer();
......@@ -255,11 +286,14 @@ public class JdtUtils {
* Modified copy from org.eclipse.jdt.internal.ui.actions.SelectionConverter
* @param input
* @param selection
* @return
* @return null, if selection is null or could not be resolved to java element
* @throws JavaModelException
*/
public static IJavaElement getElementAtOffset(IJavaElement input,
ITextSelection selection) throws JavaModelException {
if(selection == null){
return null;
}
ICompilationUnit workingCopy = null;
if (input instanceof ICompilationUnit) {
workingCopy = (ICompilationUnit) input;
......@@ -283,7 +317,7 @@ public class JdtUtils {
return ref;
}
}
return input;
return null;
}
/**
......
package de.loskutov.bco.views;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.viewers.IPostSelectionProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import de.loskutov.bco.BytecodeOutlinePlugin;
/**
* Adapter for different selection provider in one view - text control and table control.
* See <a href="http://forge.objectweb.org/tracker/?func=detail&atid=100023&aid=304424&group_id=23">bug 304424</a>
* The main problem is, that
* <pre>
* getSite().setSelectionProvider(viewSelectionProvider);
* </pre>
* could be set only once per view, so that we cannot switch existing
* selection provider on the fly (or I have no idea how to do this simplier way).
* @author Andrei
*/
class BCOViewSelectionProvider implements IPostSelectionProvider {
private IPostSelectionProvider realProvider;
private List selProviders;
private ISelection selection;
public BCOViewSelectionProvider(){
super();
selProviders = new ArrayList();
}
public void setCurrentSelectionProvider(IPostSelectionProvider provider){
if(!selProviders.contains(provider)){
BytecodeOutlinePlugin.log(
new Exception(
"Current selection provider is not registered yet"),
IStatus.WARNING);
return;
}
realProvider = provider;
if(selection != null) {
realProvider.setSelection(selection);
}
}
public void registerSelectionProvider(IPostSelectionProvider provider) {
if(!selProviders.contains(provider)){
selProviders.add(provider);
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.IPostSelectionProvider#addPostSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
*/
public void addPostSelectionChangedListener(ISelectionChangedListener listener) {
for (int i = 0; i < selProviders.size(); i++) {
IPostSelectionProvider provider = (IPostSelectionProvider) selProviders.get(i);
provider.addPostSelectionChangedListener(listener);
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.IPostSelectionProvider#removePostSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
*/
public void removePostSelectionChangedListener(ISelectionChangedListener listener) {
for (int i = 0; i < selProviders.size(); i++) {
IPostSelectionProvider provider = (IPostSelectionProvider) selProviders.get(i);
provider.removePostSelectionChangedListener(listener);
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
*/
public void addSelectionChangedListener(ISelectionChangedListener listener) {
for (int i = 0; i < selProviders.size(); i++) {
IPostSelectionProvider provider = (IPostSelectionProvider) selProviders.get(i);
provider.addSelectionChangedListener(listener);
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
*/
public ISelection getSelection() {
return realProvider != null? realProvider.getSelection() : null;
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
*/
public void removeSelectionChangedListener(ISelectionChangedListener listener) {
for (int i = 0; i < selProviders.size(); i++) {
IPostSelectionProvider provider = (IPostSelectionProvider) selProviders.get(i);
provider.removeSelectionChangedListener(listener);
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
*/
public void setSelection(ISelection selection) {
this.selection = selection;
if(realProvider != null) {
realProvider.setSelection(selection);
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment