spoon
spoon copied to clipboard
[Bug]: Problem in detecting the type of 'var' keyword from a CtInvocation
Describe the bug
Hi
I am trying to get all method invocations in a given method. I found an exceptional case in which SPOON is not able to correctly identify the type of the var
keyword. As you can see in my example below, the declaring type of the l1.add
method is detected as com.test.example.var
while it should be java.util.List
. However, when the var
keyword is replaced with the actual type (l2.add
), the declaring type is correctly detected.
Source code you are trying to analyze/transform
package com.test.example;
import java.util.Arrays;
import java.util.List;
public class Test {
public static List<String> foo() {
return Arrays.asList("a", "b", "c");
}
public static void bar() {
var l1 = foo();
l1.add("d");
List<String> l2 = foo();
l2.add("d");
}
}
Source code for your Spoon processing
package com.test.example;
import spoon.Launcher;
import spoon.reflect.CtModel;
import spoon.reflect.code.CtInvocation;
import spoon.reflect.declaration.CtExecutable;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtType;
import spoon.reflect.visitor.filter.AbstractFilter;
import java.util.List;
public class Main {
private static List<CtInvocation<?>> getInvocations(CtExecutable<?> executable) {
return executable.getElements(new AbstractFilter<>() {
@Override
public boolean matches(CtInvocation<?> element) {
return super.matches(element);
}
});
}
public static void main(String[] args) {
Launcher launcher = new Launcher();
launcher.addInputResource("./Test.java");
launcher.buildModel();
CtModel model = launcher.getModel();
for (CtType<?> s : model.getAllTypes()) {
for (CtMethod<?> m : s.getAllMethods()) {
for (CtInvocation<?> inv: getInvocations(m)) {
System.out.println("method = " + m.getSignature());
System.out.println("invocation = " + inv.getExecutable());
System.out.println("declaring type = " + inv.getExecutable().getDeclaringType());
System.out.println("__________________");
}
}
}
}
}
Actual output
method = foo()
invocation = asList(java.lang.Object[])
declaring type = java.util.Arrays
__________________
method = bar()
invocation = foo()
declaring type = com.test.example.Test
__________________
method = bar()
invocation = add(java.lang.String)
declaring type = com.test.example.var
__________________
method = bar()
invocation = foo()
declaring type = com.test.example.Test
__________________
method = bar()
invocation = add(java.lang.Object)
declaring type = java.util.List
__________________
Expected output
No response
Spoon Version
10.2.0-beta-11
JVM Version
11
What operating system are you using?
Pop!_OS 22.04 LTS
You need to set the compliance level to at least 10, i.e. launcher.getEnvironment().setComplianceLevel(10)
. The current default value is still 8.
Thank you very much @SirYwell , that solved the issue. I should have done more research to discover this configuration. It is a good idea though if you could explain this config in this page of your documentation.
Before I close this issue, I have one question and I would appreciate your answer. How large is the effect of changing the Compliance Level from 8 to 10 on other functionalities? I am working on large code bases and I want to make sure that I don't miss anything.
It is a good idea though if you could explain this config in this page of your documentation.
I agree. I think you can leave the issue open until we changed that.
I have one question and I would appreciate your answer. How large is the effect of changing the Compliance Level from 8 to 10 on other functionalities?
There are differences how other Java >8 features (e.g. modules) are handled, obviously. Besides open issues, I'm not aware of any changes of functionality, the compliance level is mainly used by JDT when parsing the source code. If you encounter any issues with it, I'd encourage you to report it to us.