Token parsing updates.

- Fixed a few bugs
- Added methods and classes (highlighting and go-to)
This commit is contained in:
Cody 2024-09-21 23:15:58 -06:00
parent 7b7f8976ea
commit 9a08a5f100

AI 샘플 코드 생성 중입니다

Loading...
7 changed files with 499 additions and 228 deletions

View File

@ -1,6 +1,7 @@
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;
@ -8,6 +9,9 @@ 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;
@ -45,7 +49,7 @@ public class GoToAction extends AbstractAction
// 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;
}
@ -98,88 +102,247 @@ public class GoToAction extends AbstractAction
}
}
}));
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))
{
field2.forEach(classFieldLocation -> {
if (classFieldLocation.type.equals("declaration"))
classReference.forEach(classReferenceLocation -> {
if (classReferenceLocation.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(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))
{
fields.forEach(classFieldLocation -> {
if (classFieldLocation.type.equals("declaration"))
{
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;
}
}
}
}

View File

@ -34,9 +34,7 @@ import the.bytecode.club.bytecodeviewer.gui.hexviewer.HexViewer;
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.BytecodeViewPanel;
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer;
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.ClassLocalVariableLocation;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.ClassParameterLocation;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.*;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.TokenUtil;
import the.bytecode.club.bytecodeviewer.util.MethodParser;
@ -117,7 +115,7 @@ public class BytecodeViewPanelUpdater implements Runnable
final String decompiledSource = decompiler.getDecompiler().decompileClassNode(viewer.resource.getResourceClassNode(), classBytes);
ClassFileContainer container = new ClassFileContainer(viewer.resource.workingName + "-" + decompiler.getDecompilerName(), decompiledSource, viewer.resource.container);
if (!container.hasBeenParsed)
if (!BytecodeViewer.viewer.workPane.classFiles.containsKey(viewer.resource.workingName + "-" + decompiler.getDecompilerName()))
{
container.parse();
BytecodeViewer.viewer.workPane.classFiles.put(viewer.resource.workingName + "-" + decompiler.getDecompilerName(), container);
@ -446,9 +444,13 @@ public class BytecodeViewPanelUpdater implements Runnable
Token token = textArea.modelToToken(textArea.getCaretPosition());
if (token == null)
{
highlighterEx.clearMarkOccurrencesHighlights();
errorStripe.refreshMarkers();
return;
token = textArea.modelToToken(textArea.getCaretPosition() - 1);
if (token == null)
{
highlighterEx.clearMarkOccurrencesHighlights();
errorStripe.refreshMarkers();
return;
}
}
token = TokenUtil.getToken(textArea, token);
@ -468,6 +470,11 @@ public class BytecodeViewPanelUpdater implements Runnable
*/
markField(textArea, classFileContainer, line, column, finalToken, highlighterEx);
/*
Methods
*/
markMethod(textArea, classFileContainer, line, column, finalToken, highlighterEx);
/*
Method parameters
*/
@ -478,6 +485,11 @@ public class BytecodeViewPanelUpdater implements Runnable
*/
markMethodLocalVariable(textArea, classFileContainer, line, column, finalToken, highlighterEx);
/*
Class references
*/
markClasses(textArea, classFileContainer, line, column, finalToken, highlighterEx);
errorStripe.refreshMarkers();
}
@ -489,20 +501,11 @@ public class BytecodeViewPanelUpdater implements Runnable
try
{
Element root = textArea.getDocument().getDefaultRootElement();
for (
ClassFieldLocation location :
classFileContainer.getFieldLocationsFor(finalToken.getLexeme())
)
for (ClassFieldLocation location : classFileContainer.getFieldLocationsFor(finalToken.getLexeme()))
{
int startOffset = root
.getElement(location.line - 1)
.getStartOffset() + (location.columnStart - 1);
int endOffset = root
.getElement(location.line - 1)
.getStartOffset() + (location.columnEnd - 1);
highlighterEx.addMarkedOccurrenceHighlight(
startOffset, endOffset, new SmartHighlightPainter()
);
int startOffset = root.getElement(location.line - 1).getStartOffset() + (location.columnStart - 1);
int endOffset = root.getElement(location.line - 1).getStartOffset() + (location.columnEnd - 1);
highlighterEx.addMarkedOccurrenceHighlight(startOffset, endOffset, new SmartHighlightPainter());
}
} catch (BadLocationException ex)
{
@ -512,6 +515,35 @@ public class BytecodeViewPanelUpdater implements Runnable
}));
}
private void markMethod(RSyntaxTextArea textArea, ClassFileContainer classFileContainer, int line, int column, Token finalToken, RSyntaxTextAreaHighlighterEx highlighterEx)
{
classFileContainer.methodMembers.values().forEach(methods -> methods.forEach(method -> {
String owner;
String parameters;
if (method.line == line && method.columnStart - 1 <= column && method.columnEnd >= column)
{
owner = method.owner;
parameters = method.methodParameterTypes;
Element root = textArea.getDocument().getDefaultRootElement();
for (ClassMethodLocation location : classFileContainer.getMethodLocationsFor(finalToken.getLexeme()))
{
try
{
if (Objects.equals(owner, location.owner) && Objects.equals(parameters, location.methodParameterTypes))
{
int startOffset = root.getElement(location.line - 1).getStartOffset() + (location.columnStart - 1);
int endOffset = root.getElement(location.line - 1).getStartOffset() + (location.columnEnd - 1);
highlighterEx.addMarkedOccurrenceHighlight(startOffset, endOffset, new SmartHighlightPainter());
}
} catch (BadLocationException e)
{
throw new RuntimeException(e);
}
}
}
}));
}
/**
* Search through the text area and mark all occurrences that match the selected token.
*
@ -522,14 +554,7 @@ public class BytecodeViewPanelUpdater implements Runnable
* @param finalToken the token
* @param highlighterEx the highlighter
*/
private static void markMethodParameter(
RSyntaxTextArea textArea,
ClassFileContainer classFileContainer,
int line,
int column,
Token finalToken,
RSyntaxTextAreaHighlighterEx highlighterEx
)
private static void markMethodParameter(RSyntaxTextArea textArea, ClassFileContainer classFileContainer, int line, int column, Token finalToken, RSyntaxTextAreaHighlighterEx highlighterEx)
{
classFileContainer.methodParameterMembers.values().forEach(parameters -> parameters.forEach(parameter -> {
String method;
@ -539,23 +564,14 @@ public class BytecodeViewPanelUpdater implements Runnable
try
{
Element root = textArea.getDocument().getDefaultRootElement();
for (
ClassParameterLocation location :
classFileContainer.getParameterLocationsFor(finalToken.getLexeme())
)
for (ClassParameterLocation location : classFileContainer.getParameterLocationsFor(finalToken.getLexeme()))
{
if (Objects.equals(method, location.method))
{
int startOffset = root
.getElement(location.line - 1)
.getStartOffset() + (location.columnStart - 1);
int endOffset = root
.getElement(location.line - 1)
.getStartOffset() + (location.columnEnd - 1);
int startOffset = root.getElement(location.line - 1).getStartOffset() + (location.columnStart - 1);
int endOffset = root.getElement(location.line - 1).getStartOffset() + (location.columnEnd - 1);
highlighterEx.addMarkedOccurrenceHighlight(
startOffset, endOffset, new SmartHighlightPainter()
);
highlighterEx.addMarkedOccurrenceHighlight(startOffset, endOffset, new SmartHighlightPainter());
}
}
} catch (BadLocationException ex)
@ -576,14 +592,7 @@ public class BytecodeViewPanelUpdater implements Runnable
* @param finalToken the token
* @param highlighterEx the highlighter
*/
private static void markMethodLocalVariable(
RSyntaxTextArea textArea,
ClassFileContainer classFileContainer,
int line,
int column,
Token finalToken,
RSyntaxTextAreaHighlighterEx highlighterEx
)
private static void markMethodLocalVariable(RSyntaxTextArea textArea, ClassFileContainer classFileContainer, int line, int column, Token finalToken, RSyntaxTextAreaHighlighterEx highlighterEx)
{
classFileContainer.methodLocalMembers.values().forEach(localVariables -> localVariables.forEach(localVariable -> {
String method;
@ -593,23 +602,14 @@ public class BytecodeViewPanelUpdater implements Runnable
try
{
Element root = textArea.getDocument().getDefaultRootElement();
for (
ClassLocalVariableLocation location :
classFileContainer.getLocalLocationsFor(finalToken.getLexeme())
)
for (ClassLocalVariableLocation location : classFileContainer.getLocalLocationsFor(finalToken.getLexeme()))
{
if (Objects.equals(method, location.method))
{
int startOffset = root
.getElement(location.line - 1)
.getStartOffset() + (location.columnStart - 1);
int endOffset = root
.getElement(location.line - 1)
.getStartOffset() + (location.columnEnd - 1);
int startOffset = root.getElement(location.line - 1).getStartOffset() + (location.columnStart - 1);
int endOffset = root.getElement(location.line - 1).getStartOffset() + (location.columnEnd - 1);
highlighterEx.addMarkedOccurrenceHighlight(
startOffset, endOffset, new SmartHighlightPainter()
);
highlighterEx.addMarkedOccurrenceHighlight(startOffset, endOffset, new SmartHighlightPainter());
}
}
} catch (BadLocationException ex)
@ -620,9 +620,29 @@ public class BytecodeViewPanelUpdater implements Runnable
}));
}
private void markClasses(RSyntaxTextArea textArea, ClassFileContainer classFileContainer, int line, int column, Token finalToken, RSyntaxTextAreaHighlighterEx highlighterEx)
{
classFileContainer.classReferences.values().forEach(classes -> classes.forEach(clazz -> {
if (clazz.line == line && clazz.columnStart - 1 <= column && clazz.columnEnd - 1 >= column)
{
try
{
Element root = textArea.getDocument().getDefaultRootElement();
for (ClassReferenceLocation location : classFileContainer.getClassReferenceLocationsFor(finalToken.getLexeme()))
{
int startOffset = root.getElement(location.line - 1).getStartOffset() + (location.columnStart - 1);
int endOffset = root.getElement(location.line - 1).getStartOffset() + (location.columnEnd - 1);
highlighterEx.addMarkedOccurrenceHighlight(startOffset, endOffset, new SmartHighlightPainter());
}
} catch (Exception ignored)
{
}
}
}));
}
public class MarkerCaretListener implements CaretListener
{
private final String classContainerName;
public MarkerCaretListener(String classContainerName)

View File

@ -9,10 +9,7 @@ import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSol
import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
import the.bytecode.club.bytecodeviewer.resources.ResourceContainer;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.ClassFieldLocation;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.ClassLocalVariableLocation;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.ClassMethodLocation;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.ClassParameterLocation;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.*;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.MyVoidVisitor;
import java.io.IOException;
@ -20,6 +17,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.NavigableMap;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicReference;
/**
* This is a container for a specific class. The container name is based on the actual class name and the decompiler used.
@ -33,7 +31,7 @@ public class ClassFileContainer
public transient NavigableMap<String, ArrayList<ClassParameterLocation>> methodParameterMembers = new TreeMap<>();
public transient NavigableMap<String, ArrayList<ClassLocalVariableLocation>> methodLocalMembers = new TreeMap<>();
public transient NavigableMap<String, ArrayList<ClassMethodLocation>> methodMembers = new TreeMap<>();
public transient NavigableMap<String, String> imports = new TreeMap<>();
public transient NavigableMap<String, ArrayList<ClassReferenceLocation>> classReferences = new TreeMap<>();
public boolean hasBeenParsed = false;
public final String className;
@ -56,7 +54,7 @@ public class ClassFileContainer
{
try
{
TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(path));
TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(false), new JarTypeSolver(path));
StaticJavaParser.getParserConfiguration().setSymbolResolver(new JavaSymbolSolver(typeSolver));
CompilationUnit compilationUnit = StaticJavaParser.parse(this.content);
compilationUnit.accept(new MyVoidVisitor(this, compilationUnit), null);
@ -71,12 +69,12 @@ public class ClassFileContainer
public String getName()
{
return this.className.substring(this.className.lastIndexOf('.') + 1);
return this.className.substring(this.className.lastIndexOf('/') + 1, this.className.lastIndexOf('.'));
}
public String getDecompiler()
{
return getName().substring(6);
return this.className.substring(this.className.lastIndexOf('-') + 1);
}
public String getParentContainer()
@ -124,14 +122,28 @@ public class ClassFileContainer
return methodMembers.getOrDefault(key, new ArrayList<>());
}
public void putImport(String key, String value)
public void putClassReference(String key, ClassReferenceLocation value)
{
this.imports.put(key, value);
this.classReferences.computeIfAbsent(key, v -> new ArrayList<>()).add(value);
}
public String getImport(String key)
public List<ClassReferenceLocation> getClassReferenceLocationsFor(String key)
{
String value = this.imports.get(key);
return value + "/" + key;
return classReferences.getOrDefault(key, null);
}
public String getClassForField(String fieldName)
{
AtomicReference<String> className = new AtomicReference<>("");
this.classReferences.forEach((s, v) -> {
v.forEach(classReferenceLocation -> {
if (classReferenceLocation.fieldName.equals(fieldName))
{
className.set(classReferenceLocation.packagePath + "/" + s);
}
});
});
return className.get();
}
}

View File

@ -7,15 +7,17 @@ package the.bytecode.club.bytecodeviewer.resources.classcontainer.locations;
public class ClassMethodLocation
{
public final String owner;
public final String signature;
public final String methodParameterTypes;
public final String decRef;
public final int line;
public final int columnStart;
public final int columnEnd;
public ClassMethodLocation(String owner, String methodParameterTypes, String decRef, int line, int columnStart, int columnEnd)
public ClassMethodLocation(String owner, String signature, String methodParameterTypes, String decRef, int line, int columnStart, int columnEnd)
{
this.owner = owner;
this.signature = signature;
this.methodParameterTypes = methodParameterTypes;
this.decRef = decRef;
this.line = line;

View File

@ -0,0 +1,33 @@
package the.bytecode.club.bytecodeviewer.resources.classcontainer.locations;
/**
* Created by Bl3nd.
* Date: 9/20/2024
*/
public class ClassReferenceLocation
{
public final String owner;
public final String packagePath;
public final String fieldName;
public final String type;
public final int line;
public final int columnStart;
public final int columnEnd;
public ClassReferenceLocation(String owner, String packagePath, String fieldName, String type, int line, int columnStart, int columnEnd)
{
this.owner = owner;
this.packagePath = packagePath;
this.fieldName = fieldName;
this.type = type;
this.line = line;
this.columnStart = columnStart;
this.columnEnd = columnEnd;
}
@Override
public String toString()
{
return "ClassClassLocation{" + "owner='" + owner + '\'' + ", fieldName='" + fieldName + '\'' + ", type='" + type + '\'' + ", line=" + line + ", columnStart=" + columnStart + ", columnEnd=" + columnEnd + '}';
}
}

View File

@ -2,22 +2,19 @@ package the.bytecode.club.bytecodeviewer.resources.classcontainer.parser;
import com.github.javaparser.Range;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.ast.body.*;
import com.github.javaparser.ast.expr.*;
import com.github.javaparser.ast.stmt.*;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import com.github.javaparser.resolution.UnsolvedSymbolException;
import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
import com.github.javaparser.resolution.types.ResolvedType;
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.ClassLocalVariableLocation;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.ClassMethodLocation;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.ClassParameterLocation;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.*;
/**
* Our custom visitor that allows us to get the information from JavaParser we need.
@ -47,6 +44,19 @@ public class MyVoidVisitor extends VoidVisitorAdapter<Object>
return method.getDeclarationAsString(false, false);
}
@Override
public void visit(ClassOrInterfaceDeclaration n, Object arg)
{
super.visit(n, arg);
SimpleName name = n.getName();
Range range = name.getRange().get();
ResolvedReferenceTypeDeclaration resolve = n.resolve();
int line = range.begin.line;
int columnStart = range.begin.column;
int columnEnd = range.end.column;
this.classFileContainer.putClassReference(resolve.getName(), new ClassReferenceLocation(getOwner(), resolve.getPackageName(), "", "declaration", line, columnStart, columnEnd + 1));
}
/**
* Visit all {@link FieldDeclaration}s.
* <p>
@ -72,16 +82,21 @@ public class MyVoidVisitor extends VoidVisitorAdapter<Object>
}
@Override
public void visit(ImportDeclaration n, Object arg)
public void visit(ClassOrInterfaceType n, Object arg)
{
super.visit(n, arg);
if (!n.isAsterisk())
try
{
Name class_ = n.getName();
String className = class_.getIdentifier();
String package_ = Objects.requireNonNull(class_.getQualifier().orElse(null)).asString();
package_ = package_.replace('.', '/');
this.classFileContainer.putImport(className, package_);
ResolvedType resolve = n.resolve();
String nameAsString = n.getNameAsString();
String qualifiedName = resolve.asReferenceType().getQualifiedName();
String packagePath = qualifiedName.substring(0, qualifiedName.lastIndexOf('.')).replace('.', '/');
Range range = n.getName().getRange().get();
int line = range.begin.line;
int columnStart = range.begin.column;
int columnEnd = range.end.column;
this.classFileContainer.putClassReference(nameAsString, new ClassReferenceLocation(getOwner(), packagePath, "", "reference", line, columnStart, columnEnd + 1));
} catch (Exception e) {
}
}
@ -144,9 +159,17 @@ public class MyVoidVisitor extends VoidVisitorAdapter<Object>
String qualifiedName = resolvedType.asReferenceType().getQualifiedName();
String className = qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1);
String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf('.'));
this.classFileContainer.putImport(className, packageName.replace('.', '/'));
this.classFileContainer.putClassReference(className, new ClassReferenceLocation(getOwner(), packageName.replace('.', '/'), fieldName, "reference", line1, columnStart1, columnEnd1 + 1));
this.classFileContainer.putField(fieldName, new ClassFieldLocation(name1, "reference", line, columnStart, columnEnd + 1));
}
} else if (scope instanceof ThisExpr) {
ThisExpr thisExpr = (ThisExpr) scope;
ResolvedType resolvedType = n.getSymbolResolver().calculateType(thisExpr);
String qualifiedName = resolvedType.asReferenceType().getQualifiedName();
String className = qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1);
String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf('.'));
this.classFileContainer.putClassReference(className, new ClassReferenceLocation(getOwner(), packageName.replace('.', '/'), fieldName, "reference", line, columnStart, columnEnd + 1));
this.classFileContainer.putField(fieldName, new ClassFieldLocation(className, "reference", line, columnStart, columnEnd + 1));
}
}
}
@ -165,8 +188,6 @@ public class MyVoidVisitor extends VoidVisitorAdapter<Object>
public void visit(ConstructorDeclaration n, Object arg)
{
super.visit(n, arg);
StringBuilder parameterTypes = new StringBuilder();
AtomicInteger count = new AtomicInteger();
n.getParameters().forEach(parameter -> {
SimpleName name = parameter.getName();
String parameterName = name.getIdentifier();
@ -174,25 +195,24 @@ public class MyVoidVisitor extends VoidVisitorAdapter<Object>
int line = range.begin.line;
int columnStart = range.begin.column;
int columnEnd = range.end.column;
this.classFileContainer.putParameter(parameterName, new ClassParameterLocation(getOwner(), n.getDeclarationAsString(false, false),
"declaration", line, columnStart, columnEnd + 1));
count.getAndIncrement();
parameterTypes.append(parameter.getTypeAsString());
if (n.getParameters().size() > 1 && count.get() != n.getParameters().size())
{
parameterTypes.append(", ");
}
this.classFileContainer.putParameter(parameterName, new ClassParameterLocation(getOwner(), n.getDeclarationAsString(false, false), "declaration", line, columnStart, columnEnd + 1));
});
ResolvedConstructorDeclaration resolve = n.resolve();
String signature = resolve.getQualifiedSignature();
String parameters = "";
if (resolve.getNumberOfParams() != 0)
{
parameters = signature.substring(signature.indexOf('(') + 1, signature.lastIndexOf(')'));
}
SimpleName simpleName = n.getName();
String constructorName = simpleName.getIdentifier();
Range range = simpleName.getRange().get();
int line = range.begin.line;
int columnStart = range.begin.column;
int columnEnd = range.end.column;
this.classFileContainer.putMethod(constructorName, new ClassMethodLocation(getOwner(), parameterTypes.toString(), "declaration", line,
columnStart,
columnEnd + 1));
this.classFileContainer.putMethod(constructorName, new ClassMethodLocation(resolve.getClassName(), signature, parameters, "declaration", line, columnStart, columnEnd + 1));
}
/**
@ -261,33 +281,31 @@ public class MyVoidVisitor extends VoidVisitorAdapter<Object>
public void visit(MethodDeclaration n, Object arg)
{
super.visit(n, arg);
StringBuilder parameterTypes = new StringBuilder();
AtomicInteger count = new AtomicInteger();
n.getParameters().forEach(parameter -> {
SimpleName name = parameter.getName();
String parameterName = name.getIdentifier();
Range range = name.getRange().get();
int line = range.begin.line;
int columnStart = range.begin.column;
int columnEnd = range.end.column;
this.classFileContainer.putParameter(parameterName, new ClassParameterLocation(getOwner(), n.getDeclarationAsString(false, false),
"declaration", line, columnStart, columnEnd + 1));
count.getAndIncrement();
parameterTypes.append(parameter.getTypeAsString());
if (n.getParameters().size() > 1 && count.get() != n.getParameters().size())
{
parameterTypes.append(", ");
}
});
ResolvedMethodDeclaration resolve = n.resolve();
String signature = resolve.getQualifiedSignature();
String parameters = "";
if (resolve.getNumberOfParams() != 0)
{
parameters = signature.substring(signature.indexOf('(') + 1, signature.lastIndexOf(')'));
}
SimpleName methodSimpleName = n.getName();
String methodName = methodSimpleName.getIdentifier();
Range range = methodSimpleName.getRange().get();
int line = range.begin.line;
int columnStart = range.begin.column;
int columnEnd = range.end.column;
this.classFileContainer.putMethod(methodName, new ClassMethodLocation(getOwner(), parameterTypes.toString(), "declaration", line, columnStart,
columnEnd + 1));
this.classFileContainer.putMethod(methodSimpleName.getIdentifier(), new ClassMethodLocation(resolve.getClassName(), signature, parameters, "declaration", line, columnStart, columnEnd + 1));
n.getParameters().forEach(parameter -> {
SimpleName name = parameter.getName();
String parameterName = name.getIdentifier();
Range range1 = name.getRange().get();
int line1 = range1.begin.line;
int columnStart1 = range1.begin.column;
int columnEnd1 = range1.end.column;
this.classFileContainer.putParameter(parameterName, new ClassParameterLocation(getOwner(), n.getDeclarationAsString(false, false),
"declaration", line1, columnStart1, columnEnd1 + 1));
});
}
/**
@ -311,6 +329,26 @@ public class MyVoidVisitor extends VoidVisitorAdapter<Object>
}
}
try
{
ResolvedMethodDeclaration resolve = n.resolve();
String signature = resolve.getQualifiedSignature();
String parameters = "";
if (resolve.getNumberOfParams() != 0)
{
parameters = signature.substring(signature.indexOf('(') + 1, signature.lastIndexOf(')'));
}
SimpleName methodSimpleName = n.getName();
Range range = methodSimpleName.getRange().get();
int line = range.begin.line;
int columnStart = range.begin.column;
int columnEnd = range.end.column;
this.classFileContainer.putMethod(methodSimpleName.getIdentifier(), new ClassMethodLocation(resolve.getClassName(), signature, parameters, "reference", line, columnStart, columnEnd + 1));
} catch (Exception e)
{
}
if (method != null)
{
if (n.hasScope())
@ -319,28 +357,32 @@ public class MyVoidVisitor extends VoidVisitorAdapter<Object>
if (scope instanceof NameExpr)
{
NameExpr nameExpr = (NameExpr) scope;
SimpleName simpleName = nameExpr.getName();
String name = simpleName.getIdentifier();
Range range1 = simpleName.getRange().get();
int line1 = range1.begin.line;
int columnStart1 = range1.begin.column;
int columnEnd1 = range1.end.column;
try
{
ResolvedValueDeclaration vd = nameExpr.resolve();
SimpleName simpleName = nameExpr.getName();
String name = simpleName.getIdentifier();
Range range = simpleName.getRange().get();
int line = range.begin.line;
int columnStart = range.begin.column;
int columnEnd = range.end.column;
if (vd.isField())
{
this.classFileContainer.putField(name, new ClassFieldLocation(getOwner(), "reference", line, columnStart, columnEnd + 1));
this.classFileContainer.putField(name, new ClassFieldLocation(getOwner(), "reference", line1, columnStart1, columnEnd1 + 1));
} else if (vd.isVariable())
{
this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1));
this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line1, columnStart1, columnEnd1 + 1));
} else if (vd.isParameter())
{
this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1));
this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line1, columnStart1, columnEnd1 + 1));
}
} catch (UnsolvedSymbolException ignored)
{
ResolvedType resolvedType = n.getSymbolResolver().calculateType(nameExpr);
String qualifiedName = resolvedType.asReferenceType().getQualifiedName();
String className = qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1);
String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf('.'));
this.classFileContainer.putClassReference(className, new ClassReferenceLocation(getOwner(), packageName.replace('.', '/'), "", "reference", line1, columnStart1, columnEnd1 + 1));
}
}
}
@ -353,19 +395,19 @@ public class MyVoidVisitor extends VoidVisitorAdapter<Object>
ResolvedValueDeclaration vd = nameExpr.resolve();
SimpleName simpleName = nameExpr.getName();
String name = simpleName.getIdentifier();
Range range = simpleName.getRange().get();
int line = range.begin.line;
int columnStart = range.begin.column;
int columnEnd = range.end.column;
Range range1 = simpleName.getRange().get();
int line1 = range1.begin.line;
int columnStart1 = range1.begin.column;
int columnEnd1 = range1.end.column;
if (vd.isField())
{
this.classFileContainer.putField(name, new ClassFieldLocation(getOwner(), "reference", line, columnStart, columnEnd + 1));
this.classFileContainer.putField(name, new ClassFieldLocation(getOwner(), "reference", line1, columnStart1, columnEnd1 + 1));
} else if (vd.isVariable())
{
this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(finalMethod), "reference", line, columnStart, columnEnd + 1));
this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(finalMethod), "reference", line1, columnStart1, columnEnd1 + 1));
} else if (vd.isParameter())
{
this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(finalMethod), "reference", line, columnStart, columnEnd + 1));
this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(finalMethod), "reference", line1, columnStart1, columnEnd1 + 1));
}
}
});
@ -382,19 +424,19 @@ public class MyVoidVisitor extends VoidVisitorAdapter<Object>
ResolvedValueDeclaration vd = nameExpr.resolve();
SimpleName simpleName = nameExpr.getName();
String name = simpleName.getIdentifier();
Range range = simpleName.getRange().get();
int line = range.begin.line;
int columnStart = range.begin.column;
int columnEnd = range.end.column;
Range range1 = simpleName.getRange().get();
int line1 = range1.begin.line;
int columnStart1 = range1.begin.column;
int columnEnd1 = range1.end.column;
if (vd.isField())
{
this.classFileContainer.putField(name, new ClassFieldLocation(getOwner(), "reference", line, columnStart, columnEnd + 1));
this.classFileContainer.putField(name, new ClassFieldLocation(getOwner(), "reference", line1, columnStart1, columnEnd1 + 1));
} else if (vd.isVariable())
{
this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), "static", "reference", line, columnStart, columnEnd + 1));
this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), "static", "reference", line1, columnStart1, columnEnd1 + 1));
} else if (vd.isParameter())
{
this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), "static", "reference", line, columnStart, columnEnd + 1));
this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), "static", "reference", line1, columnStart1, columnEnd1 + 1));
}
} catch (UnsolvedSymbolException ignored)
{
@ -410,19 +452,19 @@ public class MyVoidVisitor extends VoidVisitorAdapter<Object>
ResolvedValueDeclaration vd = nameExpr.resolve();
SimpleName simpleName = nameExpr.getName();
String name = simpleName.getIdentifier();
Range range = simpleName.getRange().get();
int line = range.begin.line;
int columnStart = range.begin.column;
int columnEnd = range.end.column;
Range range1 = simpleName.getRange().get();
int line1 = range1.begin.line;
int columnStart1 = range1.begin.column;
int columnEnd1 = range1.end.column;
if (vd.isField())
{
this.classFileContainer.putField(name, new ClassFieldLocation(getOwner(), "reference", line, columnStart, columnEnd + 1));
this.classFileContainer.putField(name, new ClassFieldLocation(getOwner(), "reference", line1, columnStart1, columnEnd1 + 1));
} else if (vd.isVariable())
{
this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), "static", "reference", line, columnStart, columnEnd + 1));
this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), "static", "reference", line1, columnStart1, columnEnd1 + 1));
} else if (vd.isParameter())
{
this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), "static", "reference", line, columnStart, columnEnd + 1));
this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), "static", "reference", line1, columnStart1, columnEnd1 + 1));
}
}
});
@ -640,9 +682,7 @@ public class MyVoidVisitor extends VoidVisitorAdapter<Object>
} else if (vd.isVariable())
{
this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), "static", "reference", line, columnStart, columnEnd + 1));
}/* else if (vd.isParameter()) {
System.err.println("AssignExpr - parameter2");
}*/
}
} catch (UnsolvedSymbolException e)
{
System.err.println(nameExpr.getName().getIdentifier() + " not resolved. " + e.getMessage());

View File

@ -24,6 +24,7 @@ public class TokenUtil
|| lexeme.equals(" ")
|| lexeme.equals(";")
|| lexeme.equals(",")
|| lexeme.equals(">")
? textArea.modelToToken(textArea.getCaretPosition() - 1)
: token;
}