Skip to content

Commit a6ac90b

Browse files
authored
feat: argument to disable linting of ( for auto-printing (#2962)
* feat: argument to disable linting of ( for auto-printing closes #2916 supersedes #2919 * update NEWS * tweak argument description
1 parent 65229d8 commit a6ac90b

File tree

4 files changed

+52
-2
lines changed

4 files changed

+52
-2
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
* `sprintf_linter()` lints `sprintf()` and `gettextf()` calls when a constant string is passed to `fmt` (#2894, @Bisaloo).
5151
* `use_lintr()` adds the created `.lintr` file to the `.Rbuildignore` if run in a package (#2926, initial work by @MEO265, finalized by @Bisaloo).
5252
* `length_test_linter()` is extended to check incorrect usage of `nrow()`, `ncol()`, `NROW()`, `NCOL()` (#2933, @mcol).
53+
* `implicit_assignment_linter()` gains argument `allow_paren_print` to disable lints for the use of `(` for auto-printing (#2962, @TimTaylor).
5354

5455
### New linters
5556

R/implicit_assignment_linter.R

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#' @param allow_scoped Logical, default `FALSE`. If `TRUE`, "scoped assignments",
1010
#' where the object is assigned in the statement beginning a branch and used only
1111
#' within that branch, are skipped.
12+
#' @param allow_paren_print Logical, default `FALSE`. If `TRUE`, assignments using
13+
#' `(` for auto-printing at the top-level are not linted.
1214
#'
1315
#' @examples
1416
#' # will produce lints
@@ -22,6 +24,12 @@
2224
#' linters = implicit_assignment_linter()
2325
#' )
2426
#'
27+
#' lint(
28+
#' text = "(x <- 1)",
29+
#' linters = implicit_assignment_linter()
30+
#' )
31+
#'
32+
#'
2533
#' # okay
2634
#' lines <- "x <- 1L\nif (x) TRUE"
2735
#' writeLines(lines)
@@ -53,6 +61,11 @@
5361
#' linters = implicit_assignment_linter(allow_scoped = TRUE)
5462
#' )
5563
#'
64+
#' lint(
65+
#' text = "(x <- 1)",
66+
#' linters = implicit_assignment_linter(allow_paren_print = TRUE)
67+
#' )
68+
#'
5669
#' @evalRd rd_tags("implicit_assignment_linter")
5770
#' @seealso
5871
#' - [linters] for a complete list of linters available in lintr.
@@ -61,7 +74,8 @@
6174
#' @export
6275
implicit_assignment_linter <- function(except = c("bquote", "expression", "expr", "quo", "quos", "quote"),
6376
allow_lazy = FALSE,
64-
allow_scoped = FALSE) {
77+
allow_scoped = FALSE,
78+
allow_paren_print = FALSE) {
6579
stopifnot(is.null(except) || is.character(except))
6680

6781
if (length(except) > 0L) {
@@ -116,6 +130,9 @@ implicit_assignment_linter <- function(except = c("bquote", "expression", "expr"
116130
bad_expr <- xml_find_all(xml, xpath)
117131

118132
print_only <- !is.na(xml_find_first(bad_expr, "parent::expr[parent::exprlist and *[1][self::OP-LEFT-PAREN]]"))
133+
if (allow_paren_print) {
134+
bad_expr <- bad_expr[!print_only]
135+
}
119136

120137
xml_nodes_to_lints(
121138
bad_expr,

man/implicit_assignment_linter.Rd

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-implicit_assignment_linter.R

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,3 +476,20 @@ test_that("call-less '(' mentions avoiding implicit printing", {
476476
linter
477477
)
478478
})
479+
480+
test_that("allow_paren_print allows `(` for auto printing", {
481+
lint_message <- rex::rex("Avoid implicit assignments in function calls.")
482+
linter <- implicit_assignment_linter(allow_paren_print = TRUE)
483+
expect_no_lint("(a <- foo())", linter)
484+
485+
# Doesn't effect other cases
486+
lint_message <- rex::rex("Avoid implicit assignments in function calls.")
487+
expect_lint("if (x <- 1L) TRUE", lint_message, linter)
488+
expect_lint("while (x <- 0L) FALSE", lint_message, linter)
489+
expect_lint("for (x in 1:10 -> y) print(x)", lint_message, linter)
490+
expect_lint("mean(x <- 1:4)", lint_message, linter)
491+
492+
# default remains as is
493+
print_msg <- rex::rex("Call print() explicitly instead of relying on implicit printing behavior via '('.")
494+
expect_lint("(a <- foo())", print_msg, implicit_assignment_linter())
495+
})

0 commit comments

Comments
 (0)