File: T_and_F_symbol_linter.R

package info (click to toggle)
r-cran-lintr 3.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,396 kB
  • sloc: sh: 13; xml: 10; makefile: 2
file content (71 lines) | stat: -rw-r--r-- 2,224 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#' `T` and `F` symbol linter
#'
#' Although they can be synonyms, avoid the symbols `T` and `F`, and use `TRUE` and `FALSE`, respectively, instead.
#' `T` and `F` are not reserved keywords and can be assigned to any other values.
#'
#' @examples
#' # will produce lints
#' lint(
#'   text = "x <- T; y <- F",
#'   linters = T_and_F_symbol_linter()
#' )
#'
#' lint(
#'   text = "T = 1.2; F = 2.4",
#'   linters = T_and_F_symbol_linter()
#' )
#'
#' # okay
#' lint(
#'   text = "x <- c(TRUE, FALSE)",
#'   linters = T_and_F_symbol_linter()
#' )
#'
#' lint(
#'   text = "t = 1.2; f = 2.4",
#'   linters = T_and_F_symbol_linter()
#' )
#'
#' @evalRd rd_tags("T_and_F_symbol_linter")
#' @seealso
#' - [linters] for a complete list of linters available in lintr.
#' - <https://style.tidyverse.org/syntax.html#logical-vectors>
#' @export
T_and_F_symbol_linter <- function() { # nolint: object_name.
  symbol_xpath <- "//SYMBOL[
    (text() = 'T' or text() = 'F')
    and not(parent::expr[OP-DOLLAR or OP-AT])
  ]"
  assignment_xpath <-
    "parent::expr[following-sibling::LEFT_ASSIGN or preceding-sibling::RIGHT_ASSIGN or following-sibling::EQ_ASSIGN]"

  usage_xpath <- sprintf("%s[not(%s)]", symbol_xpath, assignment_xpath)
  assignment_xpath <- sprintf("%s[%s]", symbol_xpath, assignment_xpath)

  replacement_map <- c(T = "TRUE", F = "FALSE")

  Linter(linter_level = "expression", function(source_expression) {
    xml <- source_expression$xml_parsed_content

    bad_usage <- xml_find_all(xml, usage_xpath)
    bad_assignment <- xml_find_all(xml, assignment_xpath)

    make_lints <- function(expr, fmt) {
      symbol <- xml_text(expr)
      lint_message <- sprintf(fmt, replacement_map[symbol], symbol)
      xml_nodes_to_lints(
        xml = expr,
        source_expression = source_expression,
        lint_message = lint_message,
        type = "style",
        column_number_xpath = "number(./@col2 + 1)", # mark at end
        range_end_xpath = "number(./@col2 + 1)" # end after T/F for easy fixing
      )
    }

    c(
      make_lints(bad_usage, "Use %s instead of the symbol %s."),
      make_lints(bad_assignment, "Don't use %2$s as a variable name, as it can break code relying on %2$s being %1$s.")
    )
  })
}