Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

False positive in indentation_linter()? #1800

Closed
IndrajeetPatil opened this issue Dec 5, 2022 · 5 comments · Fixed by #1812
Closed

False positive in indentation_linter()? #1800

IndrajeetPatil opened this issue Dec 5, 2022 · 5 comments · Fixed by #1812
Labels
false-positive code that shouldn't lint, but does

Comments

@IndrajeetPatil
Copy link
Collaborator

Possibly related to r-lib/styler#1065.

library(lintr)

'test_that("bla", {
  x <-
    letters[1:3] %>%
    paste0() %>%
    length()
})' -> code

lint(
  text = code,
  linters = indentation_linter()
)
#> <text>:4:4: style: [indentation_linter] Indentation should be 6 spaces but is 4 spaces.
#>     paste0() %>%
#>    ^~~

Created on 2022-12-05 with reprex v2.0.2

This is what {lintr} expects:

test_that("bla", {
  x <-
    letters[1:3] %>%
      paste0() %>%
      length()
})

But {styler} changes this to the above-mentioned version that produces lints.

@AshesITR
Copy link
Collaborator

AshesITR commented Dec 5, 2022

The reason for this is that the indent triggered by <- reaches all the way to the end of the expression (i.e. upto length()) and the magrittr pipes (and base R pipes too) trigger indents for the following line due to left associativity:

"%t%" <- function(l, r) { list(l = l, r = r) }
1 %t% 2 %t% 3
#> $l
#> $l$l
#> [1] 1
#> 
#> $l$r
#> [1] 2
#> 
#> 
#> $r
#> [1] 3

Created on 2022-12-05 with reprex v2.0.2

Seems like a matter of taste if this syntactical difference between %% and <- should be reflected in the indentation.

To me, a trailing <- looks very odd anyway. I would suggest using

x <- letters[1:3] %>%
  paste0() %>%
  length()

instead.


I just checked PyCharms Auto-Indent and it agrees with lintr.

@IndrajeetPatil
Copy link
Collaborator Author

Thanks for the explanation.

Makes sense to not have a trailing <-, but note that the style guide specifically mentions this as an acceptable way of doing assignments in piped workflows:

Screenshot 2022-12-05 at 19 40 39

Why is this important?

The identation_linter() is part of the default set of linters, which means that anyone who is using this style of assignment will see lints from this linter. Add this to the fact that the new GHA workflow for linting produces errors if any lints are found.

This means that users are going to see build failures for writing tidyverse code in a style that the style guide explicitly says is acceptable. IMO, this is surprising and frustrating for the user.

We have a few options out of this quagmire:

  • support this style of assignment (i.e., no lint from identation_linter())
  • provide a parameter to identation_linter() to toggle on and off whether this assignment style should be linted
  • ask the style guide to be revised

@AshesITR
Copy link
Collaborator

AshesITR commented Dec 5, 2022

I think an optional argument (defaulting to tidyverse style) is in order.
The refactoring necessary for this isn't trivial, though :(

@AshesITR AshesITR added the false-positive code that shouldn't lint, but does label Dec 5, 2022
@IndrajeetPatil IndrajeetPatil added this to the 3.2.0 milestone Dec 5, 2022
@MichaelChirico
Copy link
Collaborator

Q is, is this worth demoting indentation_linter() out of defaults for the next release? e.g. marking it as "WIP" and "slated-for-default", or do we think it's already consistent enough with the style guide to be released as a default with some known edge case like this?

@AshesITR
Copy link
Collaborator

AshesITR commented Dec 8, 2022

I'd decide that based on how common the code style is that triggers the false-positive.
Also, not a lot to go on how exactly <- should suppress child indentations.
Surely, we still want these snippets to be considered "correct":

var <-
  function_call(
    arg1 +
      also_arg1,
    arg2
  )

Maybe only direct children infix tokens should be excluded?
That would be a fix that seems doable, so we ship 3.1.0 without the FP.


I've made a PR to fix this issue, so we can keep indentation_linter() in the defaults without worrying.
The XPath is a bit advanced, though. @MichaelChirico PTAL

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
false-positive code that shouldn't lint, but does
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants