manucapo / Gardener

A project to automatically generate plantUML sequence diagrams from java methods.
MIT License
3 stars 2 forks source link

How to resolve classes of nested method calls from strings #10

Closed manucapo closed 2 years ago

manucapo commented 2 years ago

Currently we are extracting only strings from the source code and defining all types and classes from class context.

Here some examples of strings that can be currently parsed:

This works relatively well for single method calls:

    this.Test1(2);
    Test2("2");
    Math.abs(2);

Method calls such as this are easy to parse for method and calling class.

    String f = "TEST.F";
    f.split("\\.");

Method calls like this can be parsed with relative ease by comparing the literal f to a list of variables defined in the method that can be obtained by javaparser.

public int Test3(String s, int i, boolean bool) {
    s.split("\\.");
    return 26;
}

Method calls of this form can also be parsed relatively easily by comparing the literal s to a list of method parameters that can be obtained by the java reflection API.

    test4("a").split("\\.");

Method calls of this nested form require a bit more effort but can still be parsed using a two step process. The first method call is parsed just like a single call. The second method calling class can then be inferred from the return type of the first method.

    test4("a").split("\\.").clone();

Parsing method calls like this one is proving difficult since it becomes very hard to track the class context after one nested call.

manucapo commented 2 years ago

One option is to restrict parse to method calls that can be parsed. Parsing only a subset of methods like those that belong to a single class /group of classes would give us clean diagrams and allow us to always track class context. However our program looses a lot of flexibility.

Another option is to look at the javaparser symbol solver API. This can resolve the type of symbols extracted by javaparser but requires some set up and needs the user to provide a list of dependencies. I would also like to avoid adding extra dependencies and the documentation for the javaparser symbol solver is a little bit lacking for my taste.

A third option that seems the most interesting is the ability to find classes by name using the java reflection API. This should be possible in theory but it would require the user to provide a list of (names) packages that he is interested in parsing.

I will explore the third option and if it proves too hard will look at setting up the project to use the javaparser symbol solver

manucapo commented 2 years ago

I made a lot of progress by delaying the conversion from ast node to String as long as possible.

this allowed me to extract a lot more information about the type of nodes using their class context.

The code is working pretty well at the moment. It has some issues dealing with generic types. Sometimes the type of a generic can be resolved:

     private List<String> classFieldNames;

generic interfaces that have the type specified on declaration can be resolved but the resolution has to pretty much be hard coded.

More complicated generic expressions, for example dealing with the .get() method in the Optional class results in information about the type being lost.

I feel at this point that might be an inherent limitation of the current approach.

I feel like I have extracted as much information as can be easily done in a reasonable time. Other special cases would have to be considered and handled on a one by one basis.

Since we only have so much ability and time to test specific use cases of our program I am happy to declare this part of the process finished.