3

Hello to the most helpful community on the internet!

I'm working on a project that can read a .java file and spit out data. One of my programs to extract data is not working exactly how I intend it work (very cliche). It parses through all the .java files in a file tree and lists data such as caller pkg.class.method and called pkg.class.method in a .txt file using a linkedhashmap. It does everything right except its only giving me the last method called from a method and not all the methods called from each method. I think its because of the way I'm storing the data in the linkedhashmap, i.e. one key (caller method) and multiple values (called method).

I want the text file to list every method called from each method starting from the first encountered. Is there a way around this?

Here's the code:

import japa.parser.JavaParser;
import japa.parser.ast.CompilationUnit;
import japa.parser.ast.body.MethodDeclaration;
import japa.parser.ast.expr.MethodCallExpr;
import japa.parser.ast.visitor.VoidVisitorAdapter;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.LinkedHashMap;

/*--------------------------------------------------------------------------------------------------        
 *      TASK 3: Information Extraction, Method Caller and Method Callee
 *              This java code will extract data in 2 columns
 *              (Format:pkg.class.method). First column denotes the method
 *              from which another method is being called and the second
 *              column denotes the name of the called method.
 *--------------------------------------------------------------------------------------------------
 */

public class Task3 
{

    private static HashMap<String,String> methods = new LinkedHashMap<String,String>();

    static class ClassVisitor extends VoidVisitorAdapter<Object> 
    {
        private static String className = "";

        public void visit(japa.parser.ast.body.ClassOrInterfaceDeclaration n, Object arg) 
        {
            className = arg + "," + n.getName();
            new MethodVisitor().visit(n, className);
        }

    }

    static class MethodVisitor extends VoidVisitorAdapter<Object> {
        private static String methodName = "";

        @Override
        public void visit(MethodDeclaration n, Object arg) 
        {
            methodName = arg + "," + n.getName();
            new MethodCallVisitor().visit(n,methodName);
        }


    }

    static class MethodCallVisitor extends VoidVisitorAdapter<Object>{

        @Override
        public void visit(MethodCallExpr n, Object arg) 
        {
              String className=arg.toString();    
              methods.put(arg.toString(),className.substring(0,className.lastIndexOf(','))+","+n.getName());
        }


    }

    public static void main(String[] args) 
    {
        try 
        {
            ListFiles files = new ListFiles();
            String projPath = "C:\\JavaBook\\Final\\JMencode_v0.64_src\\";
            Path file = Paths.get(projPath);
            Files.walkFileTree(file, files);
            CompilationUnit compilationUnit = null;
            FileInputStream fileInputStream = null;
            String pkg = "";

            ClassVisitor codeVisitor = null;

            for (Path path : files.javaFiles) 
            {
                fileInputStream = new FileInputStream(path.toFile());

                try 
                {
                    compilationUnit = JavaParser.parse(fileInputStream);
                } 

                finally 
                {
                    fileInputStream.close();
                }

                pkg = compilationUnit.getPackage().getName().toString();
                codeVisitor = new ClassVisitor();
                codeVisitor.visit(compilationUnit, pkg);

            }

            File ouputFile = new File("C:\\JavaBook\\Final\\src\\pkg\\Task_1_2_3\\JMencode_v0.64_src_task3_" + methods.size() + ".txt");
            FileWriter fW = new FileWriter(ouputFile);

            fW.write("Caller Method" + " \t\t\t " + "Callee Method\n");

            for (String callerMeth : methods.keySet()) 
            {
                fW.write(callerMeth + " \t\t\t "+ methods.get(callerMeth)+"\n");
                System.out.println(callerMeth + " \t\t\t " + methods.get(callerMeth)+"\n");
            }

            fW.close();

        } 

        catch (Exception ex) 
        {
            System.out.println("Exception in ProjectInfo " + ex.getMessage());
        }

    }

}

Thank you all in advance!

kalame04
  • 75
  • 7
  • You could consider using the new Javaparser version as maintained on GitHub (https://github.com/javaparser). The one you are using has been not longer maintained for years and it supports Java 1.5, while the current one supports Java 1.8 – Federico Tomassetti Dec 28 '15 at 08:33
  • @kalame04 - Am getting error in " ListFiles files = new ListFiles();" - Could you please share full code. – user3410249 Sep 07 '20 at 12:43

1 Answers1

1

In this case, there are multiple values with same key, so you should declare methods map like this:

private static HashMap<String, Set<String>> methods = new LinkedHashMap<String, Set<String>>();

And store values in a set:

Set<String> set = methods.get(arg.toString());

if (set == null) {
  set = new HashSet<String>();
  methods.put(arg.toString(), set);
}

set.add(className.substring(0,className.lastIndexOf(','))+","+n.getName());
andrucz
  • 1,971
  • 2
  • 18
  • 30