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

Have RequestParamType ignore parameter types with custom deserialization support #426

Merged
merged 3 commits into from
Jan 4, 2023

Conversation

chamil-prabodha
Copy link
Contributor

@chamil-prabodha chamil-prabodha commented Dec 28, 2022

One would want to use classes such as ImmutableList with @RequestParam given that the custom support for the underlying conversion is provided. For such occasions we can specify the classes we wish to be included on top of what is already provided (by Spring) by using the flag -XepOpt:RequestParamType:Includes=<class-name>

@chamil-prabodha chamil-prabodha force-pushed the chamil-prabodha/PSM-1820 branch from 6e66597 to 5f70f62 Compare December 28, 2022 13:58
@github-actions
Copy link

  • Surviving mutants in this change: 1
  • Killed mutants in this change: 10
class surviving killed
🧟tech.picnic.errorprone.bugpatterns.RequestParamType 1 10

Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

1 similar comment
@github-actions
Copy link

  • Surviving mutants in this change: 1
  • Killed mutants in this change: 10
class surviving killed
🧟tech.picnic.errorprone.bugpatterns.RequestParamType 1 10

Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

@github-actions
Copy link

Looks good. All 11 mutations in this change were killed.

class surviving killed
🎉tech.picnic.errorprone.bugpatterns.RequestParamType 0 11

Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

@chamil-prabodha chamil-prabodha marked this pull request as ready for review December 28, 2022 15:33
@chamil-prabodha chamil-prabodha changed the title Introduce support to use additional classes with @RequestParam Introduce support for using additional classes with @RequestParam Dec 28, 2022
@chamil-prabodha chamil-prabodha force-pushed the chamil-prabodha/PSM-1820 branch from 2cf48d9 to 5a48292 Compare December 29, 2022 09:10
@github-actions
Copy link

Looks good. All 11 mutations in this change were killed.

class surviving killed
🎉tech.picnic.errorprone.bugpatterns.RequestParamType 0 11

Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

@Stephan202 Stephan202 force-pushed the chamil-prabodha/PSM-1820 branch from 5a48292 to fb04db6 Compare January 1, 2023 14:41
Copy link
Member

@Stephan202 Stephan202 left a comment

Choose a reason for hiding this comment

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

Rebased and added a commit. Thanks for this PR!

Suggested commit message:

Have `RequestParamType` ignore parameter types with custom deserialization support (#426)

While there, introduce and use a new `Flags` utility class; various checks'
list flags now better support empty lists.

Comment on lines 80 to 81
.map(String::trim)
.filter(inclusion -> !inclusion.isEmpty())
Copy link
Member

Choose a reason for hiding this comment

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

Other code where we call ErrorProneFlags#getList doesn't trim or filter. Perhaps we should introduce support for that, but for now let's keep the burden with the caller.

Edit: added a helper method :)

? describeMatch(tree)
: Description.NO_MATCH;
}

private static Matcher<VariableTree> createVariableTreeMatcher(ErrorProneFlags flags) {
Copy link
Member

Choose a reason for hiding this comment

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

This method name doesn't explain what the returned matcher does.


/** Instantiates a new {@link RequestParamType} instance. */
public RequestParamType() {}
private final Matcher<VariableTree> hasUnsupportedRequestParams;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
private final Matcher<VariableTree> hasUnsupportedRequestParams;
private final Matcher<VariableTree> hasUnsupportedRequestParam;

Even clearer: hasUnsupportedRequestParamType.

allOf(
annotations(AT_LEAST_ONE, isType("org.springframework.web.bind.annotation.RequestParam")),
anyOf(isSubtypeOf(ImmutableCollection.class), isSubtypeOf(ImmutableMap.class)));
private static final String FLAG_PREFIX = "RequestParamType:";
Copy link
Member

Choose a reason for hiding this comment

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

This can be inlined.

annotations(AT_LEAST_ONE, isType("org.springframework.web.bind.annotation.RequestParam")),
anyOf(isSubtypeOf(ImmutableCollection.class), isSubtypeOf(ImmutableMap.class)));
private static final String FLAG_PREFIX = "RequestParamType:";
private static final String INCLUDED_CLASS_FLAG = FLAG_PREFIX + "Includes";
Copy link
Member

Choose a reason for hiding this comment

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

  • This flag name should somehow convey that it enumerates types for which custom support in provided.
  • The constant should have s/CLASS/TYPES/.

Comment on lines 86 to 80
private static Class<?> createClass(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException(
String.format("Invalid class name '%s' in `%s`", className, INCLUDED_CLASS_FLAG), e);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

We should not require the listed types to be on the classpath, as that prevents users from centrally configuring the types in a multi-module (Maven) project in which some modules don't have the listed type.

(Also, IIUC this would attempt to load the class from the annotation processor classpath rather than the compilation classpath, which is incorrect.)

Comment on lines 10 to 22
private final CompilationTestHelper restrictedCompilationTestHelper =
CompilationTestHelper.newInstance(RequestParamType.class, getClass())
.setArgs(
ImmutableList.of(
"-XepOpt:RequestParamType:Includes=com.google.common.collect.ImmutableCollection"));
private final CompilationTestHelper restrictedWithSubTypeCompilationTestHelper =
CompilationTestHelper.newInstance(RequestParamType.class, getClass())
.setArgs(
ImmutableList.of(
"-XepOpt:RequestParamType:Includes=com.google.common.collect.ImmutableSet"));
private final CompilationTestHelper restrictedWithInvalidFlagCompilationTestHelper =
CompilationTestHelper.newInstance(RequestParamType.class, getClass())
.setArgs(ImmutableList.of("-XepOpt:RequestParamType:Includes="));
Copy link
Member

Choose a reason for hiding this comment

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

Given the logic involved, IIUC one case would suffice.

private final CompilationTestHelper restrictedCompilationTestHelper =
CompilationTestHelper.newInstance(RequestParamType.class, getClass())
.setArgs(
ImmutableList.of(
Copy link
Member

Choose a reason for hiding this comment

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

We can omit ImmutableList.of here. (Yep, can also be cleaned up in other tests; I have a TODO list entry for a BugChecker that flags such cases.)

return flags.getList(INCLUDED_CLASS_FLAG).map(ImmutableList::copyOf).orElse(ImmutableList.of());
}

private static ImmutableList<Matcher<Tree>> getSupportedClasses(
Copy link
Member

Choose a reason for hiding this comment

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

This method returns matchers, not classes.

@github-actions
Copy link

github-actions bot commented Jan 1, 2023

Looks good. All 11 mutations in this change were killed.

class surviving killed
🎉tech.picnic.errorprone.bugpatterns.RequestParamType 0 7
🎉tech.picnic.errorprone.bugpatterns.util.Flags 0 3
🎉tech.picnic.errorprone.bugpatterns.RedundantStringConversion 0 1

Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

@rickie rickie force-pushed the chamil-prabodha/PSM-1820 branch from fb04db6 to eace6ce Compare January 3, 2023 10:42
@github-actions
Copy link

github-actions bot commented Jan 3, 2023

Looks good. All 11 mutations in this change were killed.

class surviving killed
🎉tech.picnic.errorprone.bugpatterns.RequestParamType 0 7
🎉tech.picnic.errorprone.bugpatterns.util.Flags 0 3
🎉tech.picnic.errorprone.bugpatterns.RedundantStringConversion 0 1

Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

Copy link
Member

@rickie rickie left a comment

Choose a reason for hiding this comment

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

One option we can discuss. Anyway approving the code as it looks good already!

Nice PR @chamil-prabodha 😄 !

@Stephan202 nice Flags improvements 🚀 !

@@ -6,6 +6,10 @@
final class RequestParamTypeTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(RequestParamType.class, getClass());
private final CompilationTestHelper restrictedCompilationTestHelper =
Copy link
Member

@rickie rickie Jan 3, 2023

Choose a reason for hiding this comment

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

@nathankooij In Error Prone there are cases for both situations; but it can be nice to inline the restrictedCompilationTestHelper IMO. Usually there is only one test with the restricted variant and would make it extra clear in the test method itself that we are using extra flags. Besides that, the flag would be closer to the test, which makes the intend clearer as well.

WDYT?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I've pondered this a few times as well. I'm fine with that, though it sounds like we should do that in a separate PR.

Copy link
Member

Choose a reason for hiding this comment

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

I'll file a PR for that then!

Copy link
Member

Choose a reason for hiding this comment

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

Filed #442.

@rickie rickie force-pushed the chamil-prabodha/PSM-1820 branch from eace6ce to 63a1386 Compare January 4, 2023 09:56
@github-actions
Copy link

github-actions bot commented Jan 4, 2023

Looks good. All 11 mutations in this change were killed.

class surviving killed
🎉tech.picnic.errorprone.bugpatterns.RequestParamType 0 7
🎉tech.picnic.errorprone.bugpatterns.util.Flags 0 3
🎉tech.picnic.errorprone.bugpatterns.RedundantStringConversion 0 1

Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

@rickie rickie added this to the 0.7.0 milestone Jan 4, 2023
@rickie rickie changed the title Introduce support for using additional classes with @RequestParam Have RequestParamType ignore parameter types with custom deserialization support Jan 4, 2023
@rickie rickie merged commit 9d08e8f into master Jan 4, 2023
@rickie rickie deleted the chamil-prabodha/PSM-1820 branch January 4, 2023 10:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

3 participants