GumTreeDiff / gumtree

An awesome code differencing tool
https://github.com/GumTreeDiff/gumtree/wiki
GNU Lesser General Public License v3.0
923 stars 173 forks source link

Using GUmTree API throws IllegalArgumentException when reading file to get tree #244

Closed GTSZM closed 3 years ago

GTSZM commented 3 years ago

Hello, I'm trying to use the GumTree API to compare two files. For now I'm trying the API using the sample code:

Run.initGenerators(); // registers the available parsers
        String srcFile = "C:/testpropagation/clones/robotmedia/AndroidBillingLibrary/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/AbstractBillingActivityTest.java";
        String dstFile = "C:/testpropagation/clones/serso/android-billing/core_testing/src/test/java/net/robotmedia/billing/helper/AbstractBillingActivityTest.java";
        Tree src =  //new JdtTreeGenerator().generateFrom().file(srcFile).getRoot();
                TreeGenerators.getInstance().getTree(srcFile).getRoot(); // retrieves and applies the default parser for the file
        Tree dst = TreeGenerators.getInstance().getTree(dstFile).getRoot(); /

But the at the point of reading the file to get the tree of the file, the ASTParser throws the IllegalArgumentException. When I debug the code I find that this error comes because the argument "level" that is passed is "14" yet the AST parser expcts values from 1-4 only in the following file:

ASTParser(int level) {
        this.workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
        this.project = null;
        this.unitName = null;
        switch(level) {
        case 2:
        case 3:
        case 4:
            this.apiLevel = level;
            this.initializeDefaults();
            return;
        default:
            throw new IllegalArgumentException();
        }
    }

The value 14 is passed from the AbstractJdtTreeGenerator generate method.

public TreeContext generate(Reader r) throws IOException {
        ASTParser parser = ASTParser.newParser(14);
        parser.setKind(8);
        Map pOptions = JavaCore.getOptions();
        pOptions.put("org.eclipse.jdt.core.compiler.compliance", "11");
        pOptions.put("org.eclipse.jdt.core.compiler.codegen.targetPlatform", "11");
        pOptions.put("org.eclipse.jdt.core.compiler.source", "11");
        pOptions.put("org.eclipse.jdt.core.compiler.doc.comment.support", "enabled");
        parser.setCompilerOptions(pOptions);
        char[] source = readerToCharArray(r);

Is there something I'm missing here? How can I resolve this? By the way, what've shown here is the decompiled code from gumtree that shows up when I'm debugging to find the source of the IllegalArgumentException

jrfaller commented 3 years ago

Hi!

Could you attach the files ?

Cheers.

GTSZM commented 3 years ago

TestProp.zip

File Main contains the sample code I got from your API sample code. The two additional Java files are the ones I'm trying to compare.

I first tried using the gumtree jar directly downloaded from Releases, but I got the same problem. So I downloaded the sources and built them using gradle to generate the jar file, but I still get the same exception.

jrfaller commented 3 years ago

Hi,

Sorry I cannot reproduce the problem, it's working fine for me. Maybe it's a classpath problem? Can you paste the error message?

Another note, you can simplifiy a lot your code by using the Diff object like that:

            Run.initGenerators(); // registers the available parsers
            String srcFile = "/Users/falleri/Downloads/TestProp/AbstractBillingActivityTest1.java";
            String dstFile = "/Users/falleri/Downloads/TestProp/AbstractBillingActivityTest2.java";
            Diff d = Diff.compute(srcFile, dstFile);
            EditScript script = d.editScript;
GTSZM commented 3 years ago
java.lang.IllegalArgumentException
    at org.eclipse.jdt.core.dom.ASTParser.<init>(ASTParser.java:226)
    at org.eclipse.jdt.core.dom.ASTParser.newParser(ASTParser.java:125)
    at com.github.gumtreediff.gen.jdt.AbstractJdtTreeGenerator.generate(AbstractJdtTreeGenerator.java:56)
    at com.github.gumtreediff.gen.TreeGenerator.generateTree(TreeGenerator.java:41)
    at com.github.gumtreediff.gen.TreeGenerator$ReaderConfigurator.reader(TreeGenerator.java:119)
    at com.github.gumtreediff.gen.TreeGenerator$ReaderConfigurator.file(TreeGenerator.java:90)
    at com.github.gumtreediff.gen.TreeGenerator$ReaderConfigurator.file(TreeGenerator.java:100)
    at com.github.gumtreediff.gen.TreeGenerators.getTree(TreeGenerators.java:55)
    at Main.main(Main.java:19)

Process finished with exit code 0
GTSZM commented 3 years ago

Even with the suggested coincise code I still get the same error:

java.lang.IllegalArgumentException
    at org.eclipse.jdt.core.dom.ASTParser.<init>(ASTParser.java:226)
    at org.eclipse.jdt.core.dom.ASTParser.newParser(ASTParser.java:125)
    at com.github.gumtreediff.gen.jdt.AbstractJdtTreeGenerator.generate(AbstractJdtTreeGenerator.java:56)
    at com.github.gumtreediff.gen.TreeGenerator.generateTree(TreeGenerator.java:41)
    at com.github.gumtreediff.gen.TreeGenerator$ReaderConfigurator.reader(TreeGenerator.java:119)
    at com.github.gumtreediff.gen.TreeGenerator$ReaderConfigurator.file(TreeGenerator.java:90)
    at com.github.gumtreediff.gen.TreeGenerator$ReaderConfigurator.file(TreeGenerator.java:100)
    at com.github.gumtreediff.gen.TreeGenerators.getTree(TreeGenerators.java:55)
    at com.github.gumtreediff.gen.TreeGenerators.getTree(TreeGenerators.java:67)
    at com.github.gumtreediff.actions.Diff.compute(Diff.java:79)
    at com.github.gumtreediff.actions.Diff.compute(Diff.java:99)
    at com.github.gumtreediff.actions.Diff.compute(Diff.java:111)
    at Main.main(Main.java:26)
![error screenshot](https://user-images.githubusercontent.com/36341369/125177056-23d13c80-e1d9-11eb-8a8d-51cc95b69839.PNG)

Process finished with exit code 0
GTSZM commented 3 years ago

HI. SO for now, I just modified line 56 in Class AbstractJdtTreeGenerator. I changed it from ASTParser parser = ASTParser.newParser(AST.JLS14); to ASTParser parser = ASTParser.newParser(4);

Then I rebuilt the gumtree JAR and ran my program and it works now.

This is my temp measure to get this working. I hope you can discover why I have such an issue but you don't.

Best,

Muke

jrfaller commented 3 years ago

Hi!

Thanks for the info. However, it does not make much sense since the parameter taken by newParser is the Java language specification. When you give 4 it means the parser will support only Java 4 programs (if I am correct).

I suspect that it might be the case that the dependencies of JDT you are using might be outdated? Could you see if refreshing it works?

In addition in the latest commit I did update the JDT version to the latest one.

Cheers.

GTSZM commented 3 years ago

Hi Jeremy,

No the paramter to the parser is the level according to this code here:

ASTParser(int level) {
        this.workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
        this.project = null;
        this.unitName = null;
        switch(level) {
        case 2:
        case 3:
        case 4:
            this.apiLevel = level;
            this.initializeDefaults();
            return;
        default:
            throw new IllegalArgumentException();
        }
    }

The problem was that what was being passed was the value 14, yet the switch stament expects 2-4, otherwise it throws that exception IllegalArgument.

So by giving it the value 4, I'm forcing it to run with the API as shown above. The Java version is given in separate code

Map pOptions = JavaCore.getOptions();
        pOptions.put("org.eclipse.jdt.core.compiler.compliance", "11");
        pOptions.put("org.eclipse.jdt.core.compiler.codegen.targetPlatform", "11");
        pOptions.put("org.eclipse.jdt.core.compiler.source", "11");
        pOptions.put("org.eclipse.jdt.core.compiler.doc.comment.support", "enabled");
        parser.setCompilerOptions(pOptions);
        char[] source = readerToCharArray(r);
GTSZM commented 3 years ago

By the way, do you have more detailed documentation on how to work with the API? The wiki doesn't have much.

jrfaller commented 3 years ago

Hi!

I still believe you have the wrong version or maybe this is because you read decompiled code because when navigating in JDT's code I have the following:

ASTParser(int level) {
        DOMASTUtil.checkASTLevel(level);
        this.apiLevel = level;
        initializeDefaults();
}

public static void checkASTLevel(int level) {
    // Clients can use AST.JLS_Latest
    if(level >=AST.JLS8 && level <= AST.JLS_Latest )
        return;
    switch (level) {
            case AST.JLS2 :
            case AST.JLS3 :
            case AST.JLS4 :
                return;
    }
    throw new IllegalArgumentException(Integer.toString(level));
}

W.r.t. the documentation, sorry but but that's all for now 😢

Cheers!