-
Notifications
You must be signed in to change notification settings - Fork 0
Refactor JavaValidationRenderer
#185
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
Conversation
ae6d631
to
20dade9
Compare
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.
@yevhenii-nadtochii very dense PR, good job! However, in some places I think you went too far. Please see my comments.
// All the validation rules of a single message type. | ||
message MessageValidation { | ||
// A message compiled by the validation library with its constraints, if any. | ||
message CompiledMessage { |
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.
As long as in Spine there is a "Model Compiler" (which in turn heavily uses the Validation codegen capabilities), we cannot use CompiledMessage
, because it clashes with that domain. Until I saw the before-after in this changeset, I had no idea what a CompiledMessage
was. My only guess was that it was something describing the work of the Model Compiler routines completed for some particular Message
instance, more of an item in some audit log.
I agree that MessageValidation
isn't the best name. But still, what this declaration represents is by no means a result of a compilation process in that sense which we assume in Model Compiler. That's why it cannot be "compiled" (a participle, meaning "it's done"), It's rather an intermediate view of a "to-do" list for the next stages.
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.
Let's think of a better name. I will, too.
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 thought about CompiledMessage
as a message that is being compiled right now. It can also be CompilingMessage
, CompilationMessage
.
messageTypes | ||
.map { m -> m.message.javaFile(m.fileHeader) } | ||
.mapNotNull { path -> find(path) } | ||
.distinct() |
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.
Are you sure that the newly introduced distinct()
(line 98) is semantically equal to this whole block? I suspect there might be a subtle difference.
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.
Now, ProtoData combines calls of javaFile(header)
, find(path)
and unchecked cast to SourceFile<Java>
in a single SourceFileSet.javaFileOf()
method.
This new method throws when find(path)
returns null
(meaning no Java file). I have added if (!sources.hasJavaRoot) { return }
in the beginning of the renderer to avoid this.
@@ -126,7 +126,7 @@ internal class ValidationConstraintsCode private constructor( | |||
/** | |||
* Creates a new instance with the generated validation constraints code. | |||
*/ | |||
fun generate(r: JavaValidationRenderer, v: MessageValidation): ValidationConstraintsCode { | |||
fun generate(r: JavaValidationRenderer, v: CompiledMessage): ValidationConstraintsCode { |
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.
As a general comment: when renaming something, please check the corresponding variable names, too.
string error_message = 2; | ||
|
||
// `true` if the field is marked with `(required) = true`, `false` otherwise. | ||
bool required = 3; | ||
bool enabled = 3; |
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.
The field was called required
because it's written like that in the consumer code.
"Enabled" is about something else. "Whether the validation is enabled or not?"
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 is a bit weird both ways.
I suggest not create RequiredField
view for non-required fields at all. The same with the rest of such views. We do nothing when such a flag is false
because RequiredField
with required = false
is NonRequiredField
.
Having this bool something = false
flag in SomethingField
means this something field
is not something
.
@@ -11,17 +11,30 @@ option java_multiple_files = true; | |||
|
|||
import "spine/protodata/ast.proto"; | |||
|
|||
// Uniquely identifies a message field. |
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 would say it uniquely identifies a declaration of a field in some Message
.
It doesn't identify the field instance itself, as one might think reading this.
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 doesn't identify the field instance itself, as one might think reading this.
It does because it has both the parent type name and the field name.
// Name of the containing type. | ||
protodata.TypeName type = 1; | ||
|
||
// Short name of the field. |
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 think it's enough that we call the field name "short" in the declaration of the FieldName
itself.
string error_message = 2; | ||
|
||
// Value of `set_once` boolean option. | ||
// `true` if the field is marked with `(set_once) = true`, `false` otherwise. | ||
bool enabled = 3; |
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.
Basically, I would have this named set_once
for that same reason as above.
@@ -55,7 +55,7 @@ message MessageValidation { | |||
|
|||
// Validation rules. | |||
// | |||
// All these rules must be met in order for a message to be regarded as valid. |
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.
Why remove? The meaning is somewhat changed, don't you think?
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #185 +/- ##
============================================
+ Coverage 31.65% 32.16% +0.50%
Complexity 329 329
============================================
Files 142 141 -1
Lines 2818 2786 -32
Branches 229 227 -2
============================================
+ Hits 892 896 +4
+ Misses 1860 1824 -36
Partials 66 66 |
@armiol PTAL |
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.
@yevhenii-nadtochii LGTM with the respect of the comment.
@@ -11,17 +11,30 @@ option java_multiple_files = true; | |||
|
|||
import "spine/protodata/ast.proto"; | |||
|
|||
// Uniquely identifies a field declaration within the compilation messages. |
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 think this type addresses not only "compilation" messages. It's a part of AST, so I say we shouldn't be specific about "compilation" messages.
This PR refactors
JavaValidationRenderer
and suggests renaming ofMessageValidation
→CompilationMessage
. I need this change to proceed with the migration to PSI and simultaneous support of rules and standalone generators (as we complete the migration to the latter).Changes to
JavaValidationRenderer
:render()
method now. A significant part of this method is local comments, describing why all modifications of a message file cannot be done under a singleforEach
. I describe this inconsistency, but leave it "as is" because I'm going to migrate to PSI in the upcoming PRs.protected
modifier fromrender()
because it is unnecessary withoverride
, and makes the entry point a bit harder to locate.Other changes:
Validations
collection, we can easily go without this class. We already have many classes with "Validation" in their names. Takes time to differentiate their purposes.FieldId
up infield_views.proto
file.MessageValidation
toCompilationMessage
.3.1. This projection stores views for each message being compiled.
3.2. Having one or more constraints is optional. We always add
validate()
to all messages (and related stuff), which go through the library no matter if they have constraints or not.3.3. When we complete migration from
Rule
, this class will disappear completely. Each generator will query only a view of interest, likeRequiredFieldView
orDistinctFieldView
.3.4. Its usages talked more about a
compilationMessage
, and less as of aset of constraints
.3.5. This eliminates another class with "Validation" in its name.
Unrelated changes:
SetOnceValidationRenderer
. Both options are good enough, but the new one looks a bit better to me. AndJavaValidationRenderer
also usesallCompilationMessages
.