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

rule: unset attribute if src is nil and no keep annotation in dst when merge #1993

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

ashi009
Copy link
Contributor

@ashi009 ashi009 commented Dec 10, 2024

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

rule/merge.go Outdated
return true
}
default:
fmt.Printf("unexpected expression type %T\n", e)
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Member

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!

Copy link
Member

@fmeum fmeum left a 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?

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

Successfully merging this pull request may close these issues.

Can't unset an attr with GlobValue during merge
2 participants