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

Fix/no guava immutable recipes #258

Merged
merged 5 commits into from
Jul 14, 2023
Merged

Conversation

joanvr
Copy link
Contributor

@joanvr joanvr commented Jul 12, 2023

What's changed?

First, we removed a previous change that allowed Map.of to be assigned to ImmutableMap (this was done to allow nested maps), but was causing uncompilable code.

Added some tests to validate that we do not produce changes in those scenarios for all three collections (List, Set, Map).

Also, since all three recipes (List, Set, Map), have the same duplicated code that needs to be synched, and already had slightly different versions, I've decided to extract it in a parent class, to avoid future inconsistence problems like it was happening right now

What's your motivation?

Fixes #256

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

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 auto-formatter on affected files
  • I've updated the documentation (if applicable)

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.

Looks good to me; thanks for fixing the issue and cleaning up the code at the same time.


public abstract class AbstractNoGuavaImmutableOf extends Recipe {

private transient final MethodMatcher IMMUTABLE_MATCHER = new MethodMatcher(getGuavaType() + " of(..)");
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the background behind adding the transient here? Is it because of the call to getGuavaType when combined with final?

I'm reading up a bit and found some conflicting reports of using transient, final, and non-trivial objects together when serialization might be involved.

If you think it'll work fine that fine by me; but wanted to ask both to learn and get a second opinion.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The RewriteTests validates that a recipe can be serializable and also checks that after deserializing are equal.
MethodMatcher was causing an InvalidDefinitionException with jackson. I've seen in many other recipes that they put all this "complex" fields to static members (because it makes sense for performance, but also avoids the serde problem) but I cannot do that since it depends on a method that must be defined by an extending class...
I've also seen some recipes with transient + final (I don't know if wrongly used), and after checking it myself in the place where the serialization+deserialization is done, it seems to not be an issue with jackson.
WDYT? I can move this to a method (although it will be instantiating a new one every time) or remove the final if you want.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe it would make sense to define a constructor in AbstractNoGuavaImmutableOf that takes in two arguments, and reduce NoGuavaImmutableMapOf to just calling that constructor with those two arguments?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a good idea the constructor thing, but I do not see how it will solve the matcher issue

Copy link
Contributor

Choose a reason for hiding this comment

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

we could move the creation of the matcher into getVisitor(), but before the return Preconditions.check. I don't think that getVisitor gets called repeatedly nowadays, but I 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.

pushed just now in 20564ab
hope you agree; otherwise open for a revert and further discussion

@timtebeek timtebeek merged commit b352e2d into main Jul 14, 2023
@timtebeek timtebeek deleted the fix/no-guava-immutable-recipes branch July 14, 2023 16:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Guava ImmutableMap recipe fails when variable type is ImmutableMap
2 participants