|
7 | 7 | #'
|
8 | 8 | #' Similar reasoning applies to `&&` usage inside [stopifnot()] and `assertthat::assert_that()` calls.
|
9 | 9 | #'
|
10 |
| -#' Relatedly, `dplyr::filter(DF, A & B)` is the same as `dplyr::filter(DF, A, B)`, but the |
11 |
| -#' latter will be more readable / easier to format for long conditions. Note that this linter |
12 |
| -#' assumes usages of `filter()` are `dplyr::filter()`; if you're using another function named `filter()`, |
13 |
| -#' e.g. [stats::filter()], please namespace-qualify it to avoid false positives. |
| 10 | +#' Relatedly, `dplyr::filter(DF, A & B)` is the same as `dplyr::filter(DF, A, B)`, but the latter will be more readable |
| 11 | +#' / easier to format for long conditions. Note that this linter assumes usages of `filter()` are `dplyr::filter()`; |
| 12 | +#' if you're using another function named `filter()`, e.g. [stats::filter()], please namespace-qualify it to avoid |
| 13 | +#' false positives. You can omit linting `filter()` expressions altogether via `allow_filter = TRUE`. |
14 | 14 | #'
|
15 | 15 | #' @param allow_named_stopifnot Logical, `TRUE` by default. If `FALSE`, "named" calls to `stopifnot()`,
|
16 | 16 | #' available since R 4.0.0 to provide helpful messages for test failures, are also linted.
|
| 17 | +#' @param allow_filter Logical, `FALSE` by default. If `TRUE`, `filter()` expressions are not linted. |
17 | 18 | #'
|
18 | 19 | #' @examples
|
19 | 20 | #' # will produce lints
|
|
32 | 33 | #' linters = conjunct_test_linter(allow_named_stopifnot = FALSE)
|
33 | 34 | #' )
|
34 | 35 | #'
|
| 36 | +#' lint( |
| 37 | +#' text = "dplyr::filter(mtcars, mpg > 20 & vs == 0)", |
| 38 | +#' linters = conjunct_test_linter() |
| 39 | +#' ) |
| 40 | +#' |
35 | 41 | #' # okay
|
36 | 42 | #' lint(
|
37 | 43 | #' text = "expect_true(x || (y && z))",
|
|
43 | 49 | #' linters = conjunct_test_linter(allow_named_stopifnot = TRUE)
|
44 | 50 | #' )
|
45 | 51 | #'
|
| 52 | +#' lint( |
| 53 | +#' text = "dplyr::filter(mtcars, mpg > 20 & vs == 0)", |
| 54 | +#' linters = conjunct_test_linter(allow_filter = TRUE) |
| 55 | +#' ) |
| 56 | +#' |
46 | 57 | #' @evalRd rd_tags("conjunct_test_linter")
|
47 | 58 | #' @seealso [linters] for a complete list of linters available in lintr.
|
48 | 59 | #' @export
|
49 |
| -conjunct_test_linter <- function(allow_named_stopifnot = TRUE) { |
| 60 | +conjunct_test_linter <- function(allow_named_stopifnot = TRUE, |
| 61 | + allow_filter = FALSE) { |
50 | 62 | expect_true_assert_that_xpath <- "
|
51 | 63 | //SYMBOL_FUNCTION_CALL[text() = 'expect_true' or text() = 'assert_that']
|
52 | 64 | /parent::expr
|
@@ -103,22 +115,26 @@ conjunct_test_linter <- function(allow_named_stopifnot = TRUE) {
|
103 | 115 | sprintf(as.character(replacement_fmt), matched_fun),
|
104 | 116 | "The latter will produce better error messages in the case of failure."
|
105 | 117 | )
|
106 |
| - test_lints <- xml_nodes_to_lints( |
| 118 | + lints <- xml_nodes_to_lints( |
107 | 119 | test_expr,
|
108 | 120 | source_expression = source_expression,
|
109 | 121 | lint_message = lint_message,
|
110 | 122 | type = "warning"
|
111 | 123 | )
|
112 | 124 |
|
113 |
| - filter_expr <- xml_find_all(xml, filter_xpath) |
| 125 | + if (!allow_filter) { |
| 126 | + filter_expr <- xml_find_all(xml, filter_xpath) |
114 | 127 |
|
115 |
| - filter_lints <- xml_nodes_to_lints( |
116 |
| - filter_expr, |
117 |
| - source_expression = source_expression, |
118 |
| - lint_message = "Use dplyr::filter(DF, A, B) instead of dplyr::filter(DF, A & B).", |
119 |
| - type = "warning" |
120 |
| - ) |
| 128 | + filter_lints <- xml_nodes_to_lints( |
| 129 | + filter_expr, |
| 130 | + source_expression = source_expression, |
| 131 | + lint_message = "Use dplyr::filter(DF, A, B) instead of dplyr::filter(DF, A & B).", |
| 132 | + type = "warning" |
| 133 | + ) |
| 134 | + |
| 135 | + lints <- c(lints, filter_lints) |
| 136 | + } |
121 | 137 |
|
122 |
| - c(test_lints, filter_lints) |
| 138 | + lints |
123 | 139 | })
|
124 | 140 | }
|
0 commit comments