Skip to content

expect_true_false_linter() is pipe-aware #2809

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
* `return_linter()` works on functions that happen to use braced expressions in their formals (#2616, @MichaelChirico).
* `object_name_linter()` and `object_length_linter()` account for S3 class correctly when the generic is assigned with `=` (#2507, @MichaelChirico).
* `assignment_linter()` with `operator = "="` does a better job of skipping implicit assignments, which are intended to be governed by `implicit_assignment_linter()` (#2765, @MichaelChirico).
* `expect_true_false_linter()` is pipe-aware, so that `42 |> expect_identical(x, ignore_attr = TRUE)` no longer lints (#1520, @MichaelChirico).
* `T_and_F_symbol_linter()` ignores `T` and `F` used as symbols in formulas (`y ~ T + F`), which can represent variables in data not controlled by the author (#2637, @MichaelChirico).

### Lint accuracy fixes: removing false negatives
Expand Down
10 changes: 7 additions & 3 deletions R/expect_true_false_linter.R
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,14 @@
#' @seealso [linters] for a complete list of linters available in lintr.
#' @export
expect_true_false_linter <- function() {
xpath <- "
following-sibling::expr[position() <= 2 and NUM_CONST[text() = 'TRUE' or text() = 'FALSE']]
pipe_cond <- glue("parent::expr/parent::expr[PIPE or SPECIAL[{xp_text_in_table(magrittr_pipes)}]]")
xpath <- glue("
following-sibling::expr[
NUM_CONST[text() = 'TRUE' or text() = 'FALSE']
and position() <= 2 - count({pipe_cond})
]
/parent::expr
"
")

Linter(linter_level = "expression", function(source_expression) {
xml_calls <- source_expression$xml_find_function_calls(c("expect_equal", "expect_identical"))
Expand Down
29 changes: 18 additions & 11 deletions tests/testthat/test-expect_true_false_linter.R
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
test_that("expect_true_false_linter skips allowed usages", {
linter <- expect_true_false_linter()
# expect_true is a scalar test; testing logical vectors with expect_equal is OK
expect_lint("expect_equal(x, c(TRUE, FALSE))", NULL, expect_true_false_linter())
expect_no_lint("expect_equal(x, c(TRUE, FALSE))", linter)

expect_no_lint("expect_equal(x, y, ignore_attr = TRUE)")

expect_no_lint("42 %>% expect_identical(42, ignore_attr = TRUE)", linter)
expect_no_lint("42 %>% expect_identical(42, TRUE)", linter)

skip_if_not_r_version("4.1.0")
expect_no_lint("42 |> expect_identical(42, ignore_attr = TRUE)", linter)
})

test_that("expect_true_false_linter blocks simple disallowed usages", {
linter <- expect_true_false_linter()
lint_msg <- rex::rex("expect_true(x) is better than expect_equal(x, TRUE)")

expect_lint(
"expect_equal(foo(x), TRUE)",
rex::rex("expect_true(x) is better than expect_equal(x, TRUE)"),
linter
)
expect_lint("expect_equal(foo(x), TRUE)", lint_msg, linter)

# expect_identical is treated the same as expect_equal
expect_lint(
Expand All @@ -20,11 +26,12 @@ test_that("expect_true_false_linter blocks simple disallowed usages", {
)

# also caught when TRUE/FALSE is the first argument
expect_lint(
"expect_equal(TRUE, foo(x))",
rex::rex("expect_true(x) is better than expect_equal(x, TRUE)"),
linter
)
expect_lint("expect_equal(TRUE, foo(x))", lint_msg, linter)

expect_lint("42 %T>% expect_equal(TRUE)", lint_msg, linter)

skip_if_not_r_version("4.1.0")
expect_lint("42 |> expect_equal(TRUE)", lint_msg, linter)
})

test_that("lints vectorize", {
Expand Down
Loading