-
Notifications
You must be signed in to change notification settings - Fork 13
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 field and rule value to violations #215
Conversation
I'm going to try to pick up the violation accumulator change today if possible. Please feel free to review what's here though. Particularly interested if there's any way we can clean up the Violation API surface to be a bit nicer. |
I did a bit of refactorings:
This necessitated some reshuffling that may not be intuitive and I'm sure there's ugly things in here but I wanted to get this out in some shape before the weekend. |
@Nullable Value fieldValue; | ||
@Nullable Value ruleValue; | ||
|
||
public interface Violation { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it!!
* {@link ConstraintViolation} contains all of the collected information about an individual | ||
* constraint violation. | ||
*/ | ||
public class ConstraintViolation implements Violation { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is the pattern everything else uses -- public access but in an "internal" package.
It's a bit unfortunate that this uses Go idioms instead of Java ones, though I guess the Java idiom (using default/package-private access) would require dumping everything into one package, which is admittedly nasty in other ways...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, same feelings here. I don't love it exactly, but actually it seems like a lot of Java software winds up doing basically this sort of thing, since there's really not much flexibility w.r.t. visibility.
src/main/java/build/buf/protovalidate/internal/evaluator/EmbeddedMessageEvaluator.java
Outdated
Show resolved
Hide resolved
import java.util.List; | ||
import javax.annotation.Nullable; | ||
|
||
class EvaluatorBase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of extending this in every evaluator type, I think it would be better to use composition and maybe call it a ConstraintViolationHelper
-- since it's really just used to get values for building a violation.
There's a lot of places that now call super(evaluator)
that IMO don't look intuitive. Also, this doesn't provide any base Evaluator
method implementations so it is awkward as a base class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was going to try to extract more common functionality but it didn't work out so it's a bit pointless now. Now it's ConstraintViolationHelper
and not being used as a base class.
ConstraintViolation.Builder violation = | ||
ConstraintViolation.newBuilder() | ||
.addAllRulePathElements(getRulePrefixElements()) | ||
.addAllRulePathElements(IN_RULE_PATH.getElementsList()) | ||
.addFirstFieldPathElement(getFieldPathElement()) | ||
.setConstraintId("any.in") | ||
.setMessage("type URL must be in the allow list") | ||
.setFieldValue(new ConstraintViolation.FieldValue(val)) | ||
.setRuleValue(new ConstraintViolation.FieldValue(this.inValue, IN_DESCRIPTOR)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to try to wrap some of this up into a helper in EvaluatorBase
, to de-boiler-plate the various calls that do this.
It looks like they all call ConstraintViolation.newBuilder().addAllRulePathElements(getRulePrefixElements())
, but the other methods vary slightly. Many also call .addFirstFieldPathElement(getFieldPathElement())
, but some do not. Anyhow, maybe not worth looking into since they all seem to vary a little -- moving the builder pattern steps into method arguments would certainly make call sites more concise, but potentially at the cost of readability, so maybe not worth doing more here...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am leaning on the other direction (not having EvaluatorBase
) instead, since I'm on the side of this not being worth it, at least for now. It does feel like there's likely something more elegant to pull out of this, but with all of the edge cases we have right now it's not currently apparent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. One tiny nit, but not blocking if you disagree with it. If you do make the change, feel free to merge w/out further review.
@@ -34,7 +34,8 @@ | |||
* com.google.protobuf.Any}'s within an expression, breaking evaluation if the type is unknown at | |||
* runtime. | |||
*/ | |||
class AnyEvaluator extends EvaluatorBase implements Evaluator { | |||
class AnyEvaluator implements Evaluator { | |||
private final ConstraintViolationHelper constraintViolationHelper; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I would call the field helper
(here and throughout) to make the call sites more readable. They are so verbose, it's a bit of a chore to read or scan the code with this long name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I accidentally made my Java a little too Java. Fixed.
Adds the ability to access the captured rule and field value from a Violation.
There's a bit of refactoring toil, so I tried to split the commits cleanly to make this easier to review.
Violation
wrapper class and plumbs it through all uses ofViolation
.Value
non-internal so we can use it to expose protobuf values in a cleaner fashion.fieldValue
andruleValue
fields.This is a breaking change. The API changes in the following ways:
ValidationResult
now provides a new wrapperViolation
type instead of thebuf.validate.Violation
message. This new wrapper has agetProto()
method to return abuf.validate.Violation
message, andValidationResult
now has atoProto()
method to return abuf.validate.Violations
message.