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

Improve message for seq_linter() #1475

Merged
merged 7 commits into from
Jul 28, 2022
Merged

Conversation

IndrajeetPatil
Copy link
Collaborator

@IndrajeetPatil IndrajeetPatil commented Jul 26, 2022

Closes #1471

TODO:

  • Improve error message
  • Adapt tests
  • Refactor code (I am not sure if the nested ifelse() can be avoided)
library(lintr)

lint(
  text = "1:length(data.frame())",
  linters = seq_linter()
)
#> <text>:1:1: warning: [seq_linter] 1:length(...) is likely to be wrong in the empty edge case. Use seq_along(...) instead.
#> 1:length(data.frame())
#> ^~~~~~~~~~~~~~~~~~~~~~

lint(
  text = "seq(length(data.frame()))",
  linters = seq_linter()
)
#> <text>:1:1: warning: [seq_linter] seq(length(...)) is likely to be wrong in the empty edge case. Use seq_along(...) instead.
#> seq(length(data.frame()))
#> ^~~~~~~~~~~~~~~~~~~~~~~~~

lint(
  text = "1:nrow(data.frame())",
  linters = seq_linter()
)
#> <text>:1:1: warning: [seq_linter] 1:nrow(...) is likely to be wrong in the empty edge case. Use seq_len(nrow(...)) instead.
#> 1:nrow(data.frame())
#> ^~~~~~~~~~~~~~~~~~~~

lint(
  text = "seq(nrow(data.frame()))",
  linters = seq_linter()
)
#> <text>:1:1: warning: [seq_linter] seq(nrow(...)) is likely to be wrong in the empty edge case. Use seq_len(nrow(...)) instead.
#> seq(nrow(data.frame()))
#> ^~~~~~~~~~~~~~~~~~~~~~~

lint(
  text ="c(1:length(x), 1:nrow(y))",
  linters = seq_linter()
)
#> <text>:1:3: warning: [seq_linter] 1:length(...) is likely to be wrong in the empty edge case. Use seq_along(...) instead.
#> c(1:length(x), 1:nrow(y))
#>   ^~~~~~~~~~~
#> <text>:1:16: warning: [seq_linter] 1:nrow(...) is likely to be wrong in the empty edge case. Use seq_len(nrow(...)) instead.
#> c(1:length(x), 1:nrow(y))
#>                ^~~~~~~~~

Created on 2022-07-26 by the reprex package (v2.0.1)

@IndrajeetPatil

This comment was marked as outdated.

@IndrajeetPatil IndrajeetPatil marked this pull request as ready for review July 27, 2022 06:32
R/seq_linter.R Outdated
"%s:%s is likely to be wrong in the empty edge case. Use %s() instead.",
dot_expr1, dot_expr2, replacement
if (length(replacement) > 0L) {
lint_message <- ifelse(replacement == "seq_len",
Copy link
Collaborator

Choose a reason for hiding this comment

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

i think we can avoid the nested ifelse by setting dot_expr2 = "..." for the seq_along() branch:

dot_expr2[replacement == "seq_along"] <- "..."
lint_message <- ifelse(
  grepl("seq", dot_expr1, fixed = TRUE),
  ...
)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Tried this, but doesn't seem to work. 🤕

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Feel free to push into the PR if you can get it to work. Maybe I missed something.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Btw, this is the second time we have talked about avoiding nested ifelse().

I am wondering if we should introduce a new linter to cover such cases?
Providing a concrete alternative in lint message will be difficult, though.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I am wondering if we should introduce a new linter to cover such cases?

There's already lintr::nested_ifelse_linter(), it's just not a default linter

Providing a concrete alternative in lint message will be difficult, though.

There's no requirement to do so. The message can suggest alternatives but doesn't need to be concrete. That's one of the main differences vs. styler, in fact -- styler generally has to be a bit more conservative & shouldn't touch code unless there's a clear, specific improvement, whereas lintr can call out code that can be improved without doing the improvement.

Copy link
Collaborator

Choose a reason for hiding this comment

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

oh i see, i had missed that dot_expr2 was used twice. so introduced dot_expr3 instead

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

There's already lintr::nested_ifelse_linter(), it's just not a default linter

Oh, missed that completely! Good to know.

introduced dot_expr3 instead

Thanks for simplifying. Much more readable now!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Okay, I went through the docs and the code, but I don't see any explanation for why this is not a default linter.
I think it should be.

E.g., in a PR like the current, we wouldn't even have to rely on its usage being caught by manual code review; the linter GHA itself would notify the contributor about the added lint.

@MichaelChirico
Copy link
Collaborator

Great stuff! Agree on the message format. Looks way better.

@MichaelChirico MichaelChirico merged commit 8794907 into main Jul 28, 2022
@MichaelChirico MichaelChirico deleted the 1471_improve_seq_linter_message branch July 28, 2022 03:41
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.

Improve message for seq_linter()
2 participants