Skip to content
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

Add examples to documentation: Part-7 (q-s) #1674

Merged
merged 19 commits into from
Oct 11, 2022
Merged
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
8 changes: 2 additions & 6 deletions R/function_left_parentheses_linter.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,15 @@
#' )
#'
#' lint(
#' text = "if (TRUE) x else y",
#' linters = function_left_parentheses_linter()
#' )
#'
#' lint(
#' text = "foo <- function(x) (x + 1)",
#' linters = function_left_parentheses_linter()
#' )
#'
#' @evalRd rd_tags("function_left_parentheses_linter")
#' @seealso
#' [linters] for a complete list of linters available in lintr. \cr
#' <https://style.tidyverse.org/syntax.html#parentheses>
#' <https://style.tidyverse.org/syntax.html#parentheses> \cr
#' [spaces_left_parentheses_linter()]
#' @export
function_left_parentheses_linter <- function() { # nolint: object_length.
xpath <- "
Expand Down
27 changes: 27 additions & 0 deletions R/redundant_equals_linter.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,33 @@
#' can be done using prefixes (is, has, can, etc.). For example, `is_child`,
#' `has_parent_supervision`, `can_watch_horror_movie` clarify their logical
#' nature, while `child`, `parent_supervision`, `watch_horror_movie` don't.
#'
#' @examples
#' # will produce lints
#' lint(
#' text = "if (any(x == TRUE)) 1",
#' linters = redundant_equals_linter()
#' )
#'
#' lint(
#' text = "if (any(x != FALSE)) 0",
#' linters = redundant_equals_linter()
#' )
#'
#' # okay
#' lint(
#' text = "if (any(x)) 1",
#' linters = redundant_equals_linter()
#' )
#'
#' lint(
#' text = "if (!all(x)) 0",
#' linters = redundant_equals_linter()
#' )
#'
#' @evalRd rd_tags("redundant_equals_linter")
#' @seealso [linters] for a complete list of linters available in lintr. \cr
#' [outer_negation_linter()]
#' @export
redundant_equals_linter <- function() {
xpath <- paste0(
Expand Down
32 changes: 32 additions & 0 deletions R/redundant_ifelse_linter.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,38 @@
#' @param allow10 Logical, default `FALSE`. If `TRUE`, usage like
#' `ifelse(x, 1, 0)` is allowed, i.e., only usage like
#' `ifelse(x, TRUE, FALSE)` is linted.
#'
#' @examples
#' # will produce lints
#' lint(
#' text = "ifelse(x >= 2.5, TRUE, FALSE)",
#' linters = redundant_ifelse_linter()
#' )
#'
#' lint(
#' text = "ifelse(x < 2.5, 1L, 0L)",
#' linters = redundant_ifelse_linter()
#' )
#'
#' # okay
#' lint(
#' text = "x >= 2.5",
#' linters = redundant_ifelse_linter()
#' )
#'
#' # Note that this is just to show the strict equivalent of the example above;
#' # converting to integer is often unnecessary and the logical vector itself
#' # should suffice.
#' lint(
MichaelChirico marked this conversation as resolved.
Show resolved Hide resolved
#' text = "as.integer(x < 2.5)",
#' linters = redundant_ifelse_linter()
#' )
#'
#' lint(
#' text = "ifelse(x < 2.5, 1L, 0L)",
#' linters = redundant_ifelse_linter(allow10 = TRUE)
#' )
#'
#' @seealso [linters] for a complete list of linters available in lintr.
#' @export
redundant_ifelse_linter <- function(allow10 = FALSE) {
Expand Down
24 changes: 24 additions & 0 deletions R/regex_subset_linter.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,30 @@
#' to match the pattern on `levels(x)` and use that to subset instead.
#'
#' @evalRd rd_tags("regex_subset_linter")
#'
#' @examples
#' # will produce lints
#' lint(
#' text = "x[grep(pattern, x)]",
#' linters = regex_subset_linter()
#' )
#'
#' lint(
#' text = "x[stringr::str_which(x, pattern)]",
#' linters = regex_subset_linter()
#' )
#'
#' # okay
#' lint(
#' text = "grep(pattern, x, value = TRUE)",
#' linters = regex_subset_linter()
#' )
#'
#' lint(
#' text = "stringr::str_subset(x, pattern)",
#' linters = regex_subset_linter()
#' )
#'
#' @seealso [linters] for a complete list of linters available in lintr.
#' @export
regex_subset_linter <- function() {
Expand Down
48 changes: 48 additions & 0 deletions R/semicolon_linter.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,54 @@
#' semicolons (e.g. as in `x; y`, i.e., on the same line of code) are allowed.
#' @param allow_trailing Logical, default `FALSE`. If `TRUE`, "trailing"
#' semicolons (i.e., those that terminate lines of code) are allowed.
#'
#' @examples
#' # will produce lints
#' lint(
#' text = "a <- 1;",
#' linters = semicolon_linter()
#' )
#'
#' lint(
#' text = "a <- 1; b <- 1",
MichaelChirico marked this conversation as resolved.
Show resolved Hide resolved
#' linters = semicolon_linter()
#' )
#'
#' lint(
#' text = "function() { a <- 1; b <- 1 }",
#' linters = semicolon_linter()
#' )
#'
#' # okay
#' lint(
#' text = "a <- 1",
#' linters = semicolon_linter()
#' )
#'
#' lint(
#' text = "a <- 1;",
#' linters = semicolon_linter(allow_trailing = TRUE)
#' )
#'
#' code_lines <- "a <- 1\nb <- 1"
#' writeLines(code_lines)
#' lint(
#' text = code_lines,
#' linters = semicolon_linter()
#' )
#'
#' lint(
#' text = "a <- 1; b <- 1",
#' linters = semicolon_linter(allow_compound = TRUE)
#' )
#'
#' code_lines <- "function() { \n a <- 1\n b <- 1\n}"
#' writeLines(code_lines)
#' lint(
#' text = code_lines,
#' linters = semicolon_linter()
#' )
#'
#' @evalRd rd_tags("semicolon_linter")
#' @seealso
#' [linters] for a complete list of linters available in lintr. \cr
Expand Down
33 changes: 33 additions & 0 deletions R/seq_linter.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,39 @@
#' These often cause bugs when the right-hand side is zero.
#' It is safer to use [base::seq_len()] or [base::seq_along()] instead.
#'
#' @examples
#' # will produce lints
#' lint(
#' text = "seq(length(x))",
MichaelChirico marked this conversation as resolved.
Show resolved Hide resolved
#' linters = seq_linter()
#' )
#'
#' lint(
#' text = "1:nrow(x)",
#' linters = seq_linter()
#' )
#'
#' lint(
#' text = "dplyr::mutate(x, .id = 1:n())",
#' linters = seq_linter()
#' )
#'
#' # okay
#' lint(
#' text = "seq_along(x)",
#' linters = seq_linter()
#' )
#'
#' lint(
#' text = "seq_len(nrow(x))",
#' linters = seq_linter()
#' )
#'
#' lint(
#' text = "dplyr::mutate(x, .id = seq_len(n()))",
#' linters = seq_linter()
#' )
#'
#' @evalRd rd_tags("seq_linter")
#' @seealso [linters] for a complete list of linters available in lintr.
#' @export
Expand Down
30 changes: 29 additions & 1 deletion R/single_quotes_linter.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,41 @@
#'
#' Check that only double quotes are used to delimit string constants.
#'
#' @examples
#' # will produce lints
#' lint(
#' text = "c('a', 'b')",
MichaelChirico marked this conversation as resolved.
Show resolved Hide resolved
#' linters = single_quotes_linter()
#' )
#'
#' # okay
#' lint(
#' text = 'c("a", "b")',
#' linters = single_quotes_linter()
#' )
#'
#' code_lines <- "paste0(x, '\"this is fine\"')"
#' writeLines(code_lines)
#' lint(
#' text = code_lines,
#' linters = single_quotes_linter()
#' )
#'
#' @evalRd rd_tags("single_quotes_linter")
#' @seealso
#' [linters] for a complete list of linters available in lintr. \cr
#' <https://style.tidyverse.org/syntax.html#character-vectors>
#' @export
single_quotes_linter <- function() {
squote_regex <- rex(start, zero_or_one(character_class("rR")), single_quote, any_non_double_quotes, single_quote, end)
squote_regex <- rex(
start,
zero_or_one(character_class("rR")),
single_quote,
any_non_double_quotes,
single_quote,
end
)

Linter(function(source_expression) {
if (!is_lint_level(source_expression, "file")) {
return(list())
Expand Down
23 changes: 23 additions & 0 deletions R/spaces_inside_linter.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,29 @@
#' inside them, i.e., directly following an opening delimiter or directly
#' preceding a closing delimiter.
#'
#' @examples
#' # will produce lints
#' lint(
#' text = "c( TRUE, FALSE )",
#' linters = spaces_inside_linter()
#' )
#'
#' lint(
#' text = "x[ 1L ]",
#' linters = spaces_inside_linter()
#' )
#'
#' # okay
#' lint(
#' text = "c(TRUE, FALSE)",
#' linters = spaces_inside_linter()
#' )
#'
#' lint(
#' text = "x[1L]",
#' linters = spaces_inside_linter()
#' )
#'
#' @evalRd rd_tags("spaces_inside_linter")
#' @seealso
#' [linters] for a complete list of linters available in lintr. \cr
Expand Down
16 changes: 15 additions & 1 deletion R/spaces_left_parentheses_linter.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,24 @@
#'
#' Check that all left parentheses have a space before them unless they are in a function call.
#'
#' @examples
#' # will produce lints
#' lint(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in an earlier linter (function_left_parentheses_linter? is that the name?) we showed if/function signature examples, should we do the reverse here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean by "reverse" here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Complementary examples to these:

#' # okay
#' lint(
#' text = "mean(x)",
#' linters = function_left_parentheses_linter()
#' )
#'
#' lint(
#' text = "stats::sd(c(x, y, z))",
#' linters = function_left_parentheses_linter()
#' )
#'
#' lint(
#' text = "if (TRUE) x else y",
#' linters = function_left_parentheses_linter()
#' )
#'
#' lint(
#' text = "foo <- function(x) (x + 1)",
#' linters = function_left_parentheses_linter()
#' )

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So including the okay examples but with a space to show that this doesn't lint with spaces_left linter?

library(lintr)

lint(
  text = "mean (x)",
  linters = spaces_left_parentheses_linter()
)

lint(
  text =  "stats::sd (c (x, y, z))",
  linters = spaces_left_parentheses_linter()
)

lint(
  text =  "if (TRUE) x else y",
  linters = spaces_left_parentheses_linter()
)

lint(
  text =  "foo <- function (x) (x + 1)",
  linters = spaces_left_parentheses_linter()
)

Created on 2022-10-11 with reprex v2.0.2

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, now I'm doubting everything :)

I definitely don't think examples like mean (x) are helpful... but maybe the better thing to do is just remove the if() example from function_left_parentheses_linter()? Since if() is irrelevant to that linter, and is covered here instead.

And then add cross-links between these two linters' help pages since they're so closely related.

WDYT?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM. I have made the necessary changes. See if this is better.

#' text = "if(TRUE) x else y",
#' linters = spaces_left_parentheses_linter()
#' )
#'
#' # okay
#' lint(
#' text = "if (TRUE) x else y",
#' linters = spaces_left_parentheses_linter()
#' )
#'
#' @evalRd rd_tags("spaces_left_parentheses_linter")
#' @seealso
#' [linters] for a complete list of linters available in lintr. \cr
#' <https://style.tidyverse.org/syntax.html#parentheses>
#' <https://style.tidyverse.org/syntax.html#parentheses> \cr
#' [function_left_parentheses_linter()]
#' @export
spaces_left_parentheses_linter <- function() {
file_level_xpath <- "//OP-LEFT-PAREN[@start - 1 = ancestor::expr/preceding-sibling::OP-SEMICOLON/@end]"
Expand Down
22 changes: 20 additions & 2 deletions R/sprintf_linter.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
#' Require correct `sprintf()` calls
#'
#' Check for an inconsistent number of arguments or arguments with incompatible types (for literal arguments) in
#' `sprintf()` calls.
#' Check for an inconsistent number of arguments or arguments with incompatible types
#' (for literal arguments) in `sprintf()` calls.
#'
#' @examples
#' # will produce lints
#' lint(
#' text = "sprintf('hello %s %s %d', x, y)",
#' linters = sprintf_linter()
#' )
#'
#' # okay
#' lint(
#' text = "sprintf('hello %s %s %d', x, y, z)",
#' linters = sprintf_linter()
#' )
#'
#' lint(
#' text = "sprintf('hello %s %s %d', x, y, ...)",
#' linters = sprintf_linter()
#' )
#'
#' @evalRd rd_tags("sprintf_linter")
#' @seealso [linters] for a complete list of linters available in lintr.
Expand Down
31 changes: 31 additions & 0 deletions R/string_boundary_linter.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,37 @@
#' are ignored. Some authors may prefer the conciseness offered by `grepl()` whereby
#' `NA` input maps to `FALSE` output, which doesn't have a direct equivalent
#' with `startsWith()` or `endsWith()`.
#'
#' @examples
#' # will produce lints
#' lint(
#' text = 'grepl("^a", x)',
#' linters = string_boundary_linter()
#' )
#'
#' lint(
#' text = 'grepl("z$", x)',
#' linters = string_boundary_linter()
#' )
#'
#' # okay
#' lint(
#' text = 'startsWith(x, "a")',
#' linters = string_boundary_linter()
#' )
#'
#' lint(
#' text = 'endsWith(x, "z")',
#' linters = string_boundary_linter()
#' )
#'
#' # If missing values are present, the suggested alternative wouldn't be strictly
#' # equivalent, so this linter can also be turned off in such cases.
#' lint(
#' text = 'grepl("z$", x)',
MichaelChirico marked this conversation as resolved.
Show resolved Hide resolved
#' linters = string_boundary_linter(allow_grepl = TRUE)
#' )
#'
#' @evalRd rd_tags("string_boundary_linter")
#' @seealso [linters] for a complete list of linters available in lintr.
#' @export
Expand Down
Loading