-
Notifications
You must be signed in to change notification settings - Fork 187
New rep_len_linter #2286
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
New rep_len_linter #2286
Changes from 4 commits
2d9329e
a09d45b
91175a4
7bbc78d
56bad45
33af970
7ea44e5
b67ed49
e306379
a54eef2
491289e
83f3450
f1634ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#' Require usage of rep_len(x, n) over rep(x, length.out = n) | ||
#' | ||
#' `rep(x, length.out = n)` calls `rep_len(x, n)` "under the hood". The latter | ||
#' is thus more direct and equally readable. | ||
#' | ||
#' @examples | ||
#' # will produce lints | ||
#' lint( | ||
#' text = "rep(1:3, length.out = 10)", | ||
#' linters = rep_len_linter() | ||
#' ) | ||
#' | ||
#' # okay | ||
#' lint( | ||
#' text = "rep(1:3, each = 2L, length.out = 10L)", | ||
IndrajeetPatil marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#' linters = rep_len_linter() | ||
#' ) | ||
#' | ||
#' @evalRd rd_tags("rep_len_linter") | ||
#' @seealso [linters] for a complete list of linters available in lintr. | ||
#' @export | ||
rep_len_linter <- make_linter_from_xpath( | ||
# count(expr) is for cases using positional matching; see ?rep. | ||
xpath = " | ||
//SYMBOL_FUNCTION_CALL[text() = 'rep'] | ||
/parent::expr | ||
/parent::expr[ | ||
( | ||
SYMBOL_SUB[text() = 'length.out'] | ||
or (not(SYMBOL_SUB) and count(expr) = 4) | ||
) | ||
and not(SYMBOL_SUB[text() = 'each'] or count(expr) = 5) | ||
] | ||
", | ||
lint_message = "Use rep_len(x, n) instead of rep(x, length.out = n)." | ||
) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
test_that("rep_len_linter skips allowed usages", { | ||
linter <- rep_len_linter() | ||
|
||
# only catch length.out usages | ||
expect_lint("rep(x, y)", NULL, linter) | ||
expect_lint("rep(1:10, 2)", NULL, linter) | ||
expect_lint("rep(1:10, 10:1)", NULL, linter) | ||
|
||
# usage of each is not compatible with rep_len; see ?rep. | ||
expect_lint("rep(x, each = 4, length.out = 50)", NULL, linter) | ||
# each is implicitly the 4th positional argument. a very strange usage | ||
# (because length.out is ignored), but doesn't hurt to catch it | ||
expect_lint("rep(a, b, length.out = c, d)", NULL, linter) | ||
# ditto for implicit length.out= | ||
expect_lint("rep(a, b, c, d)", NULL, linter) | ||
}) | ||
|
||
test_that("rep_len_linter blocks simple disallowed usages", { | ||
linter <- rep_len_linter() | ||
lint_msg <- rex::rex("Use rep_len(x, n) instead of rep(x, length.out = n).") | ||
|
||
# only catch length.out usages | ||
expect_lint("rep(x, length.out = 4L)", lint_msg, linter) | ||
|
||
# implicit times= argument; length.out has priority over times= (see ?rep), | ||
# so we still lint since it's as if times= is not supplied. | ||
# (notice here that the base behavior is odd -- one might expect output like | ||
# head(rep(1:10, 10:1), 50), but instead we get rep(1:10, length.out = 50)) | ||
expect_lint("rep(1:10, 10:1, length.out = 50)", lint_msg, linter) | ||
|
||
# ditto for explicit times= argument | ||
expect_lint("rep(1:10, times = 10:1, length.out = 50)", lint_msg, linter) | ||
|
||
# implicit usage in third argument | ||
expect_lint("rep(1:10, 10:1, 50)", lint_msg, linter) | ||
}) |
Uh oh!
There was an error while loading. Please reload this page.