[Bug]: `CtVariableRead` has wrong type when a formal type parameter is set to a concrete type (`T = Integer`)
- Dominant language
- Java
- Stars
- 2k
- Forks
- 392
- Avg merge
- 11h 24m
- Merged PRs (30d)
- 36
Description
### Describe the bug
Given the below code, two problems occur:
1. The type of the variable read should be `Integer` and not `T`
2. If one were to assume that `T` is the correct type, the code crashes when calling `isSubtypeOf`, because the `declaringType` is not set
### Source code you are trying to analyze/transform
```Java
class Command {
protected final T value;
protected Command(T value) {
this.value = value;
}
}
class ResultsInCrash extends Command {
ResultsInCrash(Integer value) {
super(value);
}
public String execute() {
return value.toString();
}
}
```
### Source code for your Spoon processing
```Java
import org.junit.jupiter.api.Test;
import spoon.Launcher;
import spoon.reflect.CtModel;
import spoon.reflect.code.CtInvocation;
import spoon.reflect.code.CtNewArray;
import spoon.reflect.code.CtReturn;
import spoon.reflect.code.CtVariableRead;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtField;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.reference.CtArrayTypeReference;
import spoon.reflect.reference.CtTypeReference;
import spoon.support.compiler.VirtualFile;
import static org.junit.jupiter.api.Assertions.*;
class TestSpoon {
@Test
void testFormalTypeParameterType() {
CtClass ctClass = Launcher.parseClass(
"public class Example {\n" +
" class Command {\n" +
" protected final T value;\n" +
"\n" +
" protected Command(T value) {\n" +
" this.value = value;\n" +
" }\n" +
" }\n" +
"\n" +
" class ResultsInCrash extends Command {\n" +
" ResultsInCrash(Integer value) {\n" +
" super(value);\n" +
" }\n" +
"\n" +
" public String execute() {\n" +
" return value.toString();\n" +
" }\n" +
" }\n" +
"}\n"
);
CtMethod execute = ctClass.getNestedType("ResultsInCrash").getMethod("execute");
CtReturn ctReturn = execute.getBody().getLastStatement();
// the `value.toString()` expression:
CtInvocation ctInvocation = (CtInvocation) ctReturn.getReturnedExpression();
CtVariableRead ctVariableRead = (CtVariableRead) ctInvocation.getTarget();
assertEquals(ctVariableRead.getFactory().Type().INTEGER, ctVariableRead.getType());
}
}
```
### Actual output
```Java
org.opentest4j.AssertionFailedError:
Expected :Integer
Actual :T
at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:182)
at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:177)
at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1142)
at org.example.playground.TestSpoon.testFormalTypeParameterType(TestSpoon.java:84)
....
```
### Expected output
_No response_
### Spoon Version
10.4.0
### JVM Version
openjdk version "17.0.1" 2021-10-19 OpenJDK Runtime Environment Temurin-17.0.1+12 (build 17.0.1+12) OpenJDK 64-Bit Server VM Temurin-17.0.1+12 (build 17.0.1+12, mixed mode, sharing)
### What operating system are you using?
Windows 10
Contributor guide
Assessment
This issue has not been assessed yet.