Skip to content

Commit

Permalink
Token parsing updates.
Browse files Browse the repository at this point in the history
- Fixed a few bugs
- Added methods and classes (highlighting and go-to)
  • Loading branch information
Bl3nd committed Sep 22, 2024
1 parent 7b7f897 commit 9a08a5f
Show file tree
Hide file tree
Showing 7 changed files with 500 additions and 229 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package the.bytecode.club.bytecodeviewer.gui.components.actions;

import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.Token;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.BytecodeViewPanel;
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer;
import the.bytecode.club.bytecodeviewer.gui.util.BytecodeViewPanelUpdater;
import the.bytecode.club.bytecodeviewer.resources.ResourceContainer;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.ClassFileContainer;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.ClassFieldLocation;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.ClassMethodLocation;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.ClassReferenceLocation;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.TokenUtil;

import javax.swing.*;
import javax.swing.event.CaretEvent;
Expand Down Expand Up @@ -45,7 +49,7 @@ public void actionPerformed(ActionEvent e)
// Open the class that is associated with the field's owner.
if (!field.owner.equals(container.getName()))
{
openFieldClass(field, textArea);
open(textArea, false, true, false);
return;
}

Expand Down Expand Up @@ -98,88 +102,247 @@ public void actionPerformed(ActionEvent e)
}
}
}));

container.methodMembers.values().forEach(methods -> methods.forEach(method -> {
if (method.line == line && method.columnStart - 1 <= column && method.columnEnd >= column)
{
Element root = textArea.getDocument().getDefaultRootElement();
if (method.decRef.equalsIgnoreCase("declaration"))
{
int startOffset = root.getElement(method.line - 1).getStartOffset() + (method.columnStart - 1);
textArea.setCaretPosition(startOffset);
} else
{
methods.stream().filter(classMethodLocation -> classMethodLocation.owner.equals(method.owner)).forEach(classMethodLocation -> {
if (classMethodLocation.decRef.equalsIgnoreCase("declaration"))
{
int startOffset = root.getElement(classMethodLocation.line - 1).getStartOffset() + (classMethodLocation.columnStart - 1);
textArea.setCaretPosition(startOffset);
}
});


open(textArea, false, false, true);
}
}
}));

container.classReferences.values().forEach(classes -> classes.forEach(clazz -> {
String name;
if (clazz.line == line && clazz.columnStart - 1 <= column && clazz.columnEnd - 1 >= column)
{
name = clazz.owner;
Element root = textArea.getDocument().getDefaultRootElement();
if (clazz.type.equals("declaration"))
{
int startOffset = root.getElement(clazz.line - 1).getStartOffset() + (clazz.columnStart - 1);
textArea.setCaretPosition(startOffset);
} else
{
classes.stream().filter(classReferenceLocation -> classReferenceLocation.owner.equals(name)).forEach(classReferenceLocation -> {
if (classReferenceLocation.type.equals("declaration"))
{
int startOffset = root.getElement(classReferenceLocation.line - 1).getStartOffset() + (classReferenceLocation.columnStart - 1);
textArea.setCaretPosition(startOffset);
}
});

// Should not really do anything when the class is already open
open(textArea, true, false, false);
}
}
}));
}

/**
* Open a class that contains the declaration of a field.
*
* @param field The field to jump to
* @param textArea The text area of the current class (not the class we are opening)
*/
private void openFieldClass(ClassFieldLocation field, RSyntaxTextArea textArea)
private ClassFileContainer openClass(String lexeme, boolean field, boolean method)
{
String token = textArea.modelToToken(textArea.getCaretPosition()).getLexeme();
if (lexeme.equals(container.getName()))
return null;

ResourceContainer resourceContainer = BytecodeViewer.getFileContainer(container.getParentContainer());
if (resourceContainer != null)
if (resourceContainer == null)
return null;

if (field)
{
String className = container.getImport(field.owner);
String className = container.getClassForField(lexeme);
BytecodeViewer.viewer.workPane.addClassResource(resourceContainer, className + ".class");
ClassViewer activeResource = (ClassViewer) BytecodeViewer.viewer.workPane.getActiveResource();
HashMap<String, ClassFileContainer> classFiles = BytecodeViewer.viewer.workPane.classFiles;
Thread thread = new Thread(() -> {
try
{
BytecodeViewer.updateBusyStatus(true);
Thread.sleep(1000);
} catch (InterruptedException e)
{
throw new RuntimeException(e);
} finally
{
BytecodeViewer.updateBusyStatus(false);
}
return wait(classFiles, activeResource);
} else if (method)
{
ClassMethodLocation classMethodLocation = container.getMethodLocationsFor(lexeme).get(0);
ClassReferenceLocation classReferenceLocation = null;
try
{
classReferenceLocation = container.getClassReferenceLocationsFor(classMethodLocation.owner).get(0);
} catch (Exception ignored)
{
}

String containerName = activeResource.resource.workingName + "-" + this.container.getDecompiler();
ClassFileContainer classFileContainer = classFiles.get(containerName);
classFileContainer.fieldMembers.forEach((field1, field2) -> {
if (field1.equals(token))
if (classReferenceLocation == null)
return null;

String packagePath = classReferenceLocation.packagePath;
if (packagePath.startsWith("java") || packagePath.startsWith("javax") || packagePath.startsWith("com.sun"))
return null;

String resourceName = packagePath + "/" + classMethodLocation.owner;
if (resourceContainer.resourceClasses.containsKey(resourceName))
{
BytecodeViewer.viewer.workPane.addClassResource(resourceContainer, resourceName + ".class");
ClassViewer activeResource = (ClassViewer) BytecodeViewer.viewer.workPane.getActiveResource();
HashMap<String, ClassFileContainer> classFiles = BytecodeViewer.viewer.workPane.classFiles;
return wait(classFiles, activeResource);
}
} else
{
ClassReferenceLocation classReferenceLocation = container.getClassReferenceLocationsFor(lexeme).get(0);
String packagePath = classReferenceLocation.packagePath;
if (packagePath.startsWith("java") || packagePath.startsWith("javax") || packagePath.startsWith("com.sun"))
return null;

String resourceName = packagePath + "/" + lexeme;
if (resourceContainer.resourceClasses.containsKey(resourceName))
{
BytecodeViewer.viewer.workPane.addClassResource(resourceContainer, resourceName + ".class");
ClassViewer activeResource = (ClassViewer) BytecodeViewer.viewer.workPane.getActiveResource();
HashMap<String, ClassFileContainer> classFiles = BytecodeViewer.viewer.workPane.classFiles;
return wait(classFiles, activeResource);
}
}

return null;
}

private void open(RSyntaxTextArea textArea, boolean isClass, boolean isField, boolean isMethod)
{
Thread thread = new Thread(() -> {
Token token = textArea.modelToToken(textArea.getCaretPosition());
token = TokenUtil.getToken(textArea, token);
String lexeme = token.getLexeme();
ClassFileContainer classFileContainer;
if (isClass)
{
classFileContainer = openClass(lexeme, false, false);
if (classFileContainer == null)
return;

classFileContainer.classReferences.forEach((className, classReference) -> {
if (className.equals(lexeme))
{
classReference.forEach(classReferenceLocation -> {
if (classReferenceLocation.type.equals("declaration"))
{
moveCursor(classReferenceLocation.line, classReferenceLocation.columnStart);
}
});
}
});
} else if (isField)
{
classFileContainer = openClass(lexeme, true, false);
if (classFileContainer == null)
return;

classFileContainer.fieldMembers.forEach((fieldName, fields) -> {
if (fieldName.equals(lexeme))
{
field2.forEach(classFieldLocation -> {
fields.forEach(classFieldLocation -> {
if (classFieldLocation.type.equals("declaration"))
{
for (int i = 0; i < 3; i++)
{
BytecodeViewPanel panel = activeResource.getPanel(i);
if (panel.textArea != null)
{
if (panel.decompiler.getDecompilerName().equals(this.container.getDecompiler()))
{
Element root = panel.textArea.getDocument().getDefaultRootElement();
int startOffset = root.getElement(classFieldLocation.line - 1).getStartOffset() + (classFieldLocation.columnStart - 1);
panel.textArea.setCaretPosition(startOffset);
for (CaretListener caretListener : panel.textArea.getCaretListeners())
{
if (caretListener instanceof BytecodeViewPanelUpdater.MarkerCaretListener)
{
BytecodeViewPanelUpdater.MarkerCaretListener markerCaretListener = (BytecodeViewPanelUpdater.MarkerCaretListener) caretListener;
markerCaretListener.caretUpdate(new CaretEvent(panel.textArea)
{
@Override
public int getDot()
{
return panel.textArea.getCaret().getDot();
}

@Override
public int getMark()
{
return 0;
}
});
}
}

panel.textArea.requestFocusInWindow();
break;
}
}
}
moveCursor(classFieldLocation.line, classFieldLocation.columnStart);
}
});
}
});
} else if (isMethod)
{
classFileContainer = openClass(lexeme, false, true);
if (classFileContainer == null)
return;

classFileContainer.methodMembers.forEach((methodName, methods) -> {
if (methodName.equals(lexeme))
{
methods.forEach(method -> {
if (method.decRef.equalsIgnoreCase("declaration"))
{
moveCursor(method.line, method.columnStart);
}
});
}
});
}
}, "Open Class");
thread.start();
}

private ClassFileContainer wait(HashMap<String, ClassFileContainer> classFiles, ClassViewer activeResource)
{
String containerName = activeResource.resource.workingName + "-" + this.container.getDecompiler();
try
{
BytecodeViewer.updateBusyStatus(true);
Thread.getAllStackTraces().forEach((name, stackTrace) -> {
if (name.getName().equals("Pane Update"))
{
try
{
name.join();
} catch (InterruptedException e)
{
throw new RuntimeException(e);
}
}
});
thread.start();
} catch (Exception e)
{
throw new RuntimeException(e);
} finally
{
BytecodeViewer.updateBusyStatus(false);
}

return classFiles.get(containerName);
}

private void moveCursor(int line, int columnStart)
{
for (int i = 0; i < 3; i++)
{
BytecodeViewPanel panel = ((ClassViewer) BytecodeViewer.viewer.workPane.getActiveResource()).getPanel(i);
if (panel.decompiler.getDecompilerName().equals(this.container.getDecompiler()))
{
Element root = panel.textArea.getDocument().getDefaultRootElement();
int startOffset = root.getElement(line - 1).getStartOffset() + (columnStart - 1);
panel.textArea.setCaretPosition(startOffset);
for (CaretListener caretListener : panel.textArea.getCaretListeners())
{
if (caretListener instanceof BytecodeViewPanelUpdater.MarkerCaretListener)
{
BytecodeViewPanelUpdater.MarkerCaretListener markerCaretListener = (BytecodeViewPanelUpdater.MarkerCaretListener) caretListener;
markerCaretListener.caretUpdate(new CaretEvent(panel.textArea)
{
@Override
public int getDot()
{
return panel.textArea.getCaret().getDot();
}

@Override
public int getMark()
{
return 0;
}
});
}
}

panel.textArea.requestFocusInWindow();
break;
}
}
}
}
Loading

0 comments on commit 9a08a5f

Please sign in to comment.