-
Notifications
You must be signed in to change notification settings - Fork 186
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* New for_loop_index_linter * add examples
- Loading branch information
1 parent
a6254c2
commit 51b2ae5
Showing
11 changed files
with
133 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#' Block usage of for loops directly overwriting the indexing variable | ||
#' | ||
#' `for (x in x)` is a poor choice of indexing variable. This overwrites | ||
#' `x` in the calling scope and is confusing to read. | ||
#' | ||
#' @examples | ||
#' # will produce lints | ||
#' lint( | ||
#' text = "for (x in x) { TRUE }", | ||
#' linters = for_loop_index_linter() | ||
#' ) | ||
#' | ||
#' lint( | ||
#' text = "for (x in foo(x, y)) { TRUE }", | ||
#' linters = for_loop_index_linter() | ||
#' ) | ||
#' | ||
#' # okay | ||
#' lint( | ||
#' text = "for (xi in x) { TRUE }", | ||
#' linters = for_loop_index_linter() | ||
#' ) | ||
#' | ||
#' lint( | ||
#' text = "for (col in DF$col) { TRUE }", | ||
#' linters = for_loop_index_linter() | ||
#' ) | ||
#' | ||
#' @evalRd rd_tags("for_loop_index_linter") | ||
#' @seealso [linters] for a complete list of linters available in lintr. | ||
#' @export | ||
for_loop_index_linter <- function() { | ||
xpath <- " | ||
//forcond | ||
/SYMBOL[text() = | ||
following-sibling::expr | ||
//SYMBOL[not( | ||
preceding-sibling::OP-DOLLAR | ||
or parent::expr[preceding-sibling::OP-LEFT-BRACKET] | ||
)] | ||
/text() | ||
] | ||
" | ||
|
||
Linter(function(source_expression) { | ||
if (!is_lint_level(source_expression, "expression")) { | ||
return(list()) | ||
} | ||
|
||
xml <- source_expression$xml_parsed_content | ||
|
||
bad_expr <- xml2::xml_find_all(xml, xpath) | ||
|
||
xml_nodes_to_lints( | ||
bad_expr, | ||
source_expression = source_expression, | ||
lint_message = "Don't re-use any sequence symbols as the index symbol in a for loop.", | ||
type = "warning" | ||
) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
test_that("for_loop_index_linter skips allowed usages", { | ||
expect_lint("for (xi in x) {}", NULL, for_loop_index_linter()) | ||
|
||
# this is OK, so not every symbol is problematic | ||
expect_lint("for (col in DF$col) {}", NULL, for_loop_index_linter()) | ||
expect_lint("for (col in DT[, col]) {}", NULL, for_loop_index_linter()) | ||
}) | ||
|
||
test_that("for_loop_index_linter blocks simple disallowed usages", { | ||
linter <- for_loop_index_linter() | ||
lint_msg <- "Don't re-use any sequence symbols as the index symbol in a for loop" | ||
|
||
expect_lint("for (x in x) {}", lint_msg, linter) | ||
# these also overwrite a variable in calling scope | ||
expect_lint("for (x in foo(x)) {}", lint_msg, linter) | ||
# arbitrary nesting | ||
expect_lint("for (x in foo(bar(y, baz(2, x)))) {}", lint_msg, linter) | ||
}) |