Loading src/main/java/tfm/exec/MethodResolver.java 0 → 100644 +105 −0 Original line number Diff line number Diff line package tfm.exec; import com.github.javaparser.JavaParser; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.AnnotationDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.expr.MethodCallExpr; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import com.github.javaparser.resolution.UnsolvedSymbolException; import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; import tfm.graphs.sdg.SDG; import tfm.nodes.GraphNode; import tfm.utils.Context; import tfm.utils.Logger; import java.io.File; import java.io.FileNotFoundException; import java.util.Arrays; import java.util.Optional; public class MethodResolver { private static class Args { String file; String method; } public static void main(String[] inputArgs) throws FileNotFoundException { Args args = parseArgs(inputArgs); CompilationUnit cu = JavaParser.parse(new File(args.file)); SDG sdg = new SDG(); sdg.build(new NodeList<>(cu)); VoidVisitorAdapter<Void> visitor = new VoidVisitorAdapter<Void>() { @Override public void visit(MethodCallExpr n, Void arg) { TypeSolver solver = new JavaParserTypeSolver(args.file.substring(0, args.file.lastIndexOf('/'))); Logger.log("-- Trying to solve method " + n.getNameAsString() + " --"); Optional<MethodDeclaration> optionalResolvedMethod; try { optionalResolvedMethod = getMethodCallWithJavaParserSymbolSolver(n, solver, new ReflectionTypeSolver()); } catch (UnsolvedSymbolException e) { optionalResolvedMethod = Optional.empty(); } if (!optionalResolvedMethod.isPresent()) { Logger.format("Not found: %s", n); return; } Logger.format("Found: %s", n.getNameAsString()); Logger.log(optionalResolvedMethod.get().getSignature().asString()); Logger.log("-- Trying to match with a node from SDG --"); Optional<GraphNode<MethodDeclaration>> methodDeclarationNode = optionalResolvedMethod.flatMap(sdg::findNodeByASTNode); if (!methodDeclarationNode.isPresent()) { Logger.log("Failed to find node in SDG"); return; } Logger.format("SDG node: %s", methodDeclarationNode.get()); } }; cu.accept(visitor, null); } private static Args parseArgs(String[] args) { Args res = new Args(); Logger.log(Arrays.asList(args)); try { res.file = args[0]; // res.method = args[2]; } catch (Exception e) { Logger.log("Incorrect syntax: java MethodResolver.class <file> <methodName>"); System.exit(1); } return res; } private static Optional<MethodDeclaration> getMethodCallWithJavaParserSymbolSolver(MethodCallExpr methodCallExpr, TypeSolver... solvers) { CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver(solvers); SymbolReference<ResolvedMethodDeclaration> solver = JavaParserFacade.get(combinedTypeSolver).solve(methodCallExpr); return solver.isSolved() ? solver.getCorrespondingDeclaration().toAst() : Optional.empty(); } } src/main/java/tfm/graphs/sdg/MethodCallReplacerVisitor.java +39 −11 Original line number Diff line number Diff line package tfm.graphs.sdg; import com.github.javaparser.ParserConfiguration; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; Loading @@ -13,12 +14,25 @@ import com.github.javaparser.ast.expr.VariableDeclarationExpr; import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.type.Type; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import com.github.javaparser.resolution.UnsolvedSymbolException; import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; import com.github.javaparser.symbolsolver.JavaSymbolSolver; import com.github.javaparser.symbolsolver.SourceFileInfoExtractor; import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; import com.github.javaparser.symbolsolver.resolution.SymbolSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; import tfm.nodes.GraphNode; import tfm.nodes.TypeNodeFactory; import tfm.nodes.type.NodeType; import tfm.utils.Context; import tfm.utils.Logger; import java.nio.file.Path; import java.util.List; import java.util.Objects; import java.util.Optional; Loading Loading @@ -99,22 +113,16 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> { Logger.log("MethodCallReplacerVisitor", context); Optional<MethodDeclaration> optionalCallingMethod = methodCallExpr.getScope().isPresent() ? shouldMakeCallWithScope(methodCallExpr, context) : shouldMakeCallWithNoScope(methodCallExpr, context); Optional<GraphNode<MethodDeclaration>> optionalNethodDeclarationNode = getMethodDeclarationNodeWithJavaParser(methodCallExpr); if (!optionalCallingMethod.isPresent()) { Logger.log("Discarding: " + methodCallExpr); if (!optionalNethodDeclarationNode.isPresent()) { Logger.format("Not found: '%s'. Discarding"); return; } MethodDeclaration methodCalled = optionalCallingMethod.get(); GraphNode<MethodDeclaration> calledMethodNode = optionalNethodDeclarationNode.get(); Optional<GraphNode<MethodDeclaration>> optionalCalledMethodNode = sdg.findNodeByASTNode(methodCalled); assert optionalCalledMethodNode.isPresent(); GraphNode<MethodDeclaration> calledMethodNode = optionalCalledMethodNode.get(); MethodDeclaration methodCalled = calledMethodNode.getAstNode(); sdg.addCallArc(methodCallNode, calledMethodNode); Loading Loading @@ -157,6 +165,26 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> { Logger.log("MethodCallReplacerVisitor", String.format("%s | Method '%s' called", methodCallExpr, methodCalled.getNameAsString())); } private Optional<GraphNode<MethodDeclaration>> getMethodDeclarationNodeWithJavaParser(MethodCallExpr methodCallExpr) { TypeSolver typeSolver = new ReflectionTypeSolver(); try { SymbolReference<ResolvedMethodDeclaration> solver = JavaParserFacade.get(typeSolver).solve(methodCallExpr); return solver.isSolved() ? solver.getCorrespondingDeclaration().toAst() .flatMap(methodDeclaration -> sdg.findNodeByASTNode(methodDeclaration)) : Optional.empty(); } catch (UnsolvedSymbolException e) { return Optional.empty(); } } /** * Handles method calls with scope. Examples: * - System.out.println() -> println() is a method call with scope System.out * - new A().getB() -> getB() is a method call with scope new A() */ private Optional<MethodDeclaration> shouldMakeCallWithScope(MethodCallExpr methodCallExpr, Context context) { assert methodCallExpr.getScope().isPresent(); Loading src/main/java/tfm/nodes/GraphNode.java +1 −1 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ public class GraphNode<N extends Node> implements Comparable<GraphNode<?>> { public static final NodeFactory DEFAULT_FACTORY = TypeNodeFactory.fromType(NodeType.STATEMENT); private NodeType nodeType; private final NodeType nodeType; private final long id; private final String instruction; Loading Loading
src/main/java/tfm/exec/MethodResolver.java 0 → 100644 +105 −0 Original line number Diff line number Diff line package tfm.exec; import com.github.javaparser.JavaParser; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.AnnotationDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.expr.MethodCallExpr; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import com.github.javaparser.resolution.UnsolvedSymbolException; import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; import tfm.graphs.sdg.SDG; import tfm.nodes.GraphNode; import tfm.utils.Context; import tfm.utils.Logger; import java.io.File; import java.io.FileNotFoundException; import java.util.Arrays; import java.util.Optional; public class MethodResolver { private static class Args { String file; String method; } public static void main(String[] inputArgs) throws FileNotFoundException { Args args = parseArgs(inputArgs); CompilationUnit cu = JavaParser.parse(new File(args.file)); SDG sdg = new SDG(); sdg.build(new NodeList<>(cu)); VoidVisitorAdapter<Void> visitor = new VoidVisitorAdapter<Void>() { @Override public void visit(MethodCallExpr n, Void arg) { TypeSolver solver = new JavaParserTypeSolver(args.file.substring(0, args.file.lastIndexOf('/'))); Logger.log("-- Trying to solve method " + n.getNameAsString() + " --"); Optional<MethodDeclaration> optionalResolvedMethod; try { optionalResolvedMethod = getMethodCallWithJavaParserSymbolSolver(n, solver, new ReflectionTypeSolver()); } catch (UnsolvedSymbolException e) { optionalResolvedMethod = Optional.empty(); } if (!optionalResolvedMethod.isPresent()) { Logger.format("Not found: %s", n); return; } Logger.format("Found: %s", n.getNameAsString()); Logger.log(optionalResolvedMethod.get().getSignature().asString()); Logger.log("-- Trying to match with a node from SDG --"); Optional<GraphNode<MethodDeclaration>> methodDeclarationNode = optionalResolvedMethod.flatMap(sdg::findNodeByASTNode); if (!methodDeclarationNode.isPresent()) { Logger.log("Failed to find node in SDG"); return; } Logger.format("SDG node: %s", methodDeclarationNode.get()); } }; cu.accept(visitor, null); } private static Args parseArgs(String[] args) { Args res = new Args(); Logger.log(Arrays.asList(args)); try { res.file = args[0]; // res.method = args[2]; } catch (Exception e) { Logger.log("Incorrect syntax: java MethodResolver.class <file> <methodName>"); System.exit(1); } return res; } private static Optional<MethodDeclaration> getMethodCallWithJavaParserSymbolSolver(MethodCallExpr methodCallExpr, TypeSolver... solvers) { CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver(solvers); SymbolReference<ResolvedMethodDeclaration> solver = JavaParserFacade.get(combinedTypeSolver).solve(methodCallExpr); return solver.isSolved() ? solver.getCorrespondingDeclaration().toAst() : Optional.empty(); } }
src/main/java/tfm/graphs/sdg/MethodCallReplacerVisitor.java +39 −11 Original line number Diff line number Diff line package tfm.graphs.sdg; import com.github.javaparser.ParserConfiguration; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; Loading @@ -13,12 +14,25 @@ import com.github.javaparser.ast.expr.VariableDeclarationExpr; import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.type.Type; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import com.github.javaparser.resolution.UnsolvedSymbolException; import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; import com.github.javaparser.symbolsolver.JavaSymbolSolver; import com.github.javaparser.symbolsolver.SourceFileInfoExtractor; import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; import com.github.javaparser.symbolsolver.resolution.SymbolSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; import tfm.nodes.GraphNode; import tfm.nodes.TypeNodeFactory; import tfm.nodes.type.NodeType; import tfm.utils.Context; import tfm.utils.Logger; import java.nio.file.Path; import java.util.List; import java.util.Objects; import java.util.Optional; Loading Loading @@ -99,22 +113,16 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> { Logger.log("MethodCallReplacerVisitor", context); Optional<MethodDeclaration> optionalCallingMethod = methodCallExpr.getScope().isPresent() ? shouldMakeCallWithScope(methodCallExpr, context) : shouldMakeCallWithNoScope(methodCallExpr, context); Optional<GraphNode<MethodDeclaration>> optionalNethodDeclarationNode = getMethodDeclarationNodeWithJavaParser(methodCallExpr); if (!optionalCallingMethod.isPresent()) { Logger.log("Discarding: " + methodCallExpr); if (!optionalNethodDeclarationNode.isPresent()) { Logger.format("Not found: '%s'. Discarding"); return; } MethodDeclaration methodCalled = optionalCallingMethod.get(); GraphNode<MethodDeclaration> calledMethodNode = optionalNethodDeclarationNode.get(); Optional<GraphNode<MethodDeclaration>> optionalCalledMethodNode = sdg.findNodeByASTNode(methodCalled); assert optionalCalledMethodNode.isPresent(); GraphNode<MethodDeclaration> calledMethodNode = optionalCalledMethodNode.get(); MethodDeclaration methodCalled = calledMethodNode.getAstNode(); sdg.addCallArc(methodCallNode, calledMethodNode); Loading Loading @@ -157,6 +165,26 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter<Context> { Logger.log("MethodCallReplacerVisitor", String.format("%s | Method '%s' called", methodCallExpr, methodCalled.getNameAsString())); } private Optional<GraphNode<MethodDeclaration>> getMethodDeclarationNodeWithJavaParser(MethodCallExpr methodCallExpr) { TypeSolver typeSolver = new ReflectionTypeSolver(); try { SymbolReference<ResolvedMethodDeclaration> solver = JavaParserFacade.get(typeSolver).solve(methodCallExpr); return solver.isSolved() ? solver.getCorrespondingDeclaration().toAst() .flatMap(methodDeclaration -> sdg.findNodeByASTNode(methodDeclaration)) : Optional.empty(); } catch (UnsolvedSymbolException e) { return Optional.empty(); } } /** * Handles method calls with scope. Examples: * - System.out.println() -> println() is a method call with scope System.out * - new A().getB() -> getB() is a method call with scope new A() */ private Optional<MethodDeclaration> shouldMakeCallWithScope(MethodCallExpr methodCallExpr, Context context) { assert methodCallExpr.getScope().isPresent(); Loading
src/main/java/tfm/nodes/GraphNode.java +1 −1 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ public class GraphNode<N extends Node> implements Comparable<GraphNode<?>> { public static final NodeFactory DEFAULT_FACTORY = TypeNodeFactory.fromType(NodeType.STATEMENT); private NodeType nodeType; private final NodeType nodeType; private final long id; private final String instruction; Loading