INRIA / INRIA/spoon

[Bug] `CtNewClass#getType()` returns type of superclass/superinterface

Open
#4,291 3 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Java
Stars
2k
Forks
392
Avg merge
11h 24m
Merged PRs (30d)
36

Description

**Describe the bug**

This problem occured to me when inspecting how anonymous enum types are handled in Java 17. Enums with anonymous enum values are `sealed` in Java 17, with the anonymous enum values as *permitted types*.

A place where this might be more relevant is my example below, as `var` allows to capture the type of an anonymous class (and you can use methods declared in the anonymous type). In such a case, the type of the `CtLocalVariable` is the anonymous type, but the type of the default expression is the super class/interface. From my understanding, the type of the default expression should be the anonymous type too.

I looked into it a bit but I wasn't able to come up with a quick solution that does not break a lot of test cases. What I considered so far:
https://github.com/INRIA/spoon/blob/2fff4c50266f79bc06b961e3b01ca6c6e0fcc1ab/src/main/java/spoon/support/reflect/code/CtConstructorCallImpl.java#L193 returns the type of the executable. I'm not sure if the type of the executable should probably even be the anonymous type at this point, but `CtExecutableReference` also has a *declaring type* which is the anonymous type already.

If the type reported by CtConstructorCallImpl is correct in the cases where it isn't a CtNewClassImpl, one could also override the method there and return the type of the anonymous class.

I'm not sure what the proper approach here would be, and the two things I mentioned are causing a lot of failing tests.

**To Reproduce**

Input:
```java
public class X {
interface Y { }
public void method() {
var obj = new Y() {
public void hello() {
System.out.println("Hello World");
}
};
obj.hello();
}
}
```

Processing with Spoon:
```java
Launcher launcher = new Launcher();
launcher.getEnvironment().setComplianceLevel(11);
// code is a string containing the code above
launcher.addInputResource(new VirtualFile(code));
launcher.buildModel();
CtMethod ctMethod = launcher.getFactory().Type().get("X").getMethods().stream().findFirst().orElseThrow();
CtLocalVariable localVariable = (CtLocalVariable) ctMethod.getBody().getStatements().get(0);
System.out.println(localVariable.getType());
System.out.println(localVariable.getDefaultExpression().getType());
```

Output:
```java
X.1
X.Y
```

Note that you can also open a pull request reproducing the issue and reference that, instead of writing additional information here.

**Operating system, JDK and Spoon version used**

* OS: Windows 10
* JDK: AdoptOpenJDK 16.0.1
* Spoon version: 10.0.0

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.