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

CDI recipe #340

Merged
merged 38 commits into from
Jan 30, 2024
Merged

CDI recipe #340

merged 38 commits into from
Jan 30, 2024

Conversation

ranuradh
Copy link
Contributor

@ranuradh ranuradh commented Nov 7, 2023

What's changed?

This recipe takes care of the following rules:

image

2 recipes were added -
UpdateAddAnnotatedType: Here an argument String with value null was added to the return type
UpdateBeanManagerMethod : Removes the deprecated method and substitutes with the right call

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

Anyone you would like to review specifically?

@cjobinabo , @timtebeek

Have you considered any alternatives or workarounds?

Any additional context

Checklist

  • I've added unit tests to cover both positive and negative cases
  • I've added the license header to any new files through ./gradlew licenseFormat
  • I've used the IntelliJ IDEA auto-formatter on affected files

@ranuradh ranuradh self-assigned this Nov 7, 2023
@timtebeek timtebeek requested a review from cjobinabo November 7, 2023 08:53
@timtebeek timtebeek added the recipe Recipe requested label Nov 7, 2023
@ranuradh ranuradh requested a review from timtebeek November 7, 2023 16:17
beforeBeanDiscovery.addAnnotatedType(producerType, "my unique id"); // Not this one
beforeBeanDiscovery.addAnnotatedType(String.class, "my other unique id"); // Not this one

beanManager.getInjectionTargetFactory().createInjectionTarget(producerType);
Copy link
Contributor

Choose a reason for hiding this comment

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

getInjectionTargetFactory needs to take in the annotatedType which was previous passed to createInjectionTarget
Screenshot 2023-11-07 at 1 07 27 PM

createInjectionTarget would take in null. Here are some examples I've seen of this code being used https://www.tabnine.com/code/java/methods/javax.enterprise.inject.spi.BeanManager/getInjectionTargetFactory

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 couldnt get this to work as well since if the arguments are right I was using the simpleName change and that worked..now we need to add different arguments to the methods as well. I updated the test

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay I'll look into both updates

@timtebeek
Copy link
Contributor

What's the status on this PR? I see some unresolved conversations above, and partial in the title, as well as some small formatting deviations.

Let me know when it's ready to review!

@cjobinabo
Copy link
Contributor

cjobinabo commented Nov 16, 2023

@timtebeek I see some of the formatting deviations you are referring to. I'll push some of those updates for Anu shortly.

I did leave a question for you about how to handle the removal of Bean.isNullable().
Ex:

if(!myFavoriteBean.isNullable()) {
   // do something;
}

I initially thought we could just update uses of myFavoriteBean.isNullable() to false but quickly realized that a method visitor cannot return a literal. So instead, I proposed updating myFavoriteBean.isNullable() to Boolean.valueOf("false"). I wanted to see if you had a better suggestion.

@cjobinabo cjobinabo changed the title partial cdi recipe CDI recipe Nov 16, 2023
@timtebeek
Copy link
Contributor

@timtebeek I see some of the formatting deviations you are referring to. I'll push some of those updates for Anu shortly.

Thanks for taking those changes on! Helps me focus on the function of the recipes in my review.

I did leave a question for you about how to handle the removal of Bean.isNullable(). Ex:

if(!myFavoriteBean.isNullable()) {
   // do something;
}

I initially thought we could just update uses of myFavoriteBean.isNullable() to false but quickly realized that a method visitor cannot return a literal. So instead, I proposed updating myFavoriteBean.isNullable() to Boolean.valueOf("false"). I wanted to see if you had a better suggestion.

If you implement JavaVisitor instead of JavaIsoVisitor then visitMethodInvocation can return a literal instead, which is probably what you'll want to do here. There's more information on (non-)isomorphic visitors in the docs.

After you replace the method invocation with false we can try to clean up any leftover conditionals with something similar to what I'm doing here. Note that that's not a finished implementation yet, but it could help clear out old code and not be left with if (false) { .. } or if (!false) { ... }

@cjobinabo
Copy link
Contributor

If you implement JavaVisitor instead of JavaIsoVisitor then visitMethodInvocation can return a literal instead, which is probably what you'll want to do here. There's more information on (non-)isomorphic visitors in the docs.

This is good to know. I have a meeting coming up in 10 minutes. After that is done I'll look into using JavaVisitor.

@cjobinabo
Copy link
Contributor

I've gone ahead and updated the code to return false and then simplified the logic as you recommended. Feel free to suggest any additional changes to the original rule logic that you think make sense. I tried not to deviate too far from the original code that was written.

Description should end with a dot; and reflect what the recipe does.
Call super in the normal code path.
Remove superfluous nullable annotations.
Add missing space in case `false` is retained.
Comment on lines 267 to 268
- org.openrewrite.java.migrate.jakarta.UpdateAddAnnotatedType:
methodPattern: jakarta.enterprise.inject.spi.BeforeBeanDiscovery addAnnotatedType(jakarta.enterprise.inject.spi.AnnotatedType)
Copy link
Contributor

Choose a reason for hiding this comment

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

UpdateAddAnnotatedType is only used once, yet the implementation seems to switch between two types of method patterns. Should it be used once more? Or can we simplify the implementation to only support a single case?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@timtebeek I added the javax case as well .Should be there in the final commit.

Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than one big test to verify three different Java recipes, as well as some yaml configuration, I'd prefer to see a unit test class per Java recipe; That helps make it clear what each recipe contributes, and allows one to jump from the implementation directly to the associated tests rather than having to deduce that from usage in yaml files.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@timtebeek will do that from the next recipe. This one just would up like that

if (type != null) {
type = type.withName(newMethodName);
}
return method.withName(method.getName().withSimpleName(newMethodName)).withMethodType(type);
Copy link
Contributor

Choose a reason for hiding this comment

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

This won't work well with our type system I think, to have a methodName containing getEvent().fire. Instead we should likely use a JavaTemplate here to create the chain of method invocations.

Copy link
Contributor

Choose a reason for hiding this comment

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

This was also not addressed.

Copy link
Contributor Author

@ranuradh ranuradh Nov 28, 2023

Choose a reason for hiding this comment

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

@timtebeek I tried to update the code with the template..no matter what I tried it keeps failing.Hence I used this way

//                    maybeRemoveImport("jakarta.enterprise.inject.spi.BeanManager");
//                    return JavaTemplate.builder("#{any(jakarta.enterprise.inject.spi.BeanManager)}.getEvent().fire(#{any()})")
//                            .build()
//                            .apply(updateCursor(mi), mi.getCoordinates().replace(), mi.getSelect(), mi.getArguments().get(0));

Not sure why the template approach didnt work for getEvent()

@timtebeek
Copy link
Contributor

@ranuradh There's still unresolved remarks above; could you respond to and address the earlier feedback?

@ranuradh
Copy link
Contributor Author

@timtebeek I fixed all the concerns other than the template usage for getEvent().

@melloware
Copy link
Contributor

Looks like there are still conflicts with this branch?

@timtebeek timtebeek requested review from timtebeek and removed request for joanvr December 27, 2023 10:39
@timtebeek
Copy link
Contributor

Would be great if we could get these conflicts resolved before a more thorough review and merge.

@timtebeek
Copy link
Contributor

The CI logs seem to be filled with stacktraces on classes added in this PR:

org.openrewrite.config.RecipeIntrospectionException: Unable to call primary constructor for Recipe class org.openrewrite.java.migrate.jakarta.UpdateAddAnnotatedType
org.openrewrite.config.RecipeIntrospectionException: Unable to call primary constructor for Recipe class org.openrewrite.java.migrate.jakarta.UpdateBeanManagerMethod

Can we fix those issues?

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.

Thanks for adding this one @ranuradh ! I've pushed changes in the last few commits that would be good to repeat in other PRs

  • have individual unit tests per Java recipe; this helps flush out validation issues
  • no need to make recipes configurable if they are specific
  • don't match on method simple name; use dedicated method matchers instead
  • use wildcards if you want to match similar classes in both javax and jakarta
  • minimize your tests to only show the recipe relevant code changes, not any common surrounding context

Hope that helps, and look forward to what you'll produce next! :)

@timtebeek timtebeek merged commit aa43f7b into openrewrite:main Jan 30, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
recipe Recipe requested
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

5 participants