diff --git a/R/my_linters.R b/R/my_linters.R index f9d87b6..ec1299b 100644 --- a/R/my_linters.R +++ b/R/my_linters.R @@ -1,74 +1,3 @@ - -#' @importFrom lintr Lint - -#' Find dangerous 1:x expressions -#' -#' Find occurrences of \code{1:length(x)}, \code{1:nrow(x)}, -#' \code{1:ncol(x)}, \code{1:NROW(x)}, \code{1:NCOL(x)} where -#' \code{x} is an R expression. -#' -#' @return Lint object. -#' -#' @importFrom xmlparsedata xml_parse_data -#' @importFrom xml2 read_xml xml_find_all xml_text xml_children xml_attr -#' @keywords internal - -seq_linter <- function() lintr::Linter(function(source_file) { - - if (!length(source_file$parsed_content)) return(list()) - - xml <- if ('xml_parsed_content' %in% names(source_file)) { - source_file$xml_parsed_content - } else { - read_xml(xml_parse_data(source_file$parsed_content)) - } - - bad_funcs <- c("length", "nrow", "ncol", "NROW", "NCOL") - text_clause <- paste0("text() = '", bad_funcs, "'", collapse = " or ") - - xpath <- paste0( - "//expr", - "[expr[NUM_CONST[text()='1' or text()='1L']]]", - "[OP-COLON]", - "[expr[expr[SYMBOL_FUNCTION_CALL[", text_clause, "]]]]" - ) - - badx <- xml_find_all(xml, xpath) - - ## The actual order of the nodes is document order - ## In practice we need to handle length(x):1 - get_fun <- function(x, n) { - funcall <- xml_children(xml_children(x)[[n]]) - if (!length(funcall)) return(NULL) - fun <- trim_ws(xml_text(funcall[[1]])) - if (! fun %in% bad_funcs) fun else paste0(fun, "(...)") - } - - ## Unfortunately the more natural lapply(badx, ...) does not work, - ## because badx looses its class for length() and/or [[ - lapply( - seq_along(badx), - function(i) { - x <- badx[[i]] - f1 <- get_fun(x, 1) - f2 <- get_fun(x, 3) - line1 <- xml_attr(x, "line1") - col1 <- xml_attr(x, "col1") - col2 <- xml_attr(x, "col1") - Lint( - filename = source_file$filename, - line_number = as.integer(line1), - column_number = as.integer(col1), - type = "warning", - message = paste0( - "Avoid ", f1, ":", f2, " expressions, use seq_len."), - line = source_file$lines[line1], - ranges = list(c(as.integer(col1), as.integer(col2))) - ) - } - ) -}) - #' @importFrom lintr Lint dangerous_functions_linter <- function(source_file, funcs, type, diff --git a/R/prep_lintr.R b/R/prep_lintr.R index 9d2fc8d..04a2b87 100644 --- a/R/prep_lintr.R +++ b/R/prep_lintr.R @@ -9,7 +9,7 @@ linters_to_lint <- list( setwd_linter = setwd_linter(), sapply_linter = sapply_linter(), library_require_linter = library_require_linter(), - seq_linter = seq_linter() + seq_linter = lintr::seq_linter() ) #' @include lists.R diff --git a/man/seq_linter.Rd b/man/seq_linter.Rd deleted file mode 100644 index 2749ace..0000000 --- a/man/seq_linter.Rd +++ /dev/null @@ -1,17 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/my_linters.R -\name{seq_linter} -\alias{seq_linter} -\title{Find dangerous 1:x expressions} -\usage{ -seq_linter() -} -\value{ -Lint object. -} -\description{ -Find occurrences of \code{1:length(x)}, \code{1:nrow(x)}, -\code{1:ncol(x)}, \code{1:NROW(x)}, \code{1:NCOL(x)} where -\code{x} is an R expression. -} -\keyword{internal}