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

Make scalar_in_linter() configurable #2574

Merged
merged 10 commits into from
May 21, 2024
Merged

Make scalar_in_linter() configurable #2574

merged 10 commits into from
May 21, 2024

Conversation

F-Noelle
Copy link
Contributor

Make scalar_in_linter configurable to allow projects to define additional %in% style functions like %notin%.

Make scalar_in_linter configurable to allow projects to define additional %in% style functions like %notin%.
@F-Noelle F-Noelle changed the title Update scalar_in_linter.R (#1) Update scalar_in_linter.R May 10, 2024
@MichaelChirico
Copy link
Collaborator

MichaelChirico commented May 10, 2024

Thanks for the PR & great suggestion! Please add a NEWS item & be sure to cite yourself!

I'm also tempted to say the default should be character(), there's no particular reason to make %chin% special. WDYT @AshesITR / @IndrajeetPatil, since that would be a breaking change (require downstream to supply %chin% if they need it)? I do see a handful of users:

https://github.com/search?q=%2Fscalar_in_linter%2F+-path%3ANEWS&type=code

* Incorporate review feedback

- Use glue in xpath,
- Add changes to NEWS
- Change default for scalar_in_linter
- Make lint msg more open ended if another %in% operator was linted
- Update tests to match new bahaviour
@F-Noelle
Copy link
Contributor Author

I also tried to make the lint message for %in% like operators a bit more generic and updated the tests accordingly.

NEWS.md Outdated
@@ -54,6 +54,7 @@
* `any_is_na_linter()` is extended to catch the unusual usage `NA %in% x` (#2113, @MichaelChirico).
* `make_linter_from_xpath()` errors up front when `lint_message` is missing (instead of delaying this error until the linter is used, #2541, @MichaelChirico).
* `paste_linter()` is extended to recommend using `paste()` instead of `paste0()` for simply aggregating a character vector with `collapse=`, i.e., when `sep=` is irrelevant (#1108, @MichaelChirico).
* `scalar_in_linter` is now configurable to allow other `%in%` like operators to be linted. `%chin%` is no longer linted by default. (@F-Noelle)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the default argument is NULL for this parameter, the second sentence is no longer needed here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The linter previously did lint the %chin% in its unconfigurable state. As this is no longer the case due to the default changing to NULL this is a notable change. If there is a better way to phrase that I am all ears.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The larger point of the change you are making is allowing to configure this linter. %chin% was just your use case, and the developers who are reading this NEWS item don't need to know that. For users of some other package, it would have been a different operator (say %nin%).

I personally don't use {data.table} much, so I wasn't even aware of this infix operator; as a result, this part of the NEWS item was confusing for me because I thought this was an operator in base that I didn't know about.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you might misunderstand something here. %chin% was never my use case. I know of {data.tables}, but never used it in any of my projects. I just through it would be easy to make this linter configurable to work with my use cases, hence the pull request.

Previously the linter in its unconfigurable form linted %in% and %chin%, nothing else. When I made the update I wanted to make it backwards compatible to its original use case, so I opted to make %chin% the default for the new parameter.

@MichaelChirico then suggested to demote %chin% from its special status making this PR a breaking change, which I am completely on board with. But having a breaking change is NEWS worthy in my opinion, because people might have relied on the old behaviour aka %chin% being linted.

As this is no longer the case I want to highlight that simple fact as part of the NEWS. Just because I don't rely on it doesn't mean that nobody else did. If there is a better way of phrasing this I am all ears.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have nothing more to add here over my previous reply.

I will let @MichaelChirico decide the best phrasing for this news item, if he thinks it merits being phrased differently.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do make a breaking change, the corresponding bullet should be in its own section to highlight the change more clearly.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @F-Noelle about the NEWS item, it looks good to me. Maybe we can emphasize better that it's a {data.table} operator.

@IndrajeetPatil see here, I'm not quite sure your point:

//SPECIAL[text() = '%in%' or text() = '%chin%']

  • On current main, x %chin% 'a' will lint
  • On this PR, x %chin% 'a' will only lint under scalar_in_linter("%chin%") or similar.

@IndrajeetPatil IndrajeetPatil changed the title Update scalar_in_linter.R Make scalar_in_linter() configurable May 11, 2024

expect_lint("x %in% 1", lint_in_msg, linter)
expect_lint("x %chin% 'a'", lint_chin_msg, linter)
expect_lint("x %notin% 1", lint_notin_msg, linter)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a negative test case (no lints) here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a test where I add negative test cases based on configuration and negative test cases for the additional in operators in general.

Is there by the way an expect_no_lint function? I would have expected a wrapper for expect_lint(content, NULL, ...).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea! #2580

NEWS.md Outdated
@@ -54,6 +54,7 @@
* `any_is_na_linter()` is extended to catch the unusual usage `NA %in% x` (#2113, @MichaelChirico).
* `make_linter_from_xpath()` errors up front when `lint_message` is missing (instead of delaying this error until the linter is used, #2541, @MichaelChirico).
* `paste_linter()` is extended to recommend using `paste()` instead of `paste0()` for simply aggregating a character vector with `collapse=`, i.e., when `sep=` is irrelevant (#1108, @MichaelChirico).
* `scalar_in_linter` is now configurable to allow other `%in%` like operators to be linted. `%chin%` is no longer linted by default. (@F-Noelle)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do make a breaking change, the corresponding bullet should be in its own section to highlight the change more clearly.

@AshesITR
Copy link
Collaborator

Thanks for the PR & great suggestion! Please add a NEWS item & be sure to cite yourself!

I'm also tempted to say the default should be character(), there's no particular reason to make %chin% special. WDYT @AshesITR / @IndrajeetPatil, since that would be a breaking change (require downstream to supply %chin% if they need it)? I do see a handful of users:

https://github.com/search?q=%2Fscalar_in_linter%2F+-path%3ANEWS&type=code

I would like to see a rough idea of the impact, using our branch comparison script for example. Slightly leaning towards a non-breaking change because false negatives (missing lints for %chin%) are generally hard to make out so lintr users basically have to read the news to find out they need to change their config.

@F-Noelle
Copy link
Contributor Author

Thanks for the PR & great suggestion! Please add a NEWS item & be sure to cite yourself!
I'm also tempted to say the default should be character(), there's no particular reason to make %chin% special. WDYT @AshesITR / @IndrajeetPatil, since that would be a breaking change (require downstream to supply %chin% if they need it)? I do see a handful of users:
https://github.com/search?q=%2Fscalar_in_linter%2F+-path%3ANEWS&type=code

I would like to see a rough idea of the impact, using our branch comparison script for example. Slightly leaning towards a non-breaking change because false negatives (missing lints for %chin%) are generally hard to make out so lintr users basically have to read the news to find out they need to change their config.

I mean we could make the "%chin%" the default for in_operators again and push the change of defaults to a later point. Essentially saying the current default is "%chin%" but it is planned to switch it to NULL in the future so please make this explicit in your defaults if you rely on this functionality.

NEWS.md Outdated Show resolved Hide resolved
NEWS.md Outdated
@@ -54,6 +54,7 @@
* `any_is_na_linter()` is extended to catch the unusual usage `NA %in% x` (#2113, @MichaelChirico).
* `make_linter_from_xpath()` errors up front when `lint_message` is missing (instead of delaying this error until the linter is used, #2541, @MichaelChirico).
* `paste_linter()` is extended to recommend using `paste()` instead of `paste0()` for simply aggregating a character vector with `collapse=`, i.e., when `sep=` is irrelevant (#1108, @MichaelChirico).
* `scalar_in_linter` is now configurable to allow other `%in%` like operators to be linted. The data.table operator `%chin%` is no longer linted by default; use `in_operators = "%chin%"` to continue linting it. (@F-Noelle)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, i'm having trouble making edits myself since this is made in your main branch, I think you need to create a dedicated branch for me to make edits.

all this to say -- could you please move this item to the "breaking changes" section at the top :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved

paste0("Use == to match length-1 scalars, not ", in_op, ". Note that == preserves NA where ", in_op, " does not.")
lint_msg <- glue(
"Use comparison operators (e.g. ==, !=, etc.) to match length-1 scalars instead of {in_op} ",
"as these operators preserve NA where {in_op} does not."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'm afraid we've over-corrected 😄

"as" implies that preserving NA is the reason for the lint. But that's not true... actually this is a somewhat ambiguous thing. Some authors might prefer this behavior and thus disfavor this linter -- hence we're highlighting this aspect as a tradeoff users should be aware of.

So let's go with

Use comparison operators... to match length-1 scalars instead of {in_op}. Note that comparison operators preserve NA where {in_op} does not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

F-Noelle and others added 2 commits May 21, 2024 08:43
Co-authored-by: Michael Chirico <michaelchirico4@gmail.com>
Copy link
Collaborator

@MichaelChirico MichaelChirico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks for your patience!

@MichaelChirico MichaelChirico merged commit e97be9b into r-lib:main May 21, 2024
20 checks passed
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.

None yet

4 participants