Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AddNullMethodArgument recipe #4047

Merged
merged 8 commits into from
Feb 25, 2024
Merged

Conversation

pstreef
Copy link
Contributor

@pstreef pstreef commented Feb 24, 2024

What's changed?

Add recipe AddNullMethodArgument

What's your motivation?

When changing a method we often add a nullable argument. Sometimes overriding it as to not break existing consumers. With this recipe we can migrate more quickly by adding a null value as the argument.

Anything in particular you'd like reviewers to focus on?

line 104 of the recipe, creating the actual null literal.
Also addArgumentsConsecutively is not working as expected. Any suggestions? If not I'll give it another try soon.

Anyone you would like to review specifically?

@timtebeek

Checklist

  • I've added unit tests to cover both positive and negative cases
  • I've read and applied the recipe conventions and best practices
  • I've used the IntelliJ IDEA auto-formatter on affected files

When changing a method we often add a nullable argument. Sometimes overriding it as to not break existing consumers. With this recipe we can migrate more quickly by adding a null value as the argument.
Copy link
Contributor

@timtebeek timtebeek left a comment

Choose a reason for hiding this comment

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

Great start! I think we can improve it with some minor touches to make it more widely applicable and correct.

List<String> parameterNames = new ArrayList<>(methodType.getParameterNames());
parameterNames.add(argumentIndex, "null");
List<JavaType> parameterTypes = new ArrayList<>(methodType.getParameterTypes());
parameterTypes.add(argumentIndex, JavaType.Primitive.Null);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not so sure about this parameter type Null here; Perhaps we need another argument where folks can pass in a FQN of the target type. That way any subsequent recipes in a larger migration will also match the method invocation going forward, especially if this is one partial step of a larger migration.

By comparison, now we end up with this after a recipe execution in void addToMiddleArgument()
image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ah, now this makes a lot more sense indeed. I did not fully understand what this part was doing to be honest 😅
I think passing the type (maybe also param name?) is OK as you should always know the exact method you are migrating to.
I don't think there is a way to determine/find this data if the method is not defined in the project is there?

Copy link
Contributor

Choose a reason for hiding this comment

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

Not as easily reliably no, especially when we start stacking migration recipes where you start out without that new method available in an older version of a library.

}

args.add(argumentIndex, new J.Literal(randomId(), args.isEmpty() ? Space.EMPTY : Space.SINGLE_SPACE, Markers.EMPTY, "null", "null", null, JavaType.Primitive.Null));
m = m.withArguments(args);
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps this would be a little more in line with what we use elsewhere?

m = m.withArguments(ListUtils.insert(m.getArguments(), new J.Literal(...), argumentIndex));

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I copied most of the cose (including this part) from DeleteMethodArgument but happy to change to this!

@timtebeek timtebeek added the recipe Requested Recipe label Feb 24, 2024
pstreef and others added 3 commits February 25, 2024 07:24
Co-authored-by: Tim te Beek <tim@moderne.io>
Co-authored-by: Shannon Pamperl <shanman190@gmail.com>
}

@Test
void addCastToConflictingArgumentType() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've added this because of possible conflicts. However I'm not sure how to get the cast to only use the not-so-fully qualified name.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is fine; should be rare that there's overloads, which require an explicit cast to String.

If you really want to get rid of this you can shorted fully qualified type references as we do here:
https://github.com/openrewrite/rewrite-templating/blob/e69126c2209f4edd1cb8e203d6eaeda26ff744b1/src/main/java/org/openrewrite/java/template/internal/AbstractRefasterJavaVisitor.java#L45

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried this but it does not shorten the cast.

Copy link
Contributor

Choose a reason for hiding this comment

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

For java.lang we indeed don't shorten fully qualified names, as that could be wrong.

Copy link
Contributor

Choose a reason for hiding this comment

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

Although note that also java.lang types would end up as unqualified if the compilation unit already contains unqualified references to that type (which is often the case), so using this visitor is probably still a good idea.

@pstreef
Copy link
Contributor Author

pstreef commented Feb 25, 2024

@shanman190 Thanks, not sure how I missed those 🙈

Copy link
Contributor

@timtebeek timtebeek left a comment

Choose a reason for hiding this comment

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

Nice addition!

}

@Test
void addCastToConflictingArgumentType() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is fine; should be rare that there's overloads, which require an explicit cast to String.

If you really want to get rid of this you can shorted fully qualified type references as we do here:
https://github.com/openrewrite/rewrite-templating/blob/e69126c2209f4edd1cb8e203d6eaeda26ff744b1/src/main/java/org/openrewrite/java/template/internal/AbstractRefasterJavaVisitor.java#L45

@pstreef pstreef merged commit 5f18069 into main Feb 25, 2024
1 check passed
@pstreef pstreef deleted the feat/add-null-method-argument branch February 25, 2024 11:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
recipe Requested Recipe
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

4 participants