-
Notifications
You must be signed in to change notification settings - Fork 385
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
rule: unset attribute if src is nil and no keep annotation in dst when merge #1993
base: master
Are you sure you want to change the base?
Conversation
rule/merge.go
Outdated
return true | ||
} | ||
default: | ||
fmt.Printf("unexpected expression type %T\n", e) |
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.
Since we walk expressions recursively, wouldn't we always hit this eventually if there is no keep comment? Can we avoid recursing so deeply and e.g. only do it once?
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.
oops, this was for debugging. Let me get rid of it.
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.
True, but I find it somewhat difficult to fix with a single keep comment check.
For example, when merging nil
to a list with a single element marked as # keep
. The merging logic should be handled by ListExpr.Merge
. However, given the way the Merger
interface is designed, it's src
's responsibility to merge dst
. A plain nil
doesn't implement Merger
, but relies on the heuristic of mergeAttrValues
to figure that out.
And this won't work on complicated value types either, say some variant of PlatformList. As dst
is always being parsed as CallExpr
, it's src
's responsibility to convert that to the actual type to merge.
My approach is basically to leave that attribute value alone if src wants to remove it and there is a # keep
inside. Which will defer the merge issue to the user. (and it doesn't break established behavior based on the unit tests.)
Alternatively, or to say the ultimate solution, would be to rewrite rule API, to make it work like json/v2
that allows plugin writers to use actual go type in some rule structures, and let reflection do its magic while preserving relevant AST properties (spacing/comments etc.) So that when the merge happens, we can consult the typing info from the struct directly instead of guessing in a heuristic way.
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.
Makes sense, thanks for the explanation!
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.
Could you add a test case with glob
that demonstrates why this change is needed?
What type of PR is this?
Bug fix
What package or component does this PR mostly affect?
all
What does this PR do? Why is it needed?
This change will allow merging a non-existing attribute to any dst attribute not annotated with
# keep
.The current merge logic requires the dst attribute to be a scaler to unset, which prevents Gazelle from removing an attribute using
glob()
.Which issues(s) does this PR fix?
Fixes #1989