ShortenFullyQualifiedTypeReferences conflicts with Types defined in parent class
What version of OpenRewrite are you using?
rewrite-java 8.31.1
What is the smallest, simplest way to reproduce the problem?
I can reproduce the issue using this test case:
@Test
void leaveFullTypeReferenceForSuperclassClash() {
rewriteRun(
spec -> spec.recipe(new ShortenFullyQualifiedTypeReferences()),
srcMainJava(
java(
"""
package com.helloworld;
public interface Parent {
class Set {}
}"""),
java(
"""
package com.helloworld;
public class Main implements Parent {
public void get() {
final java.util.Set set = null;
}
}""")));
}
What did you expect to see?
Because a class definition in the parent interface with the same type name shadows the import, the fully qualified type reference is still needed. I would expect the recipe to bail out in this case.
What did you see instead?
package com.helloworld;
import java.util.Set;
public class Main implements Parent {
public void get() {
final Set set = null; // <-- this variable now became Parent.Set instead of java.util.Set
}
}
Are you interested in contributing a fix to OpenRewrite?
Short on time at the moment, possibly later.
This looks tricky to fix. The problem is that we in the type attribution only have the reference from a nested class to the outer class, but not the inverse. This is something we should look into to allow this recipe to be implemented correctly.
I encountered a very similar issue in which we had something along these lines:
import org.example.v1.UnrelatedType1;
import org.example.v1.SomethingElse2;
import org.example.v360.Type1;
import org.example.v360.Type2;
import org.example.v360.Type3;
[ .. and then a lot of methods using things like org.example.v1.Type3 / 4 / ... ]
Let's assume both v1 & v360 have Role defined.
However, we had (in this case) a test defined like:
when(roleMapper.mapRole(any(java.util.ArrayList.class))).thenReturn(new ArrayList<org.example.v1.Role>());
As you can spot, Role is not imported, but referenced directly. (as were a lot of other things -- bad I know)
Autoconversion made it into:
import org.example.v1.*;
import org.example.v360.*;
when(roleMapper.mapRole(any(ArrayList.class))).thenReturn(new ArrayList<Role>());
But now Role is not uniquely defined any longer.
I think this is a play between ShortenFullyQualifiedTypeReferences and org.openrewrite.staticanalysis.CodeCleanup or org.openrewrite.java.OrderImports.
If this is sufficiently different from OP's issue, I'll copy/paste this explanation into a new ticket. Just tell me if I need to do so.