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

HV-840 [follow-up] Annotation Processor doesn't detect errors in parameter constraints in inheritance hierarchies #584

Closed
wants to merge 13 commits into from

Conversation

gsmet
Copy link
Member

@gsmet gsmet commented Nov 22, 2016

Hi @marko-bekhta ,

So I did a couple of fixes and thought we might as well start with a clean review slate instead of having dozens of comments piling up.

This is all based on what you did. As you suspected it, the inheritance tree was what I had in mind. I fixed a couple of issues though, the most important one being that you ended the exploration when a superclass did not have the method, while you should also have explored the superclasses of this superclass.

I think we now have something working pretty well.

Sorry again about the delay, we had a few bad surprises with our upgrade in WildFly our it drained a lot of time and efforts.

Comments welcome!

--
Guillaume

collectOverriddenMethodsInInterfaces( overriddenMethod, interfaceTypeElement, methodInheritanceTreeBuilder );
}
else {
collectOverriddenMethodsInInterfaces( overridingMethod, interfaceTypeElement, methodInheritanceTreeBuilder );
Copy link
Member

Choose a reason for hiding this comment

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

it looks that collectOverriddenMethodsInInterfaces can be moved out of if else as it is called in both cases ?

Copy link
Member Author

Choose a reason for hiding this comment

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

There's a slight difference in the calls: one is using overriddenMethod and the other overridingMethod. I thought it was clearer this way than to declare another variable. Your question makes me think I might be wrong. WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

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

OK, I fixed it, it seems to be clearer now.

Copy link
Member

Choose a reason for hiding this comment

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

ahhaa ! when I was looking at it these two lines looked the same to me :)

if ( !element.getKind().equals( ElementKind.METHOD ) ) {
continue;
}
if ( elementUtils.overrides( currentMethod, (ExecutableElement) element, currentTypeElement ) ) {
if ( elementUtils.overrides( currentMethod, (ExecutableElement) element, getEnclosingTypeElement( currentMethod ) ) ) {
Copy link
Member

Choose a reason for hiding this comment

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

maybe get enclosing element before the loop ? or this operation is not very expensive ? Something like:

TypeElement methodEnclosingType = getEnclosingTypeElement( currentMethod );
for (...){
....
if ( elementUtils.overrides( currentMethod, (ExecutableElement) element, methodEnclosingType ) ) {

Copy link
Member Author

Choose a reason for hiding this comment

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

Right! I'll fix it, thanks for noticing.

* </p>
*
* @author Marko Bekhta
*/
public abstract class AbstractClassCheck implements ClassCheck {

@Override
public Collection<ConstraintCheckIssue> checkMethod(ExecutableElement element) {
public Set<ConstraintCheckIssue> checkMethod(ExecutableElement element) {
Copy link
Member

Choose a reason for hiding this comment

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

just out of interest - did you changed to Set to be more consistent with the existing checks or is there any other reasons ? I was thinking that if we are not using any Set specific behavior a more general collection interface can be used (that's just an explanation why I used Collection in the first place)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, it's just for the sake of consistency. I must admit I wouldn't have changed it if I didn't have other changes to do.

To be honest, if I had to do it from the ground up, I think I would have used ArrayList everywhere to have the result as predictable as possible. I don't think Sets are of much value here.

@marko-bekhta
Copy link
Member

hi @gsmet !

All looks great ! You definitely are much better at naming methods and variables :) and a great improvement to MethodInheritanceTree as well.

Also I can see that it seems like I still need to do some changes to my IDE formatting as there still are some differences :)

As for the delays - it's all fine and I completely understand it. I myself got stuck with my work and wasn't able to spent much time on HV related items :)

Have a nice day,
Marko

@gsmet
Copy link
Member Author

gsmet commented Nov 23, 2016

@marko-bekhta thanks for the review. I pushed a commit fixing your remarks. Is it better now? (I'll probably squash it before merging)

@marko-bekhta
Copy link
Member

@gsmet yes ! looks great !

Copy link
Member

@gunnarmorling gunnarmorling left a comment

Choose a reason for hiding this comment

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

@gsmet I looked mainly at the tests, not the impl so much. The expected behavior in the tests look right. Two comments inline.

);

assertEquals( diagnostics.getDiagnostics().get( 0 ).getMessage( Locale.getDefault() ),
"Parameters of method \"doSomething((@javax.validation.constraints.NotNull :: java.lang.String))\" do not respect the inheritance rules. " +
Copy link
Member

Choose a reason for hiding this comment

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

The error will be shown in the context of the method. Do we need to repeat the entire signature? Shouldn't the compiler itself point it out?

public static class MethodOverridingTestCase2Sub extends MethodOverridingTestCase2 {

@Override
public void doSomething(@NotNull @NotBlank @Size(max = 10) String param) {
Copy link
Member

Choose a reason for hiding this comment

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

Is there a strong need to check for this? Technically, it doesn't represent any constraint strengthening.

Copy link
Member Author

Choose a reason for hiding this comment

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

Well, it does not respect the inheritance rules we defined. The rule is that you cannot define constraints in the method hierarchy if there are already one method defining constraints in the method hierarchy. That's what we implemented here.

And it's definitely easier to throw an error for this than trying to determine what is or what is not a constraint strengthening.

Copy link
Member

Choose a reason for hiding this comment

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

At runtime, we'd allow that one. See OverridingMethodMustNotAlterParameterConstraints and how it's calling !method.isEquallyParameterConstrained(). That's primarily due to the behavior of Weld proxy classes though which would copy the annotations from proxied classes verbatim to the method definition on the proxy.

I'd prefer behavior of the AP to closely mimic the runtime engine, but if it's too cumbersome to do, we can leave as you've proposed it. It's in the sense of the spec for sure.

import org.hibernate.validator.ap.util.MessagerAdapter;

/**
* An abstract {@link javax.lang.model.element.ElementVisitor} that should be used for implementation
Copy link
Member

Choose a reason for hiding this comment

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

No biggie, but we can use simple names in JavaDocs (and import them), too. Reads a tad nicer.

@gsmet
Copy link
Member Author

gsmet commented Nov 30, 2016

@marko-bekhta ... and merged! Thanks for your tenacity on this subject, we finally got this in!

@gsmet gsmet closed this Nov 30, 2016
@marko-bekhta
Copy link
Member

@gsmet Great ! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants