Skip to content

extend assignment_linter for other operators #928

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

Merged
merged 11 commits into from
Mar 13, 2022
Merged

Conversation

MichaelChirico
Copy link
Collaborator

Closes #915

@MichaelChirico
Copy link
Collaborator Author

@AshesITR PTAL at the test failure. Looks odd to me. For now I just removed the test.

At HEAD, assignment_linter() generates a lint with ranges=NULL:

dput(lintr::lint("a=1\n", lintr::assignment_linter()))
# structure(list(structure(list(filename = "<text>", line_number = 1L, 
#     column_number = 2L, type = "style", message = "Use <-, not =, for assignment.", 
#     line = c(`1` = "a=1"), ranges = NULL, linter = "lintr"), class = "lint")), class = "lints")

vs. in this PR it's ranges = list(c(2L, 2L))

dput(lintr::lint("a=1\n", lintr::assignment_linter()))
# structure(list(structure(list(filename = "<text>", line_number = 1L, 
#     column_number = 2L, type = "style", message = "Use <-, not =, for assignment.", 
#     line = c(`1` = "a=1"), ranges = list(c(2L, 2L)), linter = "lintr"), class = "lint")), class = "lints")

What's puzzling is the test is checking that exactly the new value of ranges isn't produced by assignment_linter():

expect_failure(expect_lint("a=1", list(ranges = list(c(2L, 2L))), linter))

So I'm second guessing if there's a reason for that? I can't think of any. And ranges will do well for printing the lint of -> (and <<- and ->>):

lintr::lint("a->1\n", lintr::assignment_linter())
# <text>:1:2: style: Use <-, not ->, for assignment.
# a->1
#  ^~

There's this comment in the original PR:

I found out that it was practically impossible to check the "ranges" of a lint using expect_lint().

expect_failure(expect_lint("a=1", list(ranges = list(c(2L, 2L))), linter))
expect_success(expect_lint("a=1", list(ranges = list(c(2L, 2L))), linter))
Copy link
Collaborator

Choose a reason for hiding this comment

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

What was the original failure?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Error: check #1: ranges NULL did not match list(c(2L, 2L))

Copy link
Collaborator

Choose a reason for hiding this comment

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

So that seems like a way of documenting the bug we just fixed 😆
Feel free to remove the test.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Despite not really knowing the purpose of the test I'm still a bit loath to remove it 😆

I changed it to use a different linter that gives NULL for ranges

@MichaelChirico
Copy link
Collaborator Author

ah poop. git is hard.

# always block = (NB: the parser differentiates EQ_ASSIGN, EQ_SUB, and EQ_FORMALS)
"//EQ_ASSIGN",
# -> and ->> are both 'RIGHT_ASSIGN'
if (!allow_right_assign) "//RIGHT_ASSIGN" else if (!allow_cascading_assign) "//RIGHT_ASSIGN[text() = '->>']",
# <-, :=, and <<- are all 'LEFT_ASSIGN'; check the text if blocking <<-
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't we lint := as well?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We'd have to write special logic to handle correct rlang and data.table usages. Don't think it's worth it (most people don't know that := can be used for "regular" assignment and it's explicitly not mentioned in the R documentation).

Copy link
Collaborator

Choose a reason for hiding this comment

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

Agreed. Maybe worth mentioning here why we chose not to lint :=?

@AshesITR
Copy link
Collaborator

Looks mostly good, just a few finishing touches needed.
Nice work!

NEWS.md Outdated
@@ -88,6 +88,7 @@ function calls. (#850, #851, @renkun-ken)
* `lintr` now uses the 3rd edition of `testthat` (@MichaelChirico, #910)
* `lintr` is adopting a new set of linters provided as part of Google's extension to the tidyverse style guide (#884, @michaelchirico)
+ `expect_null_linter()` Require usage of `expect_null(x)` over `expect_equal(x, NULL)` and similar
* `assignment_linter()` now blocks right assignment (`->` and `->>`) and gains two arguments. `allow_cascading_assign` (`TRUE` by default) toggles whether to block `<<-` and `->>`; `allow_right_assign` toggles whether to block `->` and `->>` (#915, @michaelchirico)
Copy link
Collaborator

Choose a reason for hiding this comment

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

block --> lint

# always block = (NB: the parser differentiates EQ_ASSIGN, EQ_SUB, and EQ_FORMALS)
"//EQ_ASSIGN",
# -> and ->> are both 'RIGHT_ASSIGN'
if (!allow_right_assign) "//RIGHT_ASSIGN" else if (!allow_cascading_assign) "//RIGHT_ASSIGN[text() = '->>']",
# <-, :=, and <<- are all 'LEFT_ASSIGN'; check the text if blocking <<-
Copy link
Collaborator

Choose a reason for hiding this comment

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

Agreed. Maybe worth mentioning here why we chose not to lint :=?

@MichaelChirico MichaelChirico merged commit 53b5f51 into master Mar 13, 2022
@MichaelChirico MichaelChirico deleted the assignment-right branch March 13, 2022 21:25
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.

Cover other assignment operators in assignment_linter
2 participants