Compare commits
15 Commits
5cf85f78d4
...
edadceba64
Author | SHA1 | Date | |
---|---|---|---|
|
edadceba64 | ||
|
9860c9d63c | ||
|
f560fa5b26 | ||
|
d485b9b34b | ||
|
3f1fd5a3f3 | ||
|
879b5e64b5 | ||
|
14c7ed2e57 | ||
|
29d29e14ac | ||
|
471ae44864 | ||
|
cf92749337 | ||
|
336d60ba06 | ||
|
340bec4fe8 | ||
|
82789aa38e | ||
|
a9cbd661ca | ||
|
ec47a2d6ed |
2
pom.xml
2
pom.xml
|
@ -51,7 +51,7 @@
|
|||
<treelayout.version>1.0.3</treelayout.version>
|
||||
<webp-imageio.version>a8f700b</webp-imageio.version>
|
||||
<xpp3.version>1.1.4c</xpp3.version>
|
||||
<java-parser.version>3.26.1</java-parser.version>
|
||||
<java-parser.version>3.26.2</java-parser.version>
|
||||
<taskmanager.version>1.0.1</taskmanager.version>
|
||||
<google-java-format.version>1.7</google-java-format.version> <!-- Newer versions require Java 11+ -->
|
||||
<disk-lib.version>1.2.0</disk-lib.version>
|
||||
|
|
|
@ -27,6 +27,7 @@ import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
|||
import javax.swing.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Whenever a key is pressed on the swing UI it should get logged here
|
||||
|
@ -121,8 +122,18 @@ public class GlobalHotKeys
|
|||
BytecodeViewer.updateBusyStatus(true);
|
||||
Thread jarExport = new Thread(() ->
|
||||
{
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), file.getAbsolutePath());
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
try
|
||||
{
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), file.getAbsolutePath());
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
BytecodeViewer.handleException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
}
|
||||
}, "Jar Export");
|
||||
jarExport.start();
|
||||
}
|
||||
|
|
|
@ -42,8 +42,8 @@ public class Settings
|
|||
{
|
||||
public static boolean firstBoot = true; //stays true after settings load on first boot
|
||||
public static boolean hasSetLanguageAsSystemLanguage = false;
|
||||
private static List<String> recentPlugins;
|
||||
private static List<String> recentFiles;
|
||||
private static List<String> recentPlugins = new ArrayList<>();
|
||||
private static List<String> recentFiles = new ArrayList<>();
|
||||
|
||||
//decompilers will automatically delete their temp files, useful to turn off if you want to quickly debug a decompilers results
|
||||
public static boolean DECOMPILERS_AUTOMATICALLY_CLEANUP = true;
|
||||
|
@ -53,15 +53,18 @@ public class Settings
|
|||
{
|
||||
try
|
||||
{
|
||||
File filesFile = new File(getBCVDirectory() + FS + "recentfiles.bcv");
|
||||
File pluginsFile = new File(getBCVDirectory() + FS + "recentplugins.bcv");
|
||||
|
||||
if (new File(FILES_NAME).exists())
|
||||
recentFiles = gson.fromJson(DiskReader.readString(FILES_NAME), new TypeToken<ArrayList<String>>() {}.getType());
|
||||
else
|
||||
recentFiles = Arrays.asList(DiskReader.readArray(getBCVDirectory() + FS + "recentfiles.bcv"));
|
||||
else if (filesFile.exists())
|
||||
recentFiles = Arrays.asList(DiskReader.readArray(filesFile));
|
||||
|
||||
if (new File(PLUGINS_NAME).exists())
|
||||
recentPlugins = gson.fromJson(DiskReader.readString(PLUGINS_NAME), new TypeToken<ArrayList<String>>() {}.getType());
|
||||
else
|
||||
recentPlugins = Arrays.asList(DiskReader.readArray(getBCVDirectory() + FS + "recentplugins.bcv"));
|
||||
else if (pluginsFile.exists())
|
||||
recentPlugins = Arrays.asList(DiskReader.readArray(pluginsFile));
|
||||
|
||||
MiscUtils.deduplicateAndTrim(recentFiles, maxRecentFiles);
|
||||
MiscUtils.deduplicateAndTrim(recentPlugins, maxRecentFiles);
|
||||
|
|
|
@ -127,7 +127,7 @@ public class GoToAction extends AbstractAction
|
|||
}
|
||||
else
|
||||
{
|
||||
methods.stream().filter(classMethodLocation -> classMethodLocation.owner.equals(method.owner)).forEach(classMethodLocation ->
|
||||
methods.stream().filter(classMethodLocation -> classMethodLocation.signature.equals(method.signature)).forEach(classMethodLocation ->
|
||||
{
|
||||
if (classMethodLocation.decRef.equalsIgnoreCase("declaration"))
|
||||
{
|
||||
|
@ -211,7 +211,9 @@ public class GoToAction extends AbstractAction
|
|||
if (packagePath.startsWith("java") || packagePath.startsWith("javax") || packagePath.startsWith("com.sun"))
|
||||
return null;
|
||||
|
||||
String resourceName = packagePath + "/" + classMethodLocation.owner;
|
||||
String resourceName = classMethodLocation.owner;
|
||||
if (!packagePath.isEmpty())
|
||||
resourceName = packagePath + "/" + classMethodLocation.owner;
|
||||
|
||||
if (resourceContainer.resourceClasses.containsKey(resourceName))
|
||||
{
|
||||
|
@ -229,7 +231,11 @@ public class GoToAction extends AbstractAction
|
|||
if (packagePath.startsWith("java") || packagePath.startsWith("javax") || packagePath.startsWith("com.sun"))
|
||||
return null;
|
||||
|
||||
String resourceName = packagePath + "/" + lexeme;
|
||||
String resourceName = lexeme;
|
||||
if (!packagePath.isEmpty())
|
||||
{
|
||||
resourceName = packagePath + "/" + lexeme;
|
||||
}
|
||||
|
||||
if (resourceContainer.resourceClasses.containsKey(resourceName))
|
||||
{
|
||||
|
|
|
@ -51,6 +51,7 @@ public class BytecodeViewPanel extends JPanel
|
|||
public BytecodeViewPanel(int panelIndex, ClassViewer viewer)
|
||||
{
|
||||
super(new BorderLayout());
|
||||
|
||||
this.panelIndex = panelIndex;
|
||||
this.viewer = viewer;
|
||||
}
|
||||
|
@ -63,7 +64,7 @@ public class BytecodeViewPanel extends JPanel
|
|||
if (viewer.resource == null)
|
||||
add(new JLabel("ERROR: Resource Viewer Missing Resource"));
|
||||
|
||||
//TODO remove when bcel support is added
|
||||
//TODO remove when bcel support is added
|
||||
else if (viewer.resource.getResourceClassNode() == null)
|
||||
add(new JLabel("ERROR: Resource Viewer Missing ClassNode"));
|
||||
}
|
||||
|
|
|
@ -513,6 +513,7 @@ public class BytecodeViewPanelUpdater implements Runnable
|
|||
if (token == null)
|
||||
{
|
||||
highlighterEx.clearMarkOccurrencesHighlights();
|
||||
errorStripe.refreshMarkers();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package the.bytecode.club.bytecodeviewer.resources.classcontainer;
|
||||
|
||||
import com.github.javaparser.StaticJavaParser;
|
||||
import com.github.javaparser.*;
|
||||
import com.github.javaparser.ast.CompilationUnit;
|
||||
import com.github.javaparser.resolution.TypeSolver;
|
||||
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
|
||||
|
@ -10,7 +10,7 @@ import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeS
|
|||
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
|
||||
import the.bytecode.club.bytecodeviewer.resources.ResourceContainer;
|
||||
import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.*;
|
||||
import the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.MyVoidVisitor;
|
||||
import the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors.MyVoidVisitor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -56,9 +56,21 @@ public class ClassFileContainer
|
|||
{
|
||||
if (shouldParse())
|
||||
{
|
||||
TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(false), new JarTypeSolver(path));
|
||||
StaticJavaParser.getParserConfiguration().setSymbolResolver(new JavaSymbolSolver(typeSolver));
|
||||
CompilationUnit compilationUnit = StaticJavaParser.parse(this.content);
|
||||
TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(true), new JarTypeSolver(path));
|
||||
JavaParser parser = new JavaParser();
|
||||
parser.getParserConfiguration().setSymbolResolver(new JavaSymbolSolver(typeSolver));
|
||||
ParseResult<CompilationUnit> parse = parser.parse(this.content);
|
||||
if (!parse.isSuccessful())
|
||||
{
|
||||
System.err.println("Failed to parse: " + this.getName());
|
||||
parse.getProblems().forEach(System.out::println);
|
||||
return false;
|
||||
}
|
||||
|
||||
CompilationUnit compilationUnit = parse.getResult().orElse(null);
|
||||
if (compilationUnit == null)
|
||||
return false;
|
||||
|
||||
compilationUnit.accept(new MyVoidVisitor(this, compilationUnit), null);
|
||||
return true;
|
||||
}
|
||||
|
@ -67,11 +79,6 @@ public class ClassFileContainer
|
|||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Parsing error: " + className);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -88,7 +95,10 @@ public class ClassFileContainer
|
|||
|
||||
public String getName()
|
||||
{
|
||||
return this.className.substring(this.className.lastIndexOf('/') + 1, this.className.lastIndexOf('.'));
|
||||
if (this.className.contains("/"))
|
||||
return this.className.substring(this.className.lastIndexOf('/') + 1, this.className.lastIndexOf('.'));
|
||||
else
|
||||
return this.className.substring(0, this.className.lastIndexOf('.'));
|
||||
}
|
||||
|
||||
public String getDecompiler()
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,122 @@
|
|||
package the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors;
|
||||
|
||||
import com.github.javaparser.Range;
|
||||
import com.github.javaparser.ast.CompilationUnit;
|
||||
import com.github.javaparser.ast.body.CallableDeclaration;
|
||||
import com.github.javaparser.ast.expr.*;
|
||||
import the.bytecode.club.bytecodeviewer.resources.classcontainer.ClassFileContainer;
|
||||
import the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors.ParserUtil.Value;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors.ParserUtil.*;
|
||||
|
||||
/**
|
||||
* Created by Bl3nd.
|
||||
* Date: 10/1/2024
|
||||
*/
|
||||
class ArrayParser
|
||||
{
|
||||
|
||||
static void parseAccess(CompilationUnit compilationUnit, ArrayAccessExpr expr, ClassFileContainer container)
|
||||
{
|
||||
Expression valueExp = expr.getName();
|
||||
if (valueExp instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) valueExp;
|
||||
CallableDeclaration<?> method = findMethodForExpression(expr, compilationUnit);
|
||||
if (method == null)
|
||||
{
|
||||
method = findConstructorForExpression(expr, compilationUnit);
|
||||
}
|
||||
|
||||
if (method == null)
|
||||
{
|
||||
System.err.println("ArrayAccess1 - Method not found");
|
||||
return;
|
||||
}
|
||||
|
||||
Range range = nameExpr.getName().getRange().orElse(null);
|
||||
if (range == null)
|
||||
return;
|
||||
|
||||
Value nameValue = new Value(nameExpr.getName(), range);
|
||||
putResolvedValues(container, "reference", method, nameExpr, nameValue);
|
||||
}
|
||||
|
||||
Expression indexExp = expr.getIndex();
|
||||
if (indexExp instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) indexExp;
|
||||
CallableDeclaration<?> method = findMethodForExpression(expr, compilationUnit);
|
||||
if (method == null)
|
||||
method = findConstructorForExpression(expr, compilationUnit);
|
||||
|
||||
if (method == null)
|
||||
{
|
||||
System.err.println("ArrayAccess2 - Method not found");
|
||||
return;
|
||||
}
|
||||
|
||||
Range range = nameExpr.getName().getRange().orElse(null);
|
||||
if (range == null)
|
||||
return;
|
||||
|
||||
Value indexValue = new Value(nameExpr.getName(), range);
|
||||
putResolvedValues(container, "reference", method, nameExpr, indexValue);
|
||||
}
|
||||
}
|
||||
|
||||
static void parseCreation(CompilationUnit compilationUnit, ArrayCreationExpr expr,
|
||||
ClassFileContainer container)
|
||||
{
|
||||
expr.getLevels().forEach(level -> {
|
||||
Expression dimensionExpr = level.getDimension().orElse(null);
|
||||
if (dimensionExpr instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) dimensionExpr;
|
||||
CallableDeclaration<?> method = findMethodForExpression(expr, compilationUnit);
|
||||
if (method == null)
|
||||
method = findConstructorForExpression(expr, compilationUnit);
|
||||
|
||||
if (method == null)
|
||||
{
|
||||
System.err.println("ArrayCreation - Method not found");
|
||||
return;
|
||||
}
|
||||
|
||||
Range range = nameExpr.getName().getRange().orElse(null);
|
||||
if (range == null)
|
||||
return;
|
||||
|
||||
Value dimensionValue = new Value(nameExpr.getName(), range);
|
||||
putResolvedValues(container, "reference", method, nameExpr, dimensionValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void parseInitializer(CompilationUnit compilationUnit, ArrayInitializerExpr expr,
|
||||
ClassFileContainer container)
|
||||
{
|
||||
expr.getValues().forEach(value -> {
|
||||
if (value instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) value;
|
||||
CallableDeclaration<?> method = findMethodForExpression(expr, compilationUnit);
|
||||
if (method == null)
|
||||
method = findConstructorForExpression(expr, compilationUnit);
|
||||
|
||||
if (method == null)
|
||||
{
|
||||
System.err.println("ArrayInitializer - Method not found");
|
||||
return;
|
||||
}
|
||||
|
||||
Range range = nameExpr.getName().getRange().orElse(null);
|
||||
if (range == null)
|
||||
return;
|
||||
|
||||
Value valueValue = new Value(nameExpr.getName(), range);
|
||||
putResolvedValues(container, "reference", method, nameExpr, valueValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors;
|
||||
|
||||
import com.github.javaparser.Range;
|
||||
import com.github.javaparser.ast.body.CallableDeclaration;
|
||||
import com.github.javaparser.ast.expr.AssignExpr;
|
||||
import com.github.javaparser.ast.expr.NameExpr;
|
||||
import com.github.javaparser.ast.expr.SimpleName;
|
||||
import com.github.javaparser.resolution.UnsolvedSymbolException;
|
||||
import the.bytecode.club.bytecodeviewer.resources.classcontainer.ClassFileContainer;
|
||||
import the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors.ParserUtil.Value;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors.ParserUtil.printException;
|
||||
import static the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors.ParserUtil.putResolvedValues;
|
||||
|
||||
/**
|
||||
* Created by Bl3nd.
|
||||
* Date: 9/29/2024
|
||||
*/
|
||||
class AssignParser
|
||||
{
|
||||
|
||||
static void parse(ClassFileContainer container, AssignExpr expr, CallableDeclaration<?> method)
|
||||
{
|
||||
if (expr.getValue() instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) expr.getValue();
|
||||
Range range = nameExpr.getName().getRange().orElse(null);
|
||||
if (range == null)
|
||||
return;
|
||||
|
||||
Value value = new Value(nameExpr.getName(), range);
|
||||
try
|
||||
{
|
||||
putResolvedValues(container, "reference", method, nameExpr, value);
|
||||
}
|
||||
catch (UnsolvedSymbolException e)
|
||||
{
|
||||
printException(expr, e);
|
||||
}
|
||||
}
|
||||
|
||||
if (expr.getTarget() instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) expr.getTarget();
|
||||
try
|
||||
{
|
||||
SimpleName simpleName = nameExpr.getName();
|
||||
Range range = simpleName.getRange().orElse(null);
|
||||
if (range == null)
|
||||
return;
|
||||
|
||||
Value target = new Value(nameExpr.getName(), range);
|
||||
putResolvedValues(container, "reference", method, nameExpr, target);
|
||||
}
|
||||
catch (UnsolvedSymbolException e)
|
||||
{
|
||||
printException(expr, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void parseStatic(ClassFileContainer container, AssignExpr expr)
|
||||
{
|
||||
if (expr.getValue() instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) expr.getValue();
|
||||
Range range = nameExpr.getName().getRange().orElse(null);
|
||||
if (range == null)
|
||||
return;
|
||||
|
||||
Value value = new Value(nameExpr.getName(), range);
|
||||
try
|
||||
{
|
||||
putResolvedValues(container, "reference", nameExpr, value);
|
||||
}
|
||||
catch (UnsolvedSymbolException e)
|
||||
{
|
||||
printException(expr, e);
|
||||
}
|
||||
}
|
||||
|
||||
if (expr.getTarget() instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) expr.getTarget();
|
||||
try
|
||||
{
|
||||
Range range = nameExpr.getName().getRange().orElse(null);
|
||||
if (range == null)
|
||||
return;
|
||||
|
||||
Value target = new Value(nameExpr.getName(), range);
|
||||
putResolvedValues(container, "reference", nameExpr, target);
|
||||
}
|
||||
catch (UnsolvedSymbolException e)
|
||||
{
|
||||
printException(expr, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors;
|
||||
|
||||
import com.github.javaparser.Range;
|
||||
import com.github.javaparser.ast.CompilationUnit;
|
||||
import com.github.javaparser.ast.body.CallableDeclaration;
|
||||
import com.github.javaparser.ast.expr.ConditionalExpr;
|
||||
import com.github.javaparser.ast.expr.Expression;
|
||||
import com.github.javaparser.ast.expr.NameExpr;
|
||||
import the.bytecode.club.bytecodeviewer.resources.classcontainer.ClassFileContainer;
|
||||
import the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors.ParserUtil.Value;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors.ParserUtil.*;
|
||||
|
||||
/**
|
||||
* Created by Bl3nd.
|
||||
* Date: 10/1/2024
|
||||
*/
|
||||
class ConditionalParser
|
||||
{
|
||||
|
||||
static void parse(CompilationUnit compilationUnit, ConditionalExpr expr, ClassFileContainer container)
|
||||
{
|
||||
CallableDeclaration<?> method = findMethodForExpression(expr, compilationUnit);
|
||||
if (method == null)
|
||||
method = findConstructorForExpression(expr, compilationUnit);
|
||||
|
||||
if (method == null)
|
||||
return;
|
||||
|
||||
Expression elseExpr = expr.getElseExpr();
|
||||
if (elseExpr instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) elseExpr;
|
||||
Range range = nameExpr.getName().getRange().orElse(null);
|
||||
if (range == null)
|
||||
return;
|
||||
|
||||
Value elseValue = new Value(nameExpr.getName(), range);
|
||||
putResolvedValues(container, "reference", method, nameExpr, elseValue);
|
||||
}
|
||||
|
||||
Expression thenExpr = expr.getThenExpr();
|
||||
if (thenExpr instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) thenExpr;
|
||||
Range range = nameExpr.getName().getRange().orElse(null);
|
||||
if (range == null)
|
||||
return;
|
||||
|
||||
Value thenValue = new Value(nameExpr.getName(), range);
|
||||
putResolvedValues(container, "reference", method, nameExpr, thenValue);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
package the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors;
|
||||
|
||||
import com.github.javaparser.Range;
|
||||
import com.github.javaparser.ast.expr.*;
|
||||
import com.github.javaparser.resolution.UnsolvedSymbolException;
|
||||
import the.bytecode.club.bytecodeviewer.resources.classcontainer.ClassFileContainer;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors.ParserUtil.*;
|
||||
|
||||
/**
|
||||
* Created by Bl3nd.
|
||||
* Date: 9/28/2024
|
||||
*/
|
||||
class FieldAccessParser
|
||||
{
|
||||
|
||||
static void parse(ClassFileContainer container, FieldAccessExpr expr)
|
||||
{
|
||||
Range fieldRange = Objects.requireNonNull(expr.getTokenRange().orElse(null)).getEnd().getRange().orElse(null);
|
||||
if (fieldRange == null)
|
||||
return;
|
||||
|
||||
Value fieldValue = new Value(expr.getName(), fieldRange);
|
||||
|
||||
Expression scope = expr.getScope();
|
||||
|
||||
// Ex. Clazz.field -> Clazz
|
||||
if (scope instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) scope;
|
||||
Range scopeRange = nameExpr.getRange().orElse(null);
|
||||
if (scopeRange == null)
|
||||
return;
|
||||
|
||||
Value scopeValue = new Value(nameExpr.getName(), scopeRange);
|
||||
|
||||
try
|
||||
{
|
||||
putClassResolvedValues(container, expr, nameExpr, scopeValue, fieldValue);
|
||||
}
|
||||
catch (UnsolvedSymbolException ignore)
|
||||
{
|
||||
try
|
||||
{
|
||||
putClassResolvedValues(container, expr, nameExpr, scopeValue, fieldValue);
|
||||
}
|
||||
catch (UnsolvedSymbolException e)
|
||||
{
|
||||
printException(expr, e);
|
||||
}
|
||||
}
|
||||
} // Ex. this.field
|
||||
else if (scope instanceof ThisExpr)
|
||||
{
|
||||
ThisExpr thisExpr = (ThisExpr) scope;
|
||||
try
|
||||
{
|
||||
putFieldResolvedValues(container, expr, thisExpr, fieldValue);
|
||||
} catch (UnsolvedSymbolException e)
|
||||
{
|
||||
printException(expr, e);
|
||||
}
|
||||
}
|
||||
else if (scope instanceof EnclosedExpr)
|
||||
{
|
||||
EnclosedExpr enclosedExpr = (EnclosedExpr) scope;
|
||||
try
|
||||
{
|
||||
putFieldResolvedValues(container, expr, enclosedExpr, fieldValue);
|
||||
} catch (UnsolvedSymbolException e)
|
||||
{
|
||||
printException(expr, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void parseStatic(ClassFileContainer container, FieldAccessExpr expr)
|
||||
{
|
||||
Range fieldRange = Objects.requireNonNull(expr.getTokenRange().orElse(null)).getEnd().getRange().orElse(null);
|
||||
if (fieldRange == null)
|
||||
return;
|
||||
|
||||
Value fieldValue = new Value(expr.getName(), fieldRange);
|
||||
|
||||
Expression scope = expr.getScope();
|
||||
|
||||
if (scope instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) scope;
|
||||
Range scopeRange = nameExpr.getRange().orElse(null);
|
||||
if (scopeRange == null)
|
||||
return;
|
||||
|
||||
Value scopeValue = new Value(nameExpr.getName(), scopeRange);
|
||||
|
||||
try
|
||||
{
|
||||
putClassResolvedValues(container, expr, nameExpr, scopeValue, fieldValue);
|
||||
}
|
||||
catch (UnsolvedSymbolException ignore)
|
||||
{
|
||||
try
|
||||
{
|
||||
putClassResolvedValues(container, expr, nameExpr, scopeValue, fieldValue);
|
||||
} catch (UnsolvedSymbolException e) {
|
||||
printException(expr, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (scope instanceof ThisExpr)
|
||||
{
|
||||
ThisExpr thisExpr = (ThisExpr) scope;
|
||||
try {
|
||||
putFieldResolvedValues(container, expr, thisExpr, fieldValue);
|
||||
} catch (UnsolvedSymbolException e) {
|
||||
printException(expr, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
package the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors;
|
||||
|
||||
import com.github.javaparser.Range;
|
||||
import com.github.javaparser.ast.body.CallableDeclaration;
|
||||
import com.github.javaparser.ast.expr.Expression;
|
||||
import com.github.javaparser.ast.expr.MethodCallExpr;
|
||||
import com.github.javaparser.ast.expr.NameExpr;
|
||||
import com.github.javaparser.resolution.UnsolvedSymbolException;
|
||||
import the.bytecode.club.bytecodeviewer.resources.classcontainer.ClassFileContainer;
|
||||
import the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors.ParserUtil.Value;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors.ParserUtil.*;
|
||||
|
||||
/**
|
||||
* Created by Bl3nd.
|
||||
* Date: 9/28/2024
|
||||
*/
|
||||
class MethodCallParser
|
||||
{
|
||||
|
||||
static void parse(ClassFileContainer container, MethodCallExpr expr, CallableDeclaration<?> method)
|
||||
{
|
||||
if (expr.hasScope())
|
||||
{
|
||||
Expression scope = expr.getScope().orElse(null);
|
||||
|
||||
/*
|
||||
Ex.
|
||||
field.method -> field
|
||||
variable.method -> variable
|
||||
parameter.method -> parameter
|
||||
*/
|
||||
if (scope instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) scope;
|
||||
Range range = nameExpr.getName().getRange().orElse(null);
|
||||
if (range == null)
|
||||
return;
|
||||
|
||||
Value scopeValue = new Value(nameExpr.getName(), range);
|
||||
|
||||
try
|
||||
{
|
||||
putResolvedValues(container, "reference", method, nameExpr, scopeValue);
|
||||
}
|
||||
catch (UnsolvedSymbolException ignored)
|
||||
{
|
||||
try
|
||||
{
|
||||
putClassResolvedValues(container, expr, nameExpr, scopeValue);
|
||||
} catch (UnsolvedSymbolException e)
|
||||
{
|
||||
printException(expr, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ex. method(arg, arg, ...)
|
||||
expr.getArguments().forEach(argument ->
|
||||
{
|
||||
if (argument instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) argument;
|
||||
Range range = nameExpr.getName().getRange().orElse(null);
|
||||
if (range == null)
|
||||
return;
|
||||
|
||||
Value argName = new Value(nameExpr.getName(), range);
|
||||
try {
|
||||
putResolvedValues(container, "reference", method, nameExpr, argName);
|
||||
} catch (UnsolvedSymbolException e)
|
||||
{
|
||||
printException(expr, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void parseStatic(ClassFileContainer container, MethodCallExpr expr)
|
||||
{
|
||||
if (expr.hasScope())
|
||||
{
|
||||
/*
|
||||
Ex.
|
||||
field.method -> field
|
||||
variable.method -> variable
|
||||
parameter.method -> parameter
|
||||
*/
|
||||
Expression scope = expr.getScope().orElse(null);
|
||||
if (scope instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) scope;
|
||||
Range range = nameExpr.getName().getRange().orElse(null);
|
||||
if (range == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Value scopeValue = new Value(nameExpr.getName(), range);
|
||||
|
||||
try {
|
||||
putResolvedValues(container, "reference", nameExpr, scopeValue);
|
||||
} catch (UnsolvedSymbolException ignored)
|
||||
{
|
||||
try
|
||||
{
|
||||
putClassResolvedValues(container, expr, nameExpr, scopeValue);
|
||||
} catch (UnsolvedSymbolException e)
|
||||
{
|
||||
printException(expr, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expr.getArguments().forEach(argument ->
|
||||
{
|
||||
if (argument instanceof NameExpr)
|
||||
{
|
||||
NameExpr nameExpr = (NameExpr) argument;
|
||||
Range range = nameExpr.getName().getRange().orElse(null);
|
||||
if (range == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Value argValue = new Value(nameExpr.getName(), range);
|
||||
|
||||
try
|
||||
{
|
||||
putResolvedValues(container, "reference", nameExpr, argValue);
|
||||
} catch (UnsolvedSymbolException e)
|
||||
{
|
||||
printException(expr, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,36 @@
|
|||
package the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors;
|
||||
|
||||
import com.github.javaparser.ast.CompilationUnit;
|
||||
import com.github.javaparser.ast.Node;
|
||||
import com.github.javaparser.ast.body.Parameter;
|
||||
import com.github.javaparser.ast.expr.SimpleName;
|
||||
import the.bytecode.club.bytecodeviewer.resources.classcontainer.ClassFileContainer;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors.ParserUtil.*;
|
||||
|
||||
/**
|
||||
* Created by Bl3nd.
|
||||
* Date: 10/1/2024
|
||||
*/
|
||||
public class ParameterParser
|
||||
{
|
||||
|
||||
public static void parse(CompilationUnit compilationUnit, Parameter p, ClassFileContainer container)
|
||||
{
|
||||
Node node = p.getParentNode().orElse(null);
|
||||
if (node == null)
|
||||
return;
|
||||
|
||||
String methodName = findMethodOwnerFor(compilationUnit, node);
|
||||
if (methodName == null) {
|
||||
System.err.println("Parameter - Method not found");
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleName name = p.getName();
|
||||
name.getRange().ifPresent(range -> {
|
||||
Value parameter = new Value(name, range);
|
||||
putParameter(container, parameter, methodName, "declaration");
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,517 @@
|
|||
package the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors;
|
||||
|
||||
import com.github.javaparser.Range;
|
||||
import com.github.javaparser.ast.CompilationUnit;
|
||||
import com.github.javaparser.ast.Node;
|
||||
import com.github.javaparser.ast.body.CallableDeclaration;
|
||||
import com.github.javaparser.ast.body.ConstructorDeclaration;
|
||||
import com.github.javaparser.ast.body.InitializerDeclaration;
|
||||
import com.github.javaparser.ast.body.MethodDeclaration;
|
||||
import com.github.javaparser.ast.expr.Expression;
|
||||
import com.github.javaparser.ast.expr.NameExpr;
|
||||
import com.github.javaparser.ast.expr.SimpleName;
|
||||
import com.github.javaparser.ast.stmt.CatchClause;
|
||||
import com.github.javaparser.ast.stmt.Statement;
|
||||
import com.github.javaparser.ast.stmt.TryStmt;
|
||||
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
|
||||
import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
|
||||
import com.github.javaparser.resolution.types.ResolvedReferenceType;
|
||||
import com.github.javaparser.resolution.types.ResolvedType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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.ClassReferenceLocation;
|
||||
|
||||
/**
|
||||
* Created by Bl3nd.
|
||||
* Date: 9/28/2024
|
||||
*/
|
||||
class ParserUtil
|
||||
{
|
||||
|
||||
static class Value
|
||||
{
|
||||
|
||||
final String name;
|
||||
final int line;
|
||||
final int columnStart;
|
||||
final int columnEnd;
|
||||
|
||||
public Value(SimpleName simpleName, Range range)
|
||||
{
|
||||
this.name = simpleName.getIdentifier();
|
||||
this.line = range.begin.line;
|
||||
this.columnStart = range.begin.column;
|
||||
this.columnEnd = range.end.column;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put resolved value types (field, variable and parameter) that have a method as an owner.
|
||||
*
|
||||
* @param container The class container
|
||||
* @param method The owner method of the type
|
||||
* @param resolveExpr The {@code NameExpr}
|
||||
* @param value The value
|
||||
*/
|
||||
static void putResolvedValues(ClassFileContainer container, String decRef, CallableDeclaration<?> method,
|
||||
NameExpr resolveExpr, Value value)
|
||||
{
|
||||
ResolvedValueDeclaration vd = resolveExpr.resolve();
|
||||
if (vd.isField())
|
||||
{
|
||||
container.putField(value.name, new ClassFieldLocation(getOwner(container), decRef,
|
||||
value.line, value.columnStart, value.columnEnd + 1));
|
||||
}
|
||||
else if (vd.isVariable())
|
||||
{
|
||||
container.putLocalVariable(value.name, new ClassLocalVariableLocation(getOwner(container)
|
||||
, getMethod(method), decRef, value.line, value.columnStart,
|
||||
value.columnEnd + 1));
|
||||
}
|
||||
else if (vd.isParameter())
|
||||
{
|
||||
container.putParameter(value.name, new ClassParameterLocation(getOwner(container),
|
||||
getMethod(method), decRef, value.line, value.columnStart,
|
||||
value.columnEnd + 1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put resolved value types (field, variable and parameter) that are in a static block.
|
||||
*
|
||||
* @param container The class container
|
||||
* @param resolveExpr The {@code NameExpr}
|
||||
* @param value The value
|
||||
*/
|
||||
static void putResolvedValues(ClassFileContainer container, String decRef, NameExpr resolveExpr, Value value)
|
||||
{
|
||||
ResolvedValueDeclaration vd = resolveExpr.resolve();
|
||||
if (vd.isField())
|
||||
{
|
||||
container.putField(value.name, new ClassFieldLocation(getOwner(container), decRef,
|
||||
value.line, value.columnStart, value.columnEnd + 1));
|
||||
}
|
||||
else if (vd.isVariable())
|
||||
{
|
||||
container.putLocalVariable(value.name, new ClassLocalVariableLocation(getOwner(container)
|
||||
, "static", decRef, value.line, value.columnStart, value.columnEnd + 1));
|
||||
}
|
||||
else if (vd.isParameter())
|
||||
{
|
||||
container.putParameter(value.name, new ClassParameterLocation(getOwner(container),
|
||||
"static", decRef, value.line, value.columnStart, value.columnEnd + 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void putParameter(ClassFileContainer container, Value parameter, String method, String decRef)
|
||||
{
|
||||
container.putParameter(parameter.name, new ClassParameterLocation(getOwner(container), method, decRef,
|
||||
parameter.line, parameter.columnStart, parameter.columnEnd + 1));
|
||||
}
|
||||
|
||||
static void putLocalVariable(ClassFileContainer container, Value variable, String method, String decRef)
|
||||
{
|
||||
container.putLocalVariable(variable.name, new ClassLocalVariableLocation(getOwner(container), method, decRef,
|
||||
variable.line, variable.columnStart, variable.columnEnd + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Put both the class and field reference.
|
||||
*
|
||||
* @param container The class container
|
||||
* @param visitedExpr The main expression
|
||||
* @param resolveExpr The expression to resolve
|
||||
* @param scopeValue The scope value
|
||||
* @param fieldValue The field value
|
||||
*/
|
||||
static void putClassResolvedValues(ClassFileContainer container, Expression visitedExpr, Expression resolveExpr,
|
||||
Value scopeValue, Value fieldValue)
|
||||
{
|
||||
ResolvedType resolvedType = visitedExpr.getSymbolResolver().calculateType(resolveExpr);
|
||||
if (!resolvedType.isReferenceType())
|
||||
return;
|
||||
|
||||
String qualifiedName = resolvedType.asReferenceType().getQualifiedName();
|
||||
String className = qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1);
|
||||
String packageName = "";
|
||||
if (qualifiedName.contains("."))
|
||||
packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf('.')).replace('.', '/');
|
||||
|
||||
container.putClassReference(className, new ClassReferenceLocation(ParserUtil.getOwner(container), packageName
|
||||
, fieldValue.name, "reference", scopeValue.line, scopeValue.columnStart, scopeValue.columnEnd + 1));
|
||||
container.putField(fieldValue.name, new ClassFieldLocation(scopeValue.name, "reference", fieldValue.line,
|
||||
fieldValue.columnStart, fieldValue.columnEnd + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Put only the class reference.
|
||||
*
|
||||
* @param container The class container
|
||||
* @param visitedExpr The main expression
|
||||
* @param resolveExpr The expression to resolve
|
||||
* @param scopeValue The scope value
|
||||
*/
|
||||
static void putClassResolvedValues(ClassFileContainer container, Expression visitedExpr,
|
||||
Expression resolveExpr, Value scopeValue)
|
||||
{
|
||||
ResolvedType resolvedType = visitedExpr.getSymbolResolver().calculateType(resolveExpr);
|
||||
if (!resolvedType.isReferenceType())
|
||||
return;
|
||||
|
||||
ResolvedReferenceType referenceType = resolvedType.asReferenceType();
|
||||
if (!referenceType.hasName())
|
||||
return;
|
||||
|
||||
String qualifiedName = referenceType.getQualifiedName();
|
||||
String className = qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1);
|
||||
String packageName = "";
|
||||
if (qualifiedName.contains("."))
|
||||
packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf('.')).replace('.', '/');
|
||||
|
||||
container.putClassReference(className, new ClassReferenceLocation(ParserUtil.getOwner(container), packageName
|
||||
, "", "reference", scopeValue.line, scopeValue.columnStart, scopeValue.columnEnd + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Put only a class field reference.
|
||||
*
|
||||
* @param container The class container
|
||||
* @param visitedExpr The main expression
|
||||
* @param resolveExpr The expression to resolve
|
||||
* @param fieldValue The field value
|
||||
*/
|
||||
static void putFieldResolvedValues(ClassFileContainer container, Expression visitedExpr,
|
||||
Expression resolveExpr, Value fieldValue)
|
||||
{
|
||||
ResolvedType resolvedType = visitedExpr.getSymbolResolver().calculateType(resolveExpr);
|
||||
if (!resolvedType.isReferenceType())
|
||||
return;
|
||||
|
||||
String qualifiedName = resolvedType.asReferenceType().getQualifiedName();
|
||||
String className = qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1);
|
||||
container.putField(fieldValue.name, new ClassFieldLocation(className, "reference", fieldValue.line,
|
||||
fieldValue.columnStart, fieldValue.columnEnd + 1));
|
||||
}
|
||||
|
||||
static void printException(Object o, Exception e)
|
||||
{
|
||||
System.err.println(o.getClass().getSimpleName() + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
static String getOwner(ClassFileContainer container)
|
||||
{
|
||||
return container.getName();
|
||||
}
|
||||
|
||||
static String getMethod(CallableDeclaration<?> method)
|
||||
{
|
||||
return method.getDeclarationAsString(false, false);
|
||||
}
|
||||
|
||||
static @Nullable String findMethodOwnerFor(CompilationUnit compilationUnit, Node node)
|
||||
{
|
||||
if (node instanceof CallableDeclaration<?>)
|
||||
{
|
||||
return ((CallableDeclaration<?>) node).getDeclarationAsString(false, false);
|
||||
}
|
||||
else if (node instanceof CatchClause)
|
||||
{
|
||||
TryStmt statement = (TryStmt) node.getParentNode().orElse(null);
|
||||
if (statement == null)
|
||||
return null;
|
||||
|
||||
CallableDeclaration<?> method = findMethodForStatement(statement, compilationUnit);
|
||||
if (method == null)
|
||||
{
|
||||
method = findConstructorForStatement(statement, compilationUnit);
|
||||
if (method == null)
|
||||
{
|
||||
if (findInitializerForStatement(statement, compilationUnit) != null)
|
||||
return "static";
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return method.getDeclarationAsString(false, false);
|
||||
}
|
||||
else if (node instanceof Statement)
|
||||
{
|
||||
CallableDeclaration<?> method = findMethodForStatement((Statement) node, compilationUnit);
|
||||
if (method == null)
|
||||
{
|
||||
method = findConstructorForStatement((Statement) node, compilationUnit);
|
||||
if (method == null)
|
||||
{
|
||||
if (findInitializerForStatement((Statement) node, compilationUnit) != null)
|
||||
return "static";
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return method.getDeclarationAsString(false, false);
|
||||
}
|
||||
else if (node instanceof Expression)
|
||||
{
|
||||
CallableDeclaration<?> method = findMethodForExpression((Expression) node, compilationUnit);
|
||||
if (method == null)
|
||||
{
|
||||
method = findConstructorForExpression((Expression) node, compilationUnit);
|
||||
if (method == null)
|
||||
{
|
||||
if (findInitializerForExpression((Expression) node, compilationUnit) != null)
|
||||
return "static";
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return method.getDeclarationAsString(false, false);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look through the {@link CompilationUnit} for the specific statement within its methods.
|
||||
*
|
||||
* @param statement The {@code statement} we are looking for
|
||||
* @param cu The {@code CompilationUnit}
|
||||
* @return the method that contains the {@code statement}.
|
||||
*/
|
||||
static MethodDeclaration findMethodForStatement(Statement statement, CompilationUnit cu)
|
||||
{
|
||||
final boolean[] contains = {false};
|
||||
final MethodDeclaration[] methodDeclaration = {null};
|
||||
cu.accept(new VoidVisitorAdapter<Void>()
|
||||
{
|
||||
@Override
|
||||
public void visit(MethodDeclaration n, Void arg)
|
||||
{
|
||||
super.visit(n, arg);
|
||||
if (!n.isAbstract()/* && !contains[0]*/)
|
||||
{
|
||||
for (Statement statement1 : n.getBody().get().getStatements())
|
||||
{
|
||||
if (statement1.containsWithinRange(statement))
|
||||
{
|
||||
contains[0] = true;
|
||||
methodDeclaration[0] = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
|
||||
if (contains[0])
|
||||
{
|
||||
return methodDeclaration[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look through the {@link CompilationUnit} for the specific statement within its methods.
|
||||
*
|
||||
* @param expression The {@code expression} we are looking for
|
||||
* @param cu The {@code CompilationUnit}
|
||||
* @return the method that contains the {@code expression}.
|
||||
*/
|
||||
static MethodDeclaration findMethodForExpression(Expression expression, CompilationUnit cu)
|
||||
{
|
||||
final boolean[] contains = {false};
|
||||
final MethodDeclaration[] methodDeclaration = {null};
|
||||
cu.accept(new VoidVisitorAdapter<Void>()
|
||||
{
|
||||
@Override
|
||||
public void visit(MethodDeclaration n, Void arg)
|
||||
{
|
||||
super.visit(n, arg);
|
||||
if (!n.isAbstract()/* && !contains[0]*/)
|
||||
{
|
||||
for (Statement statement : n.getBody().get().getStatements())
|
||||
{
|
||||
if (statement.containsWithinRange(expression))
|
||||
{
|
||||
contains[0] = true;
|
||||
methodDeclaration[0] = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
|
||||
if (contains[0])
|
||||
{
|
||||
return methodDeclaration[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look through the {@link CompilationUnit} for the specific statement within its methods.
|
||||
*
|
||||
* @param statement The {@code statement} we are looking for
|
||||
* @param cu The {@code CompilationUnit}
|
||||
* @return the constructor that contains the {@code statement}.
|
||||
*/
|
||||
static ConstructorDeclaration findConstructorForStatement(Statement statement, CompilationUnit cu)
|
||||
{
|
||||
final boolean[] contains = {false};
|
||||
final ConstructorDeclaration[] constructorDeclaration = {null};
|
||||
cu.accept(new VoidVisitorAdapter<Void>()
|
||||
{
|
||||
@Override
|
||||
public void visit(ConstructorDeclaration n, Void arg)
|
||||
{
|
||||
super.visit(n, arg);
|
||||
if (contains[0])
|
||||
return;
|
||||
|
||||
for (Statement statement1 : n.getBody().getStatements())
|
||||
{
|
||||
if (statement1.containsWithinRange(statement))
|
||||
{
|
||||
contains[0] = true;
|
||||
constructorDeclaration[0] = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
|
||||
if (contains[0])
|
||||
{
|
||||
return constructorDeclaration[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look through the {@link CompilationUnit} for the specific statement within its methods.
|
||||
*
|
||||
* @param expression The {@code expression} we are looking for
|
||||
* @param cu The {@code CompilationUnit}
|
||||
* @return the constructor that contains the {@code expression}.
|
||||
*/
|
||||
static ConstructorDeclaration findConstructorForExpression(Expression expression, CompilationUnit cu)
|
||||
{
|
||||
final boolean[] contains = {false};
|
||||
final ConstructorDeclaration[] constructorDeclaration = {null};
|
||||
cu.accept(new VoidVisitorAdapter<Void>()
|
||||
{
|
||||
@Override
|
||||
public void visit(ConstructorDeclaration n, Void arg)
|
||||
{
|
||||
super.visit(n, arg);
|
||||
if (contains[0])
|
||||
return;
|
||||
|
||||
for (Statement statement1 : n.getBody().getStatements())
|
||||
{
|
||||
if (statement1.containsWithinRange(expression))
|
||||
{
|
||||
contains[0] = true;
|
||||
constructorDeclaration[0] = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
|
||||
if (contains[0])
|
||||
{
|
||||
return constructorDeclaration[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look through the {@link CompilationUnit} for the specific statement within its methods.
|
||||
*
|
||||
* @param statement The {@code statement} we are looking for
|
||||
* @param cu The {@code CompilationUnit}
|
||||
* @return the initializer that contains the {@code statement}.
|
||||
*/
|
||||
static InitializerDeclaration findInitializerForStatement(Statement statement, CompilationUnit cu)
|
||||
{
|
||||
final boolean[] contains = {false};
|
||||
final InitializerDeclaration[] initializerDeclaration = {null};
|
||||
cu.accept(new VoidVisitorAdapter<Void>()
|
||||
{
|
||||
@Override
|
||||
public void visit(InitializerDeclaration n, Void arg)
|
||||
{
|
||||
super.visit(n, arg);
|
||||
if (contains[0])
|
||||
return;
|
||||
|
||||
for (Statement statement : n.getBody().getStatements())
|
||||
{
|
||||
if (statement.containsWithinRange(statement))
|
||||
{
|
||||
contains[0] = true;
|
||||
initializerDeclaration[0] = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
|
||||
if (contains[0])
|
||||
{
|
||||
return initializerDeclaration[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Look through the {@link CompilationUnit} for the specific statement within its methods.
|
||||
*
|
||||
* @param expression The {@code expression} we are looking for
|
||||
* @param cu The {@code CompilationUnit}
|
||||
* @return the initializer that contains the {@code expression}.
|
||||
*/
|
||||
static InitializerDeclaration findInitializerForExpression(Expression expression, CompilationUnit cu)
|
||||
{
|
||||
final boolean[] contains = {false};
|
||||
final InitializerDeclaration[] initializerDeclaration = {null};
|
||||
cu.accept(new VoidVisitorAdapter<Void>()
|
||||
{
|
||||
@Override
|
||||
public void visit(InitializerDeclaration n, Void arg)
|
||||
{
|
||||
super.visit(n, arg);
|
||||
if (contains[0])
|
||||
return;
|
||||
|
||||
for (Statement statement : n.getBody().getStatements())
|
||||
{
|
||||
if (statement.containsWithinRange(expression))
|
||||
{
|
||||
contains[0] = true;
|
||||
initializerDeclaration[0] = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
|
||||
if (contains[0])
|
||||
{
|
||||
return initializerDeclaration[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -31,6 +31,7 @@ import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
|||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
@ -109,17 +110,26 @@ public class APKExport implements Exporter
|
|||
|
||||
Thread saveThread = new Thread(() ->
|
||||
{
|
||||
BytecodeViewer.updateBusyStatus(true);
|
||||
final String input = TEMP_DIRECTORY + FS + MiscUtils.getRandomizedName() + ".jar";
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), input);
|
||||
|
||||
Thread buildAPKThread = new Thread(() ->
|
||||
try
|
||||
{
|
||||
APKTool.buildAPK(new File(input), file, finalContainer);
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
}, "Process APK");
|
||||
BytecodeViewer.updateBusyStatus(true);
|
||||
final String input = TEMP_DIRECTORY + FS + MiscUtils.getRandomizedName() + ".jar";
|
||||
|
||||
buildAPKThread.start();
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), input);
|
||||
|
||||
Thread buildAPKThread = new Thread(() ->
|
||||
{
|
||||
APKTool.buildAPK(new File(input), file, finalContainer);
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
}, "Process APK");
|
||||
|
||||
buildAPKThread.start();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
BytecodeViewer.handleException(ex);
|
||||
}
|
||||
}, "Jar Export");
|
||||
|
||||
saveThread.start();
|
||||
|
|
|
@ -29,6 +29,7 @@ import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
|||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.FS;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.TEMP_DIRECTORY;
|
||||
|
@ -73,18 +74,27 @@ public class DexExport implements Exporter
|
|||
|
||||
Thread saveAsJar = new Thread(() ->
|
||||
{
|
||||
BytecodeViewer.updateBusyStatus(true);
|
||||
final String input = TEMP_DIRECTORY + FS + MiscUtils.getRandomizedName() + ".jar";
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), input);
|
||||
|
||||
Thread saveAsDex = new Thread(() ->
|
||||
try
|
||||
{
|
||||
Dex2Jar.saveAsDex(new File(input), outputPath);
|
||||
BytecodeViewer.updateBusyStatus(true);
|
||||
final String input = TEMP_DIRECTORY + FS + MiscUtils.getRandomizedName() + ".jar";
|
||||
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), input);
|
||||
|
||||
Thread saveAsDex = new Thread(() ->
|
||||
{
|
||||
Dex2Jar.saveAsDex(new File(input), outputPath);
|
||||
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
}, "Process DEX");
|
||||
|
||||
saveAsDex.start();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
}, "Process DEX");
|
||||
|
||||
saveAsDex.start();
|
||||
BytecodeViewer.handleException(ex);
|
||||
}
|
||||
}, "Jar Export");
|
||||
|
||||
saveAsJar.start();
|
||||
|
|
|
@ -28,6 +28,7 @@ import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
|||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
|
@ -65,8 +66,18 @@ public class ZipExport implements Exporter
|
|||
|
||||
Thread saveThread = new Thread(() ->
|
||||
{
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), file.getAbsolutePath());
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
try
|
||||
{
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), file.getAbsolutePath());
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
BytecodeViewer.handleException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
}
|
||||
}, "Jar Export");
|
||||
|
||||
saveThread.start();
|
||||
|
|
|
@ -405,7 +405,7 @@ public class JarUtils
|
|||
* @param nodeList The loaded ClassNodes
|
||||
* @param path the exact jar output path
|
||||
*/
|
||||
public static void saveAsJar(List<ClassNode> nodeList, String path)
|
||||
public static void saveAsJar(List<ClassNode> nodeList, String path) throws IOException
|
||||
{
|
||||
try (FileOutputStream fos = new FileOutputStream(path);
|
||||
JarOutputStream out = new JarOutputStream(fos))
|
||||
|
@ -448,9 +448,5 @@ public class JarUtils
|
|||
|
||||
fileCollisionPrevention .clear();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user