diff --git a/pom.xml b/pom.xml index 28b80938c..f69cb3649 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ 1.0.3 a8f700b 1.1.4c - 3.26.1 + 3.26.2 1.0.1 1.7 1.2.0 diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/actions/GoToAction.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/actions/GoToAction.java index fcc61d009..23b5409e6 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/actions/GoToAction.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/actions/GoToAction.java @@ -127,7 +127,7 @@ public void actionPerformed(ActionEvent e) } 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 @@ else if (method) 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 @@ else if (method) 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)) { diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/ClassFileContainer.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/ClassFileContainer.java index 56a5e3803..868cbebaa 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/ClassFileContainer.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/ClassFileContainer.java @@ -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 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; @@ -57,8 +57,20 @@ public boolean parse() if (shouldParse()) { TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(false), new JarTypeSolver(path)); - StaticJavaParser.getParserConfiguration().setSymbolResolver(new JavaSymbolSolver(typeSolver)); - CompilationUnit compilationUnit = StaticJavaParser.parse(this.content); + JavaParser parser = new JavaParser(); + parser.getParserConfiguration().setSymbolResolver(new JavaSymbolSolver(typeSolver)); + ParseResult 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 boolean parse() { throw new RuntimeException(e); } - catch (Exception e) - { - System.err.println("Parsing error: " + className); - e.printStackTrace(); - } return false; } @@ -88,7 +95,10 @@ public boolean shouldParse() 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() diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/MyVoidVisitor.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/MyVoidVisitor.java deleted file mode 100644 index b5b25283a..000000000 --- a/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/MyVoidVisitor.java +++ /dev/null @@ -1,1719 +0,0 @@ -package the.bytecode.club.bytecodeviewer.resources.classcontainer.parser; - -import com.github.javaparser.Range; -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.NodeList; -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.*; - -/** - * Our custom visitor that allows us to get the information from JavaParser we need. - *

- * Created by Bl3nd. - * Date: 9/5/2024 - */ -@SuppressWarnings("OptionalGetWithoutIsPresent") -public class MyVoidVisitor extends VoidVisitorAdapter -{ - private final ClassFileContainer classFileContainer; - private final CompilationUnit compilationUnit; - - public MyVoidVisitor(ClassFileContainer container, CompilationUnit compilationUnit) - { - this.classFileContainer = container; - this.compilationUnit = compilationUnit; - } - - private String getOwner() - { - return this.classFileContainer.getName(); - } - - private String getMethod(CallableDeclaration method) - { - 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. - *

- * This only worries about the field that is being declared. - *

- * - * @param n The current {@code FieldDeclaration} - * @param arg Don't worry about it - */ - @Override - public void visit(FieldDeclaration n, Object arg) - { - super.visit(n, arg); - n.getVariables().forEach(variableDeclarator -> - { - SimpleName name = variableDeclarator.getName(); - String fieldName = name.getIdentifier(); - Range range = name.getRange().get(); - int line = range.begin.line; - int columnStart = range.begin.column; - int columnEnd = range.end.column; - this.classFileContainer.putField(fieldName, new ClassFieldLocation(getOwner(), "declaration", line, columnStart, columnEnd + 1)); - }); - } - - @Override - public void visit(ClassOrInterfaceType n, Object arg) - { - super.visit(n, arg); - try - { - 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) - { - } - } - - /** - * Visit all {@link FieldAccessExpr}s. - *

- * This finds the field accesses. - *

- * - * @param n The current {@code FieldAccessExpr} - * @param arg Don't worry about it - */ - @Override - public void visit(FieldAccessExpr n, Object arg) - { - super.visit(n, arg); - SimpleName simpleName = n.getName(); - String fieldName = simpleName.getIdentifier(); - Range range = n.getTokenRange().get().getEnd().getRange().get(); - int line = range.begin.line; - int columnStart = range.begin.column; - int columnEnd = range.end.column; - - if (n.hasScope()) - { - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - } - - if (method != null) - { - Expression scope = n.getScope(); - if (scope instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) scope; - SimpleName simpleName1 = nameExpr.getName(); - String name1 = simpleName1.getIdentifier(); - Range range1 = nameExpr.getRange().get(); - int line1 = range1.begin.line; - int columnStart1 = range1.begin.column; - int columnEnd1 = range1.end.column; - try - { - ResolvedValueDeclaration vd = nameExpr.resolve(); - if (vd.isField()) - { - this.classFileContainer.putField(name1, new ClassFieldLocation(getOwner(), "reference", line1, columnStart1, columnEnd1 + 1)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name1, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line1, columnStart1, columnEnd1 + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name1, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line1, columnStart1, columnEnd1 + 1)); - } - } - catch (UnsolvedSymbolException ignore) - { - 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('.', '/'), 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); - this.classFileContainer.putField(fieldName, new ClassFieldLocation(className, "reference", line, columnStart, columnEnd + 1)); - } - } - } - } - - /** - * Visit all {@link ConstructorDeclaration}s. - *

- * This deals with the parameters and the constructor. Not the body of the constructor. - *

- * - * @param n The current {@code ConstructorDeclaration} - * @param arg Don't worry about it - */ - @Override - public void visit(ConstructorDeclaration n, Object arg) - { - super.visit(n, arg); - 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)); - }); - - if (n.getParentNode().get() instanceof ObjectCreationExpr) - { - ObjectCreationExpr objectCreationExpr = (ObjectCreationExpr) n.getParentNode().get(); - NodeList> bodyDeclarations = objectCreationExpr.getAnonymousClassBody().get(); - if (bodyDeclarations.getFirst().get().equals(n)) - { - return; - } - } - - 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(resolve.getClassName(), signature, parameters, "declaration", line, columnStart, columnEnd + 1)); - } - - /** - * Find all {@link ExplicitConstructorInvocationStmt}s. - *

- * E.g. {@code this()} or {@code this(param, ...)} and {@code super()} or {@code super(param, ...)}. - *

- * - * @param n The current {@code ExplicitConstructorInvocationStmt} - * @param arg Don't worry about it - */ - @Override - public void visit(ExplicitConstructorInvocationStmt n, Object arg) - { - super.visit(n, arg); - ConstructorDeclaration constructor = findConstructorForStatement(n, this.compilationUnit); - if (constructor != null) - { - n.getArguments().forEach(argument -> - { - if (argument instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) argument; - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), constructor.getDeclarationAsString(false, false), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), constructor.getDeclarationAsString(false, false), "reference", line, columnStart, columnEnd + 1)); - } - } - else - { - if ((argument instanceof LongLiteralExpr) || (argument instanceof StringLiteralExpr) || (argument instanceof CharLiteralExpr) || argument instanceof BooleanLiteralExpr || argument instanceof NullLiteralExpr || argument instanceof IntegerLiteralExpr) - { - return; - } - - System.err.println(argument.getClass().getSimpleName()); - } - }); - } - } - - /** - * Visit all {@link MethodDeclaration}s. - *

- * This deals with the parameters and the method name. - *

- * - * @param n The current {@code MethodDeclaration} - * @param arg Don't worry about it - */ - @Override - public void visit(MethodDeclaration n, Object arg) - { - super.visit(n, arg); - 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, "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)); - }); - } - - /** - * Visit all {@link MethodCallExpr}s. - * - * @param n The current {@code MethodCallExpr} - * @param arg Don't worry about it - */ - @Override - public void visit(MethodCallExpr n, Object arg) - { - super.visit(n, arg); - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - InitializerDeclaration staticInitializer = null; - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - if (method == null) - { - staticInitializer = findInitializerForExpression(n, this.compilationUnit); - } - } - - 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()) - { - Expression scope = n.getScope().get(); - 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(); - if (vd.isField()) - { - 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", line1, columnStart1, columnEnd1 + 1)); - } - else if (vd.isParameter()) - { - 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)); - } - } - } - - CallableDeclaration finalMethod = method; - n.getArguments().forEach(argument -> - { - if (argument instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) argument; - ResolvedValueDeclaration vd = nameExpr.resolve(); - 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; - if (vd.isField()) - { - 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", line1, columnStart1, columnEnd1 + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(finalMethod), "reference", line1, columnStart1, columnEnd1 + 1)); - } - } - }); - } - else if (staticInitializer != null) - { - if (n.hasScope()) - { - Expression scope = n.getScope().get(); - if (scope instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) scope; - try - { - ResolvedValueDeclaration vd = nameExpr.resolve(); - 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; - if (vd.isField()) - { - 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", line1, columnStart1, columnEnd1 + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), "static", "reference", line1, columnStart1, columnEnd1 + 1)); - } - } - catch (UnsolvedSymbolException ignored) - { - - } - } - } - - n.getArguments().forEach(argument -> - { - if (argument instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) argument; - ResolvedValueDeclaration vd = nameExpr.resolve(); - 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; - if (vd.isField()) - { - 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", line1, columnStart1, columnEnd1 + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), "static", "reference", line1, columnStart1, columnEnd1 + 1)); - } - } - }); - } - } - - /** - * Visit all {@link ObjectCreationExpr}s. - * - * @param n The current {@code ObjectCreationExpr} - * @param arg Don't worry about it - */ - @Override - public void visit(ObjectCreationExpr n, Object arg) - { - super.visit(n, arg); - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - } - - if (method != null) - { - CallableDeclaration finalMethod = method; - n.getArguments().forEach(argument -> - { - if (argument instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) argument; - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(finalMethod), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(finalMethod), "reference", line, columnStart, columnEnd + 1)); - } - } - }); - } - } - - /** - * Visit all {@link VariableDeclarationExpr}s. - * - * @param n The current {@code VariableDeclarationExpr} - * @param arg Don't worry about it - */ - @Override - public void visit(VariableDeclarationExpr n, Object arg) - { - super.visit(n, arg); - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - InitializerDeclaration staticInitializer = null; - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - if (method == null) - { - staticInitializer = findInitializerForExpression(n, this.compilationUnit); - } - } - - if (method != null) - { - CallableDeclaration finalMethod = method; - n.getVariables().forEach(variable -> - { - ResolvedValueDeclaration vd = variable.resolve(); - SimpleName simpleName = variable.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; - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(finalMethod), "declaration", line, columnStart, columnEnd + 1)); - }); - } - else if (staticInitializer != null) - { - n.getVariables().forEach(variable -> - { - ResolvedValueDeclaration vd = variable.resolve(); - SimpleName simpleName = variable.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; - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), "static", "declaration", line, columnStart, columnEnd + 1)); - }); - } - } - - /** - * Visit all {@link AssignExpr}s. - * - * @param n The current {@code AssignExpr} - * @param arg Don't worry about it - */ - @Override - public void visit(AssignExpr n, Object arg) - { - super.visit(n, arg); - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - InitializerDeclaration staticInitializer = null; - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - if (method == null) - { - staticInitializer = findInitializerForExpression(n, this.compilationUnit); - } - } - - if (method != null) - { - Expression value = n.getValue(); - if (value instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) value; - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - - Expression target = n.getTarget(); - if (target instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) target; - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - catch (UnsolvedSymbolException e) - { - System.err.println(nameExpr.getName().getIdentifier() + " not resolved. " + e.getMessage()); - } - } - } - else if (staticInitializer != null) - { - Expression value = n.getValue(); - if (value instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) value; - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), "static", "reference", line, columnStart, columnEnd + 1)); - }/* else if (vd.isParameter()) { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), "static", "reference", line, columnStart, columnEnd + 1)); - }*/ - } - - Expression target = n.getTarget(); - if (target instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) target; - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), "static", "reference", line, columnStart, columnEnd + 1)); - } - } - catch (UnsolvedSymbolException e) - { - System.err.println(nameExpr.getName().getIdentifier() + " not resolved. " + e.getMessage()); - } - } - } - } - - /** - * Visit all {@link CatchClause}s. - * - * @param n The current {@code CatchClause} - * @param arg Don't worry about it - */ - @Override - public void visit(CatchClause n, Object arg) - { - super.visit(n, arg); - TryStmt parentNode = (TryStmt) n.getParentNode().get(); - CallableDeclaration method = findMethodForStatement(parentNode, this.compilationUnit); - if (method == null) - { - method = findConstructorForStatement(parentNode, this.compilationUnit); - } - - if (method != null) - { - SimpleName simpleName = n.getParameter().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; - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "declaration", line, columnStart, columnEnd + 1)); - } - } - - /** - * Visit all {@link ThrowStmt}s. - * - * @param n The current {@code ThrowStmt} - * @param arg Don't worry about it - */ - @Override - public void visit(ThrowStmt n, Object arg) - { - super.visit(n, arg); - Expression expression = n.getExpression(); - if (expression instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) expression; - CallableDeclaration method = findMethodForStatement(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForStatement(n, this.compilationUnit); - } - - if (method != null) - { - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - } - } - - /** - * Visit all {@link InstanceOfExpr}s. - * - * @param n The current {@code InstanceOfExpr} - * @param arg Don't worry about it - */ - @Override - public void visit(InstanceOfExpr n, Object arg) - { - super.visit(n, arg); - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - } - - if (method != null) - { - Expression expression = n.getExpression(); - if (expression instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) expression; - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - } - } - - /** - * Visit all {@link BinaryExpr}s. - * - * @param n The current {@code BinaryExpr} - * @param arg Don't worry about it - */ - @Override - public void visit(BinaryExpr n, Object arg) - { - super.visit(n, arg); - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - } - - if (method != null) - { - Expression left = n.getLeft(); - if (left instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) left; - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - - Expression right = n.getRight(); - if (right instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) right; - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - } - } - - /** - * Visit all {@link CastExpr}s. - * - * @param n The current {@code CastExpr} - * @param arg Don't worry about it - */ - @Override - public void visit(CastExpr n, Object arg) - { - super.visit(n, arg); - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - } - - if (method != null) - { - Expression expression = n.getExpression(); - if (expression instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) expression; - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - } - } - - /** - * Visit all {@link IfStmt}s. - * - * @param n The current {@code IfStmt} - * @param arg Don't worry about it - */ - @Override - public void visit(IfStmt n, Object arg) - { - super.visit(n, arg); - Expression condition = n.getCondition(); - if (condition instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) condition; - CallableDeclaration method = findMethodForStatement(n, this.compilationUnit); - InitializerDeclaration staticInitializer = null; - if (method == null) - { - method = findConstructorForStatement(n, this.compilationUnit); - if (method == null) - { - staticInitializer = findInitializerForStatement(n, this.compilationUnit); - } - } - - if (method != null) - { - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - else if (staticInitializer != null) - { - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), "static", "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), "static", "reference", line, columnStart, columnEnd + 1)); - } - } - } - } - - /** - * Visit all {@link ArrayInitializerExpr}s. - * - * @param n The current {@code ArrayInitializerExpr} - * @param arg Don't worry about it - */ - @Override - public void visit(ArrayInitializerExpr n, Object arg) - { - super.visit(n, arg); - n.getValues().forEach(value -> - { - if (value instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) value; - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - } - - if (method != null) - { - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - } - }); - } - - /** - * Visit all {@link ArrayCreationExpr}s. - * - * @param n The current {@code ArrayCreationExpr} - * @param arg Don't worry about it - */ - @Override - public void visit(ArrayCreationExpr n, Object arg) - { - super.visit(n, arg); - n.getLevels().forEach(level -> - { - Expression dimension = level.getDimension().orElse(null); - if (dimension instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) dimension; - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - } - - if (method != null) - { - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - } - }); - } - - /** - * Visit all {@link ArrayAccessExpr}s. - * - * @param n The current {@code ArrayAccessExpr} - * @param arg Don't worry about it - */ - @Override - public void visit(ArrayAccessExpr n, Object arg) - { - super.visit(n, arg); - Expression expression = n.getName(); - if (expression instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) expression; - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - } - - if (method != null) - { - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - } - - Expression index = n.getIndex(); - if (index instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) index; - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - } - - if (method != null) - { - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - } - } - - /** - * Visit all {@link ForEachStmt}s. - * - * @param n The current {@code ForEachStmt} - * @param arg Don't worry about it - */ - @Override - public void visit(ForEachStmt n, Object arg) - { - super.visit(n, arg); - Expression iterable = n.getIterable(); - if (iterable instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) iterable; - CallableDeclaration method = findMethodForStatement(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForStatement(n, this.compilationUnit); - } - - if (method != null) - { - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - } - } - - /** - * Visit all {@link ReturnStmt}s. - * - * @param n The current {@code ReturnStmt} - * @param arg Don't worry about it - */ - @Override - public void visit(ReturnStmt n, Object arg) - { - super.visit(n, arg); - Expression expression = n.getExpression().orElse(null); - if (expression instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) expression; - CallableDeclaration method = findMethodForStatement(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForStatement(n, this.compilationUnit); - } - - if (method != null) - { - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - } - } - - /** - * Visit all {@link UnaryExpr}s. - * - * @param n The current {@code UnaryExpr} - * @param arg Don't worry about it - */ - @Override - public void visit(UnaryExpr n, Object arg) - { - super.visit(n, arg); - Expression expression = n.getExpression(); - if (expression instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) expression; - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - } - - if (method != null) - { - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - catch (UnsolvedSymbolException ignored) - { - } - } - } - } - - /** - * Visit all {@link ConditionalExpr}s. - * - * @param n The current {@code ConditionalExpr} - * @param arg Don't worry about it - */ - @Override - public void visit(ConditionalExpr n, Object arg) - { - super.visit(n, arg); - Expression elseExpr = n.getElseExpr(); - if (elseExpr instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) elseExpr; - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - } - - if (method != null) - { - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - } - } - - Expression thenExpr = n.getThenExpr(); - if (thenExpr instanceof NameExpr) - { - NameExpr nameExpr = (NameExpr) thenExpr; - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - } - - if (method != null) - { - 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)); - } - else if (vd.isVariable()) - { - this.classFileContainer.putLocalVariable(name, new ClassLocalVariableLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd + 1)); - } - else if (vd.isParameter()) - { - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(method), "reference", line, columnStart, columnEnd)); - } - } - } - } - - /** - * Visit all {@link LambdaExpr}'s. - * - * @param n The current {@code LambdaExpr} - * @param arg Don't worry about it. - */ - @Override - public void visit(LambdaExpr n, Object arg) - { - super.visit(n, arg); - CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); - if (method == null) - { - method = findConstructorForExpression(n, this.compilationUnit); - } - - if (method != null) - { - CallableDeclaration finalMethod = method; - n.getParameters().forEach(parameter -> - { - SimpleName simpleName = parameter.getName(); - String name = simpleName.getIdentifier(); - Range range = parameter.getRange().get(); - int line = range.begin.line; - int columnStart = range.begin.column; - int columnEnd = range.end.column; - this.classFileContainer.putParameter(name, new ClassParameterLocation(getOwner(), getMethod(finalMethod), "declaration", line, columnStart, columnEnd + 1)); - }); - } - } - - /** - * Visit all {@link EnumDeclaration}'s. - * - * @param n The current {@code EnumDeclaration} - * @param arg Don't worry about it. - */ - @Override - public void visit(EnumDeclaration n, Object arg) - { - super.visit(n, arg); - n.getEntries().forEach(entry -> - { - SimpleName simpleName = entry.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; - this.classFileContainer.putField(name, new ClassFieldLocation(getOwner(), "declaration", line, columnStart, columnEnd + 1)); - }); - } - - /** - * 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}. - */ - private MethodDeclaration findMethodForStatement(Statement statement, CompilationUnit cu) - { - final boolean[] contains = {false}; - final MethodDeclaration[] methodDeclaration = {null}; - cu.accept(new VoidVisitorAdapter() - { - @Override - public void visit(MethodDeclaration n, Void arg) - { - super.visit(n, arg); - if (!n.isAbstract()) - { - for (Statement statement1 : n.getBody().get().getStatements()) - { - if (statement1.containsWithinRange(statement)) - { - contains[0] = true; - methodDeclaration[0] = n; - } - } - } - } - }, 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}. - */ - private MethodDeclaration findMethodForExpression(Expression expression, CompilationUnit cu) - { - final boolean[] contains = {false}; - final MethodDeclaration[] methodDeclaration = {null}; - cu.accept(new VoidVisitorAdapter() - { - @Override - public void visit(MethodDeclaration n, Void arg) - { - super.visit(n, arg); - if (!n.isAbstract()) - { - for (Statement statement : n.getBody().get().getStatements()) - { - if (statement.containsWithinRange(expression)) - { - contains[0] = true; - methodDeclaration[0] = n; - } - } - } - } - }, 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}. - */ - private ConstructorDeclaration findConstructorForStatement(Statement statement, CompilationUnit cu) - { - final boolean[] contains = {false}; - final ConstructorDeclaration[] constructorDeclaration = {null}; - cu.accept(new VoidVisitorAdapter() - { - @Override - public void visit(ConstructorDeclaration n, Void arg) - { - super.visit(n, arg); - for (Statement statement1 : n.getBody().getStatements()) - { - if (statement1.containsWithinRange(statement)) - { - 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 expression The {@code expression} we are looking for - * @param cu The {@code CompilationUnit} - * @return the constructor that contains the {@code expression}. - */ - private ConstructorDeclaration findConstructorForExpression(Expression expression, CompilationUnit cu) - { - final boolean[] contains = {false}; - final ConstructorDeclaration[] constructorDeclaration = {null}; - cu.accept(new VoidVisitorAdapter() - { - @Override - public void visit(ConstructorDeclaration n, Void arg) - { - super.visit(n, arg); - 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}. - */ - private InitializerDeclaration findInitializerForStatement(Statement statement, CompilationUnit cu) - { - final boolean[] contains = {false}; - final InitializerDeclaration[] initializerDeclaration = {null}; - cu.accept(new VoidVisitorAdapter() - { - @Override - public void visit(InitializerDeclaration n, Void arg) - { - super.visit(n, arg); - 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}. - */ - private InitializerDeclaration findInitializerForExpression(Expression expression, CompilationUnit cu) - { - final boolean[] contains = {false}; - final InitializerDeclaration[] initializerDeclaration = {null}; - cu.accept(new VoidVisitorAdapter() - { - @Override - public void visit(InitializerDeclaration n, Void arg) - { - super.visit(n, arg); - 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; - } -} diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/ArrayParser.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/ArrayParser.java new file mode 100644 index 000000000..82164963a --- /dev/null +++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/ArrayParser.java @@ -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); + } + }); + } +} diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/AssignParser.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/AssignParser.java new file mode 100644 index 000000000..19f791d91 --- /dev/null +++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/AssignParser.java @@ -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); + } + } + } +} diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/ConditionalParser.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/ConditionalParser.java new file mode 100644 index 000000000..a77956c6b --- /dev/null +++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/ConditionalParser.java @@ -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); + } + } +} diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/FieldAccessParser.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/FieldAccessParser.java new file mode 100644 index 000000000..0faa2d4f2 --- /dev/null +++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/FieldAccessParser.java @@ -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); + } + } + } +} diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/MethodCallParser.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/MethodCallParser.java new file mode 100644 index 000000000..79926dee3 --- /dev/null +++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/MethodCallParser.java @@ -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); + } + } + }); + } +} diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/MyVoidVisitor.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/MyVoidVisitor.java new file mode 100644 index 000000000..1bb6f44ab --- /dev/null +++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/MyVoidVisitor.java @@ -0,0 +1,1175 @@ +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.NodeList; +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.type.IntersectionType; +import com.github.javaparser.ast.type.TypeParameter; +import com.github.javaparser.ast.visitor.VoidVisitorAdapter; +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.types.ResolvedReferenceType; +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.ClassMethodLocation; +import the.bytecode.club.bytecodeviewer.resources.classcontainer.locations.ClassReferenceLocation; + +import java.util.Objects; + +import static the.bytecode.club.bytecodeviewer.resources.classcontainer.parser.visitors.ParserUtil.*; + +/** + * Our custom visitor that allows us to get the information from JavaParser we need. + *

+ * Created by Bl3nd. + * Date: 9/5/2024 + */ +public class MyVoidVisitor extends VoidVisitorAdapter +{ + + /* + Any issues related to JavaParser that we cannot fix: + + TODO: Ambiguous method call: JavaParser Issue #3037 / resulting from MethodCallExpr -> FieldAccessExpr + */ + + private static final boolean DEBUG = false; + + private final ClassFileContainer classFileContainer; + private final CompilationUnit compilationUnit; + + + public MyVoidVisitor(ClassFileContainer container, CompilationUnit compilationUnit) + { + this.classFileContainer = container; + this.compilationUnit = compilationUnit; + } + + @Override + public void visit(AnnotationDeclaration n, Object arg) + { + super.visit(n, arg); + if (DEBUG) System.err.println("AnnotationDeclaration"); + } + + @Override + public void visit(AnnotationMemberDeclaration n, Object arg) + { + super.visit(n, arg); + if (DEBUG) System.err.println("AnnotationMemberDeclaration"); + } + + + /** + * Visit all {@link ArrayAccessExpr}s. + *

+ * Ex. {@code getNames()[15 * 15]} + *

+ * + * @param n The current {@code ArrayAccessExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(ArrayAccessExpr n, Object arg) + { + super.visit(n, arg); + try + { + ArrayParser.parseAccess(compilationUnit, n, classFileContainer); + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link ArrayCreationExpr}s. + *

+ * Ex. {@code new int[5] and new int[1][2]} + *

+ * + * @param n The current {@code ArrayCreationExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(ArrayCreationExpr n, Object arg) + { + super.visit(n, arg); + try + { + ArrayParser.parseCreation(compilationUnit, n, classFileContainer); + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link ArrayInitializerExpr}s. + *

+ * Ex. {@code new int[][] {{1, 1}, {2, 2}}} + *

+ * + * @param n The current {@code ArrayInitializerExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(ArrayInitializerExpr n, Object arg) + { + super.visit(n, arg); + try + { + ArrayParser.parseInitializer(compilationUnit, n, classFileContainer); + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link AssignExpr}s. + *

+ * Ex. {@code a = 5} + *

+ * + * @param n The current {@code AssignExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(AssignExpr n, Object arg) + { + super.visit(n, arg); + try + { + CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); + InitializerDeclaration staticInitializer = null; + if (method == null) + { + method = findConstructorForExpression(n, this.compilationUnit); + if (method == null) + { + staticInitializer = findInitializerForExpression(n, this.compilationUnit); + } + } + + if (method != null) + AssignParser.parse(classFileContainer, n, method); + + if (staticInitializer != null) + AssignParser.parseStatic(classFileContainer, n); + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link BinaryExpr}s. + *

+ * Ex. {@code a && b} + *

+ * + * @param n The current {@code BinaryExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(BinaryExpr n, Object arg) + { + super.visit(n, arg); + try + { + CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); + if (method == null) + { + method = findConstructorForExpression(n, this.compilationUnit); + } + + if (method != null) + { + Expression leftExpr = n.getLeft(); + if (leftExpr instanceof NameExpr) + { + NameExpr nameExpr = (NameExpr) leftExpr; + Range range = nameExpr.getName().getRange().orElse(null); + if (range == null) + return; + + Value left = new Value(nameExpr.getName(), range); + putResolvedValues(classFileContainer, "reference", method, nameExpr, left); + } + + Expression rightExpr = n.getRight(); + if (rightExpr instanceof NameExpr) + { + NameExpr nameExpr = (NameExpr) rightExpr; + Range range = nameExpr.getName().getRange().orElse(null); + if (range == null) + return; + + Value right = new Value(nameExpr.getName(), range); + putResolvedValues(classFileContainer, "reference", method, nameExpr, right); + } + } + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link CastExpr}s. + *

+ * Ex. {@code (long) 15} + *

+ * + * @param n The current {@code CastExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(CastExpr n, Object arg) + { + super.visit(n, arg); + try + { + CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); + if (method == null) + { + method = findConstructorForExpression(n, this.compilationUnit); + } + + if (method != null) + { + Expression expression = n.getExpression(); + if (expression instanceof NameExpr) + { + NameExpr nameExpr = (NameExpr) expression; + Range range = nameExpr.getName().getRange().orElse(null); + if (range == null) + return; + + Value value = new Value(nameExpr.getName(), range); + putResolvedValues(classFileContainer, "reference", method, nameExpr, value); + } + } + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link ClassOrInterfaceDeclaration}s. + *

+ * Ex. {@code class X{...}} + *

+ * + * @param n The current {@code ClassOrInterfaceDeclaration} + * @param arg Don't worry about it + */ + @Override + public void visit(ClassOrInterfaceDeclaration n, Object arg) + { + super.visit(n, arg); + try + { + SimpleName name = n.getName(); + Range range = name.getRange().orElse(null); + if (range == null) + return; + + Value value = new Value(n.getName(), range); + + ResolvedReferenceTypeDeclaration resolve = n.resolve(); + this.classFileContainer.putClassReference(resolve.getName(), + new ClassReferenceLocation(getOwner(classFileContainer), + resolve.getPackageName(), "", "declaration", value.line, value.columnStart, value.columnEnd + 1)); + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link ClassOrInterfaceType}s. + *

+ * Examples:
+ * {@code Object}
+ * {@code HashMap}
+ * {@code java.util.Punchcard} + *

+ * + * @param n The current {@code ClassOrInterfaceType} + * @param arg Don't worry about it + */ + @Override + public void visit(ClassOrInterfaceType n, Object arg) + { + super.visit(n, arg); + try + { + Range range = n.getName().getRange().orElse(null); + if (range == null) + return; + + Value classValue = new Value(n.getName(), range); + + ResolvedType resolve = n.resolve(); + + if (!resolve.isReferenceType()) + return; + + ResolvedReferenceType referenceType = resolve.asReferenceType(); + + // Anonymous class + if (!referenceType.hasName()) + return; + + String qualifiedName = referenceType.getQualifiedName(); + String packagePath = ""; + if (qualifiedName.contains(".")) + packagePath = qualifiedName.substring(0, qualifiedName.lastIndexOf('.')).replace('.', '/'); + + this.classFileContainer.putClassReference(classValue.name, + new ClassReferenceLocation(getOwner(classFileContainer), + packagePath, "", "reference", classValue.line, classValue.columnStart, classValue.columnEnd + 1)); + } + catch (ClassCastException | UnsupportedOperationException | IllegalArgumentException e) + { + printException(n, e); + } + } + + /** + * Visit all {@link ConditionalExpr}s. + *

+ * Ex. {@code if (a)} + *

+ * + * @param n The current {@code ConditionalExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(ConditionalExpr n, Object arg) + { + super.visit(n, arg); + try + { + ConditionalParser.parse(compilationUnit, n, classFileContainer); + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link ConstructorDeclaration}s. + *

+ * Ex. {@code X { X(){} } } + *

+ * + * @param n The current {@code ConstructorDeclaration} + * @param arg Don't worry about it + */ + @Override + public void visit(ConstructorDeclaration n, Object arg) + { + super.visit(n, arg); + try + { + Node node = n.getParentNode().orElse(null); + if (node == null) + { + System.err.println("ConstructorDeclaration: parent node is null"); + return; + } + + if (node instanceof ObjectCreationExpr) + { + NodeList> bodyDeclarations = + ((ObjectCreationExpr) node).getAnonymousClassBody().orElse(null); + if (bodyDeclarations != null) + { + if (Objects.requireNonNull(bodyDeclarations.getFirst().orElse(null)).equals(n)) + return; + } + } + + ResolvedConstructorDeclaration resolve = n.resolve(); + String signature = resolve.getQualifiedSignature(); + String parameters = ""; + if (resolve.getNumberOfParams() != 0) + parameters = signature.substring(signature.indexOf('(') + 1, signature.lastIndexOf(')')); + + Range range = n.getName().getRange().orElse(null); + if (range == null) + return; + + Value constructor = new Value(n.getName(), range); + this.classFileContainer.putMethod(constructor.name, new ClassMethodLocation(resolve.getClassName(), + signature, parameters, "declaration", constructor.line, constructor.columnStart, + constructor.columnEnd + 1)); + } + catch (RuntimeException e) + { + printException(n, e); + } + } + + /** + * Visit all {@link DoStmt}s. + *

+ * Ex. {@code do {...} while (a == 0)} + *

+ * + * @param n The current {@code DoStmt} + * @param arg Don't worry about it. + */ + @Override + public void visit(DoStmt n, Object arg) + { + super.visit(n, arg); + if (DEBUG) System.err.println("DoStmt"); + } + + /** + * Visit all {@link EnumDeclaration}s. + *

+ * Ex. {@code enum X {...}} + *

+ * + * @param n The current {@code EnumDeclaration} + * @param arg Don't worry about it. + */ + @Override + public void visit(EnumDeclaration n, Object arg) + { + super.visit(n, arg); + n.getEntries().forEach(entry -> + { + SimpleName simpleName = entry.getName(); + String name = simpleName.getIdentifier(); + Range range = simpleName.getRange().orElse(null); + if (range == null) + return; + + int line = range.begin.line; + int columnStart = range.begin.column; + int columnEnd = range.end.column; + this.classFileContainer.putField(name, new ClassFieldLocation(getOwner(classFileContainer), "declaration", line, columnStart, columnEnd + 1)); + }); + } + + /** + * Find all {@link ExplicitConstructorInvocationStmt}s. + *

+ * Examples:
+ * {@code class X{ X(){super(15);} }}
+ * {@code class X{ X(){this(1, 2);} }} + *

+ * + * @param n The current {@code ExplicitConstructorInvocationStmt} + * @param arg Don't worry about it + */ + @Override + public void visit(ExplicitConstructorInvocationStmt n, Object arg) + { + super.visit(n, arg); + try + { + ConstructorDeclaration constructor = findConstructorForStatement(n, this.compilationUnit); + if (constructor != null) + { + n.getArguments().forEach(argument -> + { + if (argument instanceof NameExpr) + { + NameExpr nameExpr = (NameExpr) argument; + Range range = nameExpr.getName().getRange().orElse(null); + if (range == null) + return; + + Value argumentValue = new Value(nameExpr.getName(), range); + + putResolvedValues(classFileContainer, "reference", constructor, nameExpr, argumentValue); + } + }); + } + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link FieldAccessExpr}s. + *

+ * Ex. {@code person.name} + *

+ * + * @param n The current {@code FieldAccessExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(FieldAccessExpr n, Object arg) + { + super.visit(n, arg); + try + { + InitializerDeclaration initializer = findInitializerForExpression(n, this.compilationUnit); + + if (initializer == null) + FieldAccessParser.parse(classFileContainer, n); + else + FieldAccessParser.parseStatic(classFileContainer, n); + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link FieldDeclaration}s. + *

+ * Ex. {@code private static int a = 15} + *

+ * + * @param n The current {@code FieldDeclaration} + * @param arg Don't worry about it + */ + @Override + public void visit(FieldDeclaration n, Object arg) + { + super.visit(n, arg); + n.getVariables().forEach(variableDeclarator -> + { + Range range = variableDeclarator.getName().getRange().orElse(null); + if (range == null) + return; + + Value field = new Value(variableDeclarator.getName(), range); + + this.classFileContainer.putField(field.name, new ClassFieldLocation(getOwner(classFileContainer), + "declaration", field.line, field.columnStart, field.columnEnd + 1)); + }); + } + + /** + * Visit all {@link ForEachStmt}s. + *

+ * Ex. {@code for (Object o : objects) {...}} + *

+ * + * @param n The current {@code ForEachStmt} + * @param arg Don't worry about it + */ + @Override + public void visit(ForEachStmt n, Object arg) + { + super.visit(n, arg); + try + { + Expression iterable = n.getIterable(); + if (iterable instanceof NameExpr) + { + NameExpr nameExpr = (NameExpr) iterable; + CallableDeclaration method = findMethodForStatement(n, this.compilationUnit); + if (method == null) + { + method = findConstructorForStatement(n, this.compilationUnit); + } + + if (method != null) + { + Range range = nameExpr.getName().getRange().orElse(null); + if (range == null) + return; + + Value value = new Value(nameExpr.getName(), range); + putResolvedValues(classFileContainer, "reference", method, nameExpr, value); + } + } + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link IfStmt}s. + *

+ * Ex. {@code if (a == 5) hurray() else boo()} + *

+ * + * @param n The current {@code IfStmt} + * @param arg Don't worry about it + */ + @Override + public void visit(IfStmt n, Object arg) + { + super.visit(n, arg); + try + { + Expression condition = n.getCondition(); + if (condition instanceof NameExpr) + { + NameExpr nameExpr = (NameExpr) condition; + CallableDeclaration method = findMethodForStatement(n, this.compilationUnit); + InitializerDeclaration staticInitializer = null; + if (method == null) + { + method = findConstructorForStatement(n, this.compilationUnit); + if (method == null) + { + staticInitializer = findInitializerForStatement(n, this.compilationUnit); + } + } + + if (method != null) + { + Range range = nameExpr.getName().getRange().orElse(null); + if (range == null) + return; + + Value value = new Value(nameExpr.getName(), range); + putResolvedValues(classFileContainer, "reference", method, nameExpr, value); + } + else if (staticInitializer != null) + { + Range range = nameExpr.getName().getRange().orElse(null); + if (range == null) + return; + + Value value = new Value(nameExpr.getName(), range); + putResolvedValues(classFileContainer, "reference", nameExpr, value); + } + } + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link InstanceOfExpr}s. + *

+ * Ex. {@code tool instanceof Drill} + *

+ * + * @param n The current {@code InstanceOfExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(InstanceOfExpr n, Object arg) + { + super.visit(n, arg); + try + { + CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); + if (method == null) + { + method = findConstructorForExpression(n, this.compilationUnit); + } + + if (method != null) + { + Expression expression = n.getExpression(); + if (expression instanceof NameExpr) + { + NameExpr nameExpr = (NameExpr) expression; + Range range = nameExpr.getName().getRange().orElse(null); + if (range == null) + return; + + Value value = new Value(nameExpr.getName(), range); + putResolvedValues(classFileContainer, "reference", method, nameExpr, value); + } + } + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link IntersectionType}s. + *

+ * Ex. {@code Serializable & Cloneable} + *

+ * + * @param n The current {@code IntersectionType} + * @param arg Don't worry about it + */ + @Override + public void visit(IntersectionType n, Object arg) + { + super.visit(n, arg); + if (DEBUG) System.err.println("IntersectionType"); + } + + /** + * Visit all {@link LabeledStmt}s. + *

+ * Ex. {@code label123: println("continuing")} + *

+ * + * @param n The current {@code LabeledStmt} + * @param arg Don't worry about it + */ + @Override + public void visit(LabeledStmt n, Object arg) + { + super.visit(n, arg); + if (DEBUG) System.err.println("LabeledStmt"); + } + + /** + * Visit all {@link LambdaExpr}s. + *

+ * Ex. {@code (a, b) -> a + b} + *

+ * + * @param n The current {@code LambdaExpr} + * @param arg Don't worry about it. + */ + @Override + public void visit(LambdaExpr n, Object arg) + { + super.visit(n, arg); // We already do parameters + } + + /** + * Visit all {@link LocalClassDeclarationStmt}s. + *

+ * Ex. {@code class X { void m() { class Y() {} }}} + *

+ * + * @param n The current {@code LocalClassDeclarationStmt} + * @param arg Don't worry about it + */ + @Override + public void visit(LocalClassDeclarationStmt n, Object arg) + { + super.visit(n, arg); // We already do class declarations + } + + /** + * Visit all {@link MarkerAnnotationExpr}s. + *

+ * Ex. {@code @Override} + *

+ * + * @param n The current {@code MarkerAnnotationExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(MarkerAnnotationExpr n, Object arg) + { + super.visit(n, arg); + if (DEBUG) System.err.println("MarkerAnnotationExpr"); + } + + /** + * Visit all {@link MethodCallExpr}s. + *

+ * Ex. {@code circle.circumference()} + *

+ * + * @param n The current {@code MethodCallExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(MethodCallExpr n, Object arg) + { + super.visit(n, arg); + try + { + CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); + InitializerDeclaration staticInitializer = null; + if (method == null) + { + method = findConstructorForExpression(n, this.compilationUnit); + if (method == null) + { + staticInitializer = findInitializerForExpression(n, this.compilationUnit); + } + } + + ResolvedMethodDeclaration resolve = n.resolve(); + String signature = resolve.getQualifiedSignature(); + String parameters = ""; + if (resolve.getNumberOfParams() != 0) + { + parameters = signature.substring(signature.indexOf('(') + 1, signature.lastIndexOf(')')); + } + + Range methodRange = n.getName().getRange().orElse(null); + if (methodRange == null) + return; + + Value methodCall = new Value(n.getName(), methodRange); + this.classFileContainer.putMethod(methodCall.name, + new ClassMethodLocation(resolve.getClassName(), signature, parameters, "reference", methodCall.line, + methodCall.columnStart, methodCall.columnEnd + 1)); + + if (method != null) + { + MethodCallParser.parse(classFileContainer, n, method); + } + else if (staticInitializer != null) + { + MethodCallParser.parseStatic(classFileContainer, n); + } + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link MethodDeclaration}s. + *

+ * Ex. {@code public int abc(){return 1;}} + *

+ * + * @param n The current {@code MethodDeclaration} + * @param arg Don't worry about it + */ + @Override + public void visit(MethodDeclaration n, Object arg) + { + super.visit(n, arg); + try + { + ResolvedMethodDeclaration resolve = n.resolve(); + String signature = resolve.getQualifiedSignature(); + String parameters = ""; + if (resolve.getNumberOfParams() != 0) + { + parameters = signature.substring(signature.indexOf('(') + 1, signature.lastIndexOf(')')); + } + + Range methodRange = n.getName().getRange().orElse(null); + if (methodRange == null) + return; + + Value method = new Value(n.getName(), methodRange); + this.classFileContainer.putMethod(method.name, new ClassMethodLocation(resolve.getClassName(), signature, + parameters, "declaration", method.line, method.columnStart, method.columnEnd + 1)); + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link MethodReferenceExpr}s. + *

+ * Ex. {@code System.out::println} + *

+ * + * @param n The current {@code MethodReferenceExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(MethodReferenceExpr n, Object arg) + { + super.visit(n, arg); + if (DEBUG) System.err.println("MethodReferenceExpr"); + } + + + @Override + public void visit(NormalAnnotationExpr n, Object arg) + { + super.visit(n, arg); + if (DEBUG) System.err.println("NormalAnnotationExpr"); + } + + /** + * Visit all {@link ObjectCreationExpr}s. + *

+ * Ex. {@code new HashMap.Entry(15)} + *

+ * + * @param n The current {@code ObjectCreationExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(ObjectCreationExpr n, Object arg) + { + super.visit(n, arg); + try + { + CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); + if (method == null) + { + method = findConstructorForExpression(n, this.compilationUnit); + } + + if (method != null) + { + CallableDeclaration finalMethod = method; + n.getArguments().forEach(argument -> + { + if (argument instanceof NameExpr) + { + NameExpr nameExpr = (NameExpr) argument; + Range range = nameExpr.getName().getRange().orElse(null); + if (range == null) + { + return; + } + + Value argumentValue = new Value(nameExpr.getName(), range); + putResolvedValues(classFileContainer, "reference", finalMethod, nameExpr, argumentValue); + } + }); + } + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link Parameter}s. + *

+ * Ex. {@code int abc(String x)} + *

+ * + * @param n The current {@code Parameter} + * @param arg Don't worry about it + */ + @Override + public void visit(Parameter n, Object arg) + { + super.visit(n, arg); + ParameterParser.parse(compilationUnit, n, classFileContainer); + } + + /** + * Visit all {@link ReturnStmt}s. + *

+ * Ex. {@code return 5 * 5} + *

+ * + * @param n The current {@code ReturnStmt} + * @param arg Don't worry about it + */ + @Override + public void visit(ReturnStmt n, Object arg) + { + super.visit(n, arg); + try + { + Expression expression = n.getExpression().orElse(null); + if (expression instanceof NameExpr) + { + NameExpr nameExpr = (NameExpr) expression; + CallableDeclaration method = findMethodForStatement(n, this.compilationUnit); + if (method == null) + { + method = findConstructorForStatement(n, this.compilationUnit); + } + + if (method != null) + { + Range range = nameExpr.getName().getRange().orElse(null); + if (range == null) + return; + + Value value = new Value(nameExpr.getName(), range); + putResolvedValues(classFileContainer, "reference", method, nameExpr, value); + } + } + } + catch (Exception e) + { + printException(n, e); + } + } + + @Override + public void visit(SingleMemberAnnotationExpr n, Object arg) + { + super.visit(n, arg); + if (DEBUG) System.err.println("SingleMemberAnnotationExpr"); + } + + /** + * Visit all {@link ThrowStmt}s. + *

+ * Ex. {@code throw new Exception()} + *

+ * + * @param n The current {@code ThrowStmt} + * @param arg Don't worry about it + */ + @Override + public void visit(ThrowStmt n, Object arg) + { + super.visit(n, arg); + try + { + Expression expression = n.getExpression(); + if (expression instanceof NameExpr) + { + NameExpr nameExpr = (NameExpr) expression; + CallableDeclaration method = findMethodForStatement(n, this.compilationUnit); + if (method == null) + { + method = findConstructorForStatement(n, this.compilationUnit); + } + + if (method != null) + { + Range range = nameExpr.getName().getRange().orElse(null); + if (range == null) + return; + + Value value = new Value(nameExpr.getName(), range); + putResolvedValues(classFileContainer, "reference", method, nameExpr, value); + } + } + } + catch (Exception e) + { + printException(n, e); + } + } + + @Override + public void visit(TypeExpr n, Object arg) + { + super.visit(n, arg); + if (DEBUG) System.err.println("TypeExpr"); + } + + @Override + public void visit(TypeParameter n, Object arg) + { + super.visit(n, arg); + + Range range = n.getName().getRange().orElse(null); + if (range == null) + return; + + Value typeParameter = new Value(n.getName(), range); + // TODO: Figure out the best way to implement this. + if (DEBUG) System.err.println("TypeParameter"); + } + + /** + * Visit all {@link UnaryExpr}s. + *

+ * Ex. {@code 11++} + *

+ * + * @param n The current {@code UnaryExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(UnaryExpr n, Object arg) + { + super.visit(n, arg); + try + { + Expression expression = n.getExpression(); + if (expression instanceof NameExpr) + { + NameExpr nameExpr = (NameExpr) expression; + CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); + if (method == null) + { + method = findConstructorForExpression(n, this.compilationUnit); + } + + if (method != null) + { + Range range = nameExpr.getName().getRange().orElse(null); + if (range == null) + return; + + Value value = new Value(nameExpr.getName(), range); + putResolvedValues(classFileContainer, "reference", method, nameExpr, value); + } + } + } + catch (Exception e) + { + printException(n, e); + } + } + + /** + * Visit all {@link VariableDeclarationExpr}s. + *

+ * Ex. {@code final int x = 3, y = 55} + *

+ * + * @param n The current {@code VariableDeclarationExpr} + * @param arg Don't worry about it + */ + @Override + public void visit(VariableDeclarationExpr n, Object arg) + { + super.visit(n, arg); + CallableDeclaration method = findMethodForExpression(n, this.compilationUnit); + InitializerDeclaration staticInitializer = null; + if (method == null) + { + method = findConstructorForExpression(n, this.compilationUnit); + if (method == null) + { + staticInitializer = findInitializerForExpression(n, this.compilationUnit); + } + } + + if (method != null) + { + CallableDeclaration finalMethod = method; + n.getVariables().forEach(variable -> { + Range range = variable.getName().getRange().orElse(null); + if (range == null) + return; + + Value value = new Value(variable.getName(), range); + putLocalVariable(classFileContainer, value, getMethod(finalMethod), "declaration"); + }); + } + else if (staticInitializer != null) + { + n.getVariables().forEach(variable -> { + Range range = variable.getName().getRange().orElse(null); + if (range == null) + return; + + Value value = new Value(variable.getName(), range); + putLocalVariable(classFileContainer, value, "static", "declaration"); + }); + } + } +} diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/ParameterParser.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/ParameterParser.java new file mode 100644 index 000000000..729b8dac9 --- /dev/null +++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/ParameterParser.java @@ -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"); + }); + } +} diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/ParserUtil.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/ParserUtil.java new file mode 100644 index 000000000..265410b84 --- /dev/null +++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/classcontainer/parser/visitors/ParserUtil.java @@ -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() + { + @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() + { + @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() + { + @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() + { + @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() + { + @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() + { + @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; + } +}