-
Notifications
You must be signed in to change notification settings - Fork 21
Add preferredmarkers linter
#172
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
base: main
Are you sure you want to change the base?
Add preferredmarkers linter
#172
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: saschagrunert The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
8b3ad22 to
c13e1ee
Compare
Introduce a new configurable linter that enforces consistent marker usage across codebases by ensuring preferred marker identifiers are used instead of equivalent alternatives. Key Features: - Configurable marker preferences with multiple equivalent identifiers - Auto-fix support with expression preservation - Smart duplicate handling (consolidates multiple equivalents) - Type-aware checking (handles markers inherited from type aliases) - Deterministic output with sorted processing - Comprehensive configuration validation Signed-off-by: Sascha Grunert <sgrunert@redhat.com>
c13e1ee to
c004f0d
Compare
preferredmarkers linter
| - `+k8s:optional` | ||
| - `+kubebuilder:validation:Optional` |
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.
| - `+k8s:optional` | |
| - `+kubebuilder:validation:Optional` | |
| - `+optional` | |
| - `+k8s:optional` | |
| - `+kubebuilder:validation:Optional` |
| markers: | ||
| - preferredIdentifier: "custom:preferred" | ||
| equivalentIdentifiers: | ||
| - "custom:old:marker" |
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.
If I had a value for the marker, how would the value be translated? For example, if we switch from +kubebuilder:validation:MaxLength:=3 to +k8s:maxLength:=3, is that handled?
What about something more complex like XValidation that has multiple arguments?
Reading further on, these are preserved verbatim.
If in the future we wanted to remap, is the current config extensible in any way? Possibly not.
I'm expecting a future where (and this is somewhat OpenShift specific), we want to remap
+openshift:validation:featureGate=ABC --> +k8s:ifEnabled(FeatureGate=ABC)
Perhaps we want to make the equivalentIdentifiers a list of objects so that we can expand with a mapping option later?
| OptionalFieldKubebuilder string `json:"optionalFieldKubebuilder"` // want `field OptionalFieldKubebuilder uses marker "kubebuilder:validation:Optional", should use preferred marker "k8s:optional" instead` | ||
|
|
||
| // Inherited from type alias | ||
| OptionalFieldKubebuilderTypeAlias OptionalTypeKubebuilder `json:"optionalFieldKubebuilderTypeAlias"` // want `field OptionalFieldKubebuilderTypeAlias uses marker "kubebuilder:validation:Optional", should use preferred marker "k8s:optional" instead` |
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.
Given this will be reported at the type level, is it beneficial for it to be reported here again?
| Expect(errs).To(HaveLen(0), "No errors were expected") | ||
| } | ||
| }, | ||
| Entry("With a valid preferredmarkers configuration", testCase{ |
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.
Do we have a case that checks the preferred identifier is not in the list of equivalent identifiers? So we wouldn't create a loop of trying to replace an identifier with itself
| // Config is the configuration type | ||
| // for the preferredmarkers linter. | ||
| type Config struct { | ||
| // Markers is the unique set of preferred markers |
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.
We follow the conventions of lowercase first word on the godoc on these config types
| // Markers is the unique set of preferred markers | |
| // markers is the unique set of preferred markers |
| return | ||
| } | ||
|
|
||
| markerSet := utils.TypeAwareMarkerCollectionForField(pass, markersAccess, 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 suspect this is going to cause confusion since we are inspecting the types separately
|
|
||
| // Check for unnamed expression (simple case like "+marker:=value") | ||
| if unnamedValue, ok := expressions[markers.UnnamedExpression]; ok { | ||
| return ":=" + unnamedValue |
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 don't think := is universally compatible, just use =.
Kubebuilder supports :=, but to my knowledge, the +k8s markers do not
| // preferred identifier while preserving any expressions from the original | ||
| // marker. | ||
| func buildReplacementMarker(marker markers.Marker, preferredIdentifier string) string { | ||
| return "// +" + preferredIdentifier + formatExpressions(marker.Expressions) |
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.
@everettraven can you PTAL at this given your context with the DV parsing, is this likely to break/change?
|
|
||
| // Type at end of file without trailing newline | ||
| // +kubebuilder:validation:Optional | ||
| type EndOfFileType string // want `type EndOfFileType uses marker "kubebuilder:validation:Optional", should use preferred marker "k8s:optional" instead` No newline at end of file |
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.
Is this important to test? The change isn't actually at the end of the file, it's on line 4?
How did you come across this issue to want to test EOF?
Add a new linter that allows projects to enforce using preferred markers instead of equivalent but different marker identifiers.
The linter is disabled by default and requires explicit configuration to enable.
Fixes #139