Skip to content

Conversation

@knutwannheden
Copy link
Contributor

Improves the type attribution for method references by "manually" instantiating the J.MemberReference rather than via JavaTemplate. This may seem strange, but the reason is that the recipe doesn't know where the type is coming from (JDK, 3rd party library, or even source path), so the template's compiler may not have the type on its classpath and cannot really produce a properly type-attributed result.

Improves the type attribution for method references by "manually" instantiating the `J.MemberReference` rather than via `JavaTemplate`. This may seem strange, but the reason is that the recipe doesn't know where the type is coming from (JDK, 3rd party library, or even source path), so the template's compiler may not have the type on its classpath and cannot really produce a properly type-attributed result.
@knutwannheden knutwannheden self-assigned this Jun 29, 2023
@knutwannheden knutwannheden requested review from joanvr and sambsnyd June 29, 2023 07:11
@timtebeek timtebeek added the enhancement New feature or request label Jun 29, 2023

import static org.openrewrite.Tree.randomId;

final class JavaElementFactory {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please note that this class was intentionally not made public. I don't know how we intend to address this kind of problem in the long run (creating LST elements which potentially refer to types from the source set). While I think it would be nice if JavaTemplate could be used for this, I have my doubts if we will be able to provide this any time soon. So in the meantime I suggest that we have a factory like this one.

J.Binary binary = (J.Binary) body;
if (isNullCheck(binary.getLeft(), binary.getRight()) ||
isNullCheck(binary.getRight(), binary.getLeft())) {
maybeAddImport("java.util.Objects");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is basically how it all got started: I wanted to use the new ShortenFullyQualifiedTypeReferences recipe to allow removing this line (to avoid conflicts with any other imports for types with Objects as the simple name). That is how I discovered the incorrect type attribution with the stub from a few lines above.

!(j.getType() instanceof JavaType.GenericTypeVariable)) {
body = tree;
code = "#{}.class::cast";
J tree = j.getTree();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were checking if j could be null previously, it was not needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeCast#getClazz() is not annotated as @Nullable, so I think this should be fine.

"Objects::nonNull";
doAfterVisit(new ShortenFullyQualifiedTypeReferences().getVisitor());
code = J.Binary.Type.Equal.equals(binary.getOperator()) ? "java.util.Objects::isNull" :
"java.util.Objects::nonNull";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OpenRewrite doesn't provide any API to do a lookup of types. That would sometimes be useful to have.

@knutwannheden knutwannheden merged commit 1a2d031 into main Jun 29, 2023
@knutwannheden knutwannheden deleted the method-reference-type-attribution branch June 29, 2023 08:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

More accurate type attribution validation in RewriteTest

4 participants