Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion R/settings.R
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ get_encoding_from_dcf <- function(file) {
)

if (!is.null(encodings)) {
# Produces a warning in R <= 3.5 if encodings is NULL
# Produces a warning in R <= 3.5 if encoding is NULL
encodings <- encodings[!is.na(encodings)]
}
if (length(encodings) > 0L) {
Expand Down
32 changes: 32 additions & 0 deletions R/zzz.R
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,38 @@ default_undesirable_operators <- all_undesirable_operators[names(all_undesirable
)]

#' Default lintr settings
#'
#' @description
#' The default settings consist of
#'
#' - `linters`: a list of default linters (see [default_linters()])
#' - `encoding`: the character encoding assumed for the file
#' - `exclude`: pattern used to exclude a line of code
#' - `exclude_start`, `exclude_end`: patterns used to mark start and of the code block to exclude
#' - `exclude_linter`, `exclude_linter_sep`: patterns used to exclude linters
#' - `exclusions`:a list of files to exclude
#' - `cache_directory`: location of cache directory
#' - `comment_token`: a GitHub token character
#' - `comment_bot`: decides if lintr comment bot on GitHub can comment on commits
#' - `error_on_lint`: decides if error should be produced when any lints are found
#'
#' @examples
#' # available settings
#' names(default_settings)
#'
#' # linters included by default
#' names(default_settings$linters)
#'
#' # default values for a few of the other settings
#' default_settings$encoding
Copy link
Collaborator

Choose a reason for hiding this comment

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

why not just show all the settings at once

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Because the linters element completely overwhelms everything else:

library(lintr)

default_settings
#> $linters
#> $linters$assignment_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)
#>     if (length(bad_expr) == 0L) {
#>       return(list())
#>     }
#> 
#>     operator <- xml2::xml_text(bad_expr)
#>     lint_message_fmt <- ifelse(
#>       operator %in% c("<<-", "->>"),
#>       "%s can have hard-to-predict behavior; prefer assigning to a specific environment instead (with assign() or <-).",
#>       "Use <-, not %s, for assignment."
#>     )
#> 
#>     if (!allow_trailing) {
#>       bad_trailing_expr <- xml2::xml_find_all(xml, trailing_assign_xpath)
#>       trailing_assignments <- xml2::xml_attrs(bad_expr) %in% xml2::xml_attrs(bad_trailing_expr)
#>       lint_message_fmt[trailing_assignments] <- "Assignment %s should not be trailing at end of line"
#>     }
#> 
#>     lint_message <- sprintf(lint_message_fmt, operator)
#>     xml_nodes_to_lints(bad_expr, source_expression, lint_message, type = "style")
#>   }
#> <bytecode: 0x15a9c30b0>
#> <environment: 0x15a9c1ad0>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "assignment_linter"
#> 
#> $linters$brace_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "expression")) {
#>       return(list())
#>     }
#> 
#>     xml <- source_expression$xml_parsed_content
#>     lints <- list()
#> 
#>     lints <- c(lints, xml_nodes_to_lints(
#>       xml2::xml_find_all(xml, xp_open_curly),
#>       source_expression = source_expression,
#>       lint_message =
#>         "Opening curly braces should never go on their own line and should always be followed by a new line."
#>     ))
#> 
#>     lints <- c(lints, xml_nodes_to_lints(
#>       xml2::xml_find_all(xml, xp_paren_brace),
#>       source_expression = source_expression,
#>       lint_message = "There should be a space before an opening curly brace."
#>     ))
#> 
#>     lints <- c(lints, xml_nodes_to_lints(
#>       xml2::xml_find_all(xml, xp_closed_curly),
#>       source_expression = source_expression,
#>       lint_message = "Closing curly-braces should always be on their own line, unless they are followed by an else."
#>     ))
#> 
#>     lints <- c(lints, xml_nodes_to_lints(
#>       xml2::xml_find_all(xml, xp_else_same_line),
#>       source_expression = source_expression,
#>       lint_message = "`else` should come on the same line as the previous `}`."
#>     ))
#> 
#>     lints <- c(lints, xml_nodes_to_lints(
#>       xml2::xml_find_all(xml, xp_function_brace),
#>       source_expression = source_expression,
#>       lint_message = "Any function spanning multiple lines should use curly braces."
#>     ))
#> 
#>     lints <- c(lints, xml_nodes_to_lints(
#>       xml2::xml_find_all(xml, xp_if_else_match_brace),
#>       source_expression = source_expression,
#>       lint_message = "Either both or neither branch in `if`/`else` should use curly braces."
#>     ))
#> 
#>     lints
#>   }
#> <bytecode: 0x15a99cee8>
#> <environment: 0x15a99f2a0>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "brace_linter"
#> 
#> $linters$commas_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "expression")) {
#>       return(list())
#>     }
#>     xml <- source_expression$xml_parsed_content
#> 
#>     before_lints <- xml_nodes_to_lints(
#>       xml2::xml_find_all(xml, xpath_before),
#>       source_expression = source_expression,
#>       lint_message = "Commas should never have a space before.",
#>       range_start_xpath = "number(./preceding-sibling::*[1]/@col2 + 1)", # start after preceding expression
#>       range_end_xpath = "number(./@col1 - 1)" # end before comma
#>     )
#> 
#>     after_lints <- xml_nodes_to_lints(
#>       xml2::xml_find_all(xml, xpath_after),
#>       source_expression = source_expression,
#>       lint_message = "Commas should always have a space after.",
#>       range_start_xpath = "number(./@col2 + 1)", # start and end after comma
#>       range_end_xpath = "number(./@col2 + 1)"
#>     )
#> 
#>     c(before_lints, after_lints)
#>   }
#> <bytecode: 0x15a95b8f8>
#> <environment: 0x15a95dfc0>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "commas_linter"
#> 
#> $linters$commented_code_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "file")) {
#>       return(list())
#>     }
#>     all_comment_nodes <- xml2::xml_find_all(source_expression$full_xml_parsed_content, "//COMMENT")
#>     all_comments <- xml2::xml_text(all_comment_nodes)
#>     code_candidates <- re_matches(all_comments, code_candidate_regex, global = FALSE, locations = TRUE)
#>     extracted_code <- code_candidates[, "code"]
#>     # ignore trailing ',' when testing for parsability
#>     extracted_code <- rex::re_substitutes(extracted_code, rex::rex(",", any_spaces, end), "")
#>     extracted_code <- rex::re_substitutes(extracted_code, rex::rex(start, any_spaces, ","), "")
#>     is_parsable <- which(vapply(extracted_code, parsable, logical(1L)))
#> 
#>     lint_list <- xml_nodes_to_lints(
#>       all_comment_nodes[is_parsable],
#>       source_expression = source_expression,
#>       lint_message = "Commented code should be removed."
#>     )
#> 
#>     # Location info needs updating
#>     for (i in seq_along(lint_list)) {
#>       rng <- lint_list[[i]]$ranges[[1L]]
#> 
#>       rng[2L] <- rng[1L] + code_candidates[is_parsable[i], "code.end"] - 1L
#>       rng[1L] <- rng[1L] + code_candidates[is_parsable[i], "code.start"] - 1L
#> 
#>       lint_list[[i]]$column_number <- rng[1L]
#>       lint_list[[i]]$ranges <- list(rng)
#>     }
#> 
#>     lint_list
#>   }
#> <bytecode: 0x13acf2e40>
#> <environment: 0x15a900008>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "commented_code_linter"
#> 
#> $linters$cyclocomp_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "expression")) {
#>       return(list())
#>     }
#>     complexity <- try_silently(
#>       cyclocomp::cyclocomp(parse(text = source_expression$content))
#>     )
#>     if (inherits(complexity, "try-error") || complexity <= complexity_limit) {
#>       return(list())
#>     }
#>     col1 <- source_expression[["column"]][1L]
#>     Lint(
#>       filename = source_expression[["filename"]],
#>       line_number = source_expression[["line"]][1L],
#>       column_number = source_expression[["column"]][1L],
#>       type = "style",
#>       message = sprintf(
#>         "Functions should have cyclomatic complexity of less than %d, this has %d.",
#>         complexity_limit, complexity
#>       ),
#>       ranges = list(rep(col1, 2L)),
#>       line = source_expression$lines[1L]
#>     )
#>   }
#> <bytecode: 0x13adda438>
#> <environment: 0x13ada9918>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "cyclocomp_linter"
#> 
#> $linters$equals_na_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,
#>       lint_message = "Use is.na for comparisons to NA (not == or !=)",
#>       type = "warning"
#>     )
#>   }
#> <bytecode: 0x13adeec18>
#> <environment: 0x13adebad0>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "equals_na_linter"
#> 
#> $linters$function_left_parentheses_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "expression")) {
#>       return(list())
#>     }
#> 
#>     xml <- source_expression$xml_parsed_content
#>     bad_exprs <- xml2::xml_find_all(xml, xpath)
#> 
#>     xml_nodes_to_lints(
#>       bad_exprs,
#>       source_expression = source_expression,
#>       lint_message = "Remove spaces before the left parenthesis in a function call.",
#>       range_start_xpath = "number(./@col2 + 1)", # start after function / fun
#>       range_end_xpath = "number(./following-sibling::OP-LEFT-PAREN/@col1 - 1)" # end before (
#>     )
#>   }
#> <bytecode: 0x13adfceb8>
#> <environment: 0x13adf9c90>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "function_left_parentheses_linter"
#> 
#> $linters$infix_spaces_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 = lint_message, type = "style")
#>   }
#> <bytecode: 0x13ae08da0>
#> <environment: 0x13ae03e88>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "infix_spaces_linter"
#> 
#> $linters$line_length_linter
#> function(source_expression) {
#>     # Only go over complete file
#>     if (!is_lint_level(source_expression, "file")) {
#>       return(list())
#>     }
#> 
#>     line_lengths <- nchar(source_expression$file_lines)
#>     long_lines <- which(line_lengths > length)
#> 
#>     lint_message <- sprintf("Lines should not be more than %d characters.", length)
#> 
#>     lapply(long_lines, function(long_line) {
#>       Lint(
#>         filename = source_expression$filename,
#>         line_number = long_line,
#>         column_number = length + 1L,
#>         type = "style",
#>         message = lint_message,
#>         line = source_expression$file_lines[long_line],
#>         ranges = list(c(1L, line_lengths[long_line]))
#>       )
#>     })
#>   }
#> <bytecode: 0x13ae14630>
#> <environment: 0x13ae118a0>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "line_length_linter"
#> 
#> $linters$no_tab_linter
#> function(source_expression) {
#>       if (!is_lint_level(source_expression, "expression")) {
#>         return(list())
#>       }
#> 
#>       all_matches <- re_matches(
#>         source_expression[["lines"]],
#>         regex,
#>         locations = TRUE,
#>         global = TRUE
#>       )
#> 
#>       line_numbers <- as.integer(names(source_expression[["lines"]]))
#> 
#>       lints <- Map(
#>         function(line_matches, line_number) {
#>           lapply(
#>             split(line_matches, seq_len(nrow(line_matches))),
#>             function(.match) {
#>               if (is.na(.match[["start"]]) ||
#>                 .in_ignorable_position(source_expression, line_number, .match)) {
#>                 return()
#>               }
#>               start <- .match[["start"]]
#>               end <- .match[["end"]]
#>               Lint(
#>                 filename = source_expression[["filename"]],
#>                 line_number = line_number,
#>                 column_number = start,
#>                 type = lint_type,
#>                 message = lint_msg,
#>                 line = source_expression[["lines"]][[as.character(line_number)]],
#>                 ranges = list(c(start, end))
#>               )
#>             }
#>           )
#>         },
#>         all_matches,
#>         line_numbers
#>       )
#> 
#>       Filter(function(x) any(lengths(x) > 0L), lints)
#>     }
#> <bytecode: 0x13ae2d8a0>
#> <environment: 0x13ae29fd8>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "no_tab_linter"
#> 
#> $linters$object_length_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "file")) {
#>       return(list())
#>     }
#> 
#>     xml <- source_expression$full_xml_parsed_content
#> 
#>     assignments <- xml2::xml_find_all(xml, object_name_xpath)
#> 
#>     # Retrieve assigned name
#>     nms <- strip_names(
#>       xml2::xml_text(assignments)
#>     )
#> 
#>     # run namespace_imports at run-time, not "compile" time to allow package structure to change
#>     ns_imports <- namespace_imports(find_package(source_expression$filename))
#>     generics <- strip_names(c(
#>       declared_s3_generics(xml),
#>       imported_s3_generics(ns_imports)$fun,
#>       .base_s3_generics
#>     ))
#>     generics <- unique(generics[nzchar(generics)])
#> 
#>     # Remove generic function names from generic implementations
#>     # This only lints S3 implementations if the class names are too long, still lints generics if they are too long.
#>     nms_stripped <- re_substitutes(nms, rex(start, or(generics), "."), "")
#> 
#>     too_long <- nchar(nms_stripped) > length
#> 
#>     xml_nodes_to_lints(
#>       assignments[too_long],
#>       source_expression = source_expression,
#>       lint_message = lint_message,
#>       type = "style"
#>     )
#>   }
#> <bytecode: 0x13ae5b8e0>
#> <environment: 0x13ae5c638>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "object_length_linter"
#> 
#> $linters$object_name_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "file")) {
#>       return(list())
#>     }
#> 
#>     xml <- source_expression$full_xml_parsed_content
#> 
#>     assignments <- xml2::xml_find_all(xml, object_name_xpath)
#> 
#>     # Retrieve assigned name
#>     nms <- strip_names(
#>       xml2::xml_text(assignments)
#>     )
#> 
#>     # run namespace_imports at run-time, not "compile" time to allow package structure to change
#>     generics <- c(
#>       declared_s3_generics(xml),
#>       imported_s3_generics(namespace_imports(find_package(source_expression$filename)))$fun,
#>       .base_s3_generics
#>     )
#>     generics <- unique(generics[nzchar(generics)])
#> 
#>     style_matches <- lapply(styles, function(style) {
#>       check_style(nms, style, generics)
#>     })
#> 
#>     matches_a_style <- Reduce(`|`, style_matches)
#> 
#>     xml_nodes_to_lints(
#>       assignments[!matches_a_style],
#>       source_expression,
#>       lint_message = lint_message,
#>       type = "style"
#>     )
#>   }
#> <bytecode: 0x13ae7acc8>
#> <environment: 0x13ae75ad8>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "object_name_linter"
#> 
#> $linters$object_usage_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "file")) {
#>       return(list())
#>     }
#> 
#>     pkg_name <- pkg_name(find_package(dirname(source_expression$filename)))
#>     # run the following at run-time, not "compile" time to allow package structure to change
#>     env <- make_check_env(pkg_name)
#> 
#>     declared_globals <- try_silently(utils::globalVariables(package = pkg_name %||% globalenv()))
#> 
#>     xml <- source_expression$full_xml_parsed_content
#> 
#>     symbols <- c(
#>       get_assignment_symbols(xml),
#>       get_imported_symbols(xml)
#>     )
#> 
#>     # Just assign them an empty function
#>     for (symbol in symbols) {
#>       assign(symbol, function(...) invisible(), envir = env)
#>     }
#> 
#>     fun_assignments <- xml2::xml_find_all(xml, xpath_function_assignment)
#> 
#>     lapply(fun_assignments, function(fun_assignment) {
#>       code <- get_content(lines = source_expression$content, fun_assignment)
#>       fun <- try_silently(eval(
#>         envir = env,
#>         parse(
#>           text = code,
#>           keep.source = TRUE
#>         )
#>       ))
#> 
#>       if (inherits(fun, "try-error")) {
#>         return()
#>       }
#>       known_used_symbols <- get_used_symbols(fun_assignment, interpret_glue = interpret_glue)
#>       res <- parse_check_usage(
#>         fun,
#>         known_used_symbols = known_used_symbols,
#>         declared_globals = declared_globals,
#>         start_line = as.integer(xml2::xml_attr(fun_assignment, "line1")),
#>         skip_with = skip_with
#>       )
#> 
#>       # TODO handle assignment functions properly
#>       # e.g. `not_existing<-`(a, b)
#>       res$name <- rex::re_substitutes(res$name, rex::rex("<-"), "")
#> 
#>       lintable_symbols <- xml2::xml_find_all(
#>         fun_assignment,
#>         "
#>         descendant::SYMBOL
#>         | descendant::SYMBOL_FUNCTION_CALL
#>         | descendant::SPECIAL
#>         | descendant::LEFT_ASSIGN[text() = ':=']
#>         "
#>       )
#> 
#>       lintable_symbol_names <- gsub("^`|`$", "", xml2::xml_text(lintable_symbols))
#>       lintable_symbol_lines <- as.integer(xml2::xml_attr(lintable_symbols, "line1"))
#> 
#>       matched_symbol <- vapply(
#>         seq_len(nrow(res)),
#>         function(i) {
#>           match(
#>             TRUE,
#>             lintable_symbol_names == res$name[i] &
#>               lintable_symbol_lines >= res$line1[i] &
#>               lintable_symbol_lines <= res$line2[i]
#>           )
#>         },
#>         integer(1L)
#>       )
#> 
#>       nodes <- unclass(lintable_symbols)[matched_symbol]
#>       nodes[is.na(matched_symbol)] <- list(fun_assignment)
#> 
#>       xml_nodes_to_lints(nodes, source_expression = source_expression, lint_message = res$message, type = "warning")
#>     })
#>   }
#> <bytecode: 0x13ae95320>
#> <environment: 0x13ae92be8>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "object_usage_linter"
#> 
#> $linters$paren_body_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "expression")) {
#>       return(list())
#>     }
#> 
#>     xml <- source_expression$xml_parsed_content
#>     matched_expressions <- xml2::xml_find_all(xml, xpath)
#> 
#>     xml_nodes_to_lints(
#>       matched_expressions,
#>       source_expression = source_expression,
#>       lint_message = "There should be a space between a right parenthesis and a body expression."
#>     )
#>   }
#> <bytecode: 0x13aee14a8>
#> <environment: 0x13aede280>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "paren_body_linter"
#> 
#> $linters$pipe_continuation_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "file")) {
#>       return(list())
#>     }
#>     x <- source_expression$full_xml_parsed_content
#> 
#>     pipe_exprs <- xml_find_all(x, multiline_pipe_test)
#> 
#>     xml_nodes_to_lints(
#>       pipe_exprs,
#>       source_expression = source_expression,
#>       lint_message = paste(
#>         "`%>%` should always have a space before it and a new line after it,",
#>         "unless the full pipeline fits on one line."
#>       ),
#>       type = "style"
#>     )
#>   }
#> <bytecode: 0x13aeeb790>
#> <environment: 0x13aeec4e8>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "pipe_continuation_linter"
#> 
#> $linters$semicolon_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "file")) {
#>       return(list())
#>     }
#> 
#>     xml <- source_expression$full_xml_parsed_content
#>     bad_exprs <- xml2::xml_find_all(xml, xpath)
#>     if (need_detection) {
#>       is_trailing <- is.na(xml2::xml_find_first(bad_exprs, compound_xpath))
#>       msg <- ifelse(is_trailing, msg_trailing, msg_compound)
#>     }
#> 
#>     xml_nodes_to_lints(
#>       bad_exprs,
#>       source_expression = source_expression,
#>       lint_message = msg
#>     )
#>   }
#> <bytecode: 0x13aefaf68>
#> <environment: 0x13aef6130>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "semicolon_linter"
#> 
#> $linters$seq_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "expression")) {
#>       return(list())
#>     }
#> 
#>     xml <- source_expression$xml_parsed_content
#> 
#>     badx <- xml2::xml_find_all(xml, xpath)
#> 
#>     # TODO: better message customization. For example, length(x):1
#>     #   would get rev(seq_along(x)) as the preferred replacement.
#>     dot_expr1 <- get_fun(badx, 1L)
#>     dot_expr2 <- get_fun(badx, 2L)
#>     seq_along_idx <- grepl("length(", dot_expr1, fixed = TRUE) | grepl("length(", dot_expr2, fixed = TRUE)
#>     replacement <- ifelse(seq_along_idx, "seq_along", "seq_len")
#> 
#>     dot_expr3 <- ifelse(seq_along_idx, "...", dot_expr2)
#>     lint_message <- ifelse(
#>       grepl("seq", dot_expr1, fixed = TRUE),
#>       sprintf(
#>         "%s(%s) is likely to be wrong in the empty edge case. Use %s(%s) instead.",
#>         dot_expr1, dot_expr2, replacement, dot_expr3
#>       ),
#>       sprintf(
#>         "%s:%s is likely to be wrong in the empty edge case. Use %s(%s) instead.",
#>         dot_expr1, dot_expr2, replacement, dot_expr3
#>       )
#>     )
#> 
#>     xml_nodes_to_lints(badx, source_expression, lint_message, type = "warning")
#>   }
#> <bytecode: 0x13af12210>
#> <environment: 0x13af0cb08>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "seq_linter"
#> 
#> $linters$single_quotes_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "file")) {
#>       return(list())
#>     }
#> 
#>     content <- source_expression$full_parsed_content
#>     str_idx <- which(content$token == "STR_CONST")
#>     squote_matches <- which(re_matches(content[str_idx, "text"], squote_regex))
#> 
#>     lapply(
#>       squote_matches,
#>       function(id) {
#>         with(content[str_idx[id], ], {
#>           line <- source_expression$file_lines[[line1]]
#>           col2 <- if (line1 == line2) col2 else nchar(line)
#>           Lint(
#>             filename = source_expression$filename,
#>             line_number = line1,
#>             column_number = col1,
#>             type = "style",
#>             message = "Only use double-quotes.",
#>             line = line,
#>             ranges = list(c(col1, col2))
#>           )
#>         })
#>       }
#>     )
#>   }
#> <bytecode: 0x13af32800>
#> <environment: 0x13af33590>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "single_quotes_linter"
#> 
#> $linters$spaces_inside_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "file")) {
#>       return(list())
#>     }
#> 
#>     xml <- source_expression$full_xml_parsed_content
#> 
#>     left_expr <- xml2::xml_find_all(xml, left_xpath)
#>     left_msg <- ifelse(
#>       xml2::xml_text(left_expr) == "[",
#>       "Do not place spaces after square brackets.",
#>       "Do not place spaces after parentheses."
#>     )
#> 
#>     left_lints <- xml_nodes_to_lints(
#>       left_expr,
#>       source_expression = source_expression,
#>       lint_message = left_msg,
#>       range_start_xpath = "number(./@col2 + 1)", # start after ( or [
#>       range_end_xpath = "number(./following-sibling::*[1]/@col1 - 1)" # end before following expr
#>     )
#> 
#>     right_expr <- xml2::xml_find_all(xml, right_xpath)
#>     right_msg <- ifelse(
#>       xml2::xml_text(right_expr) == "]",
#>       "Do not place spaces before square brackets.",
#>       "Do not place spaces before parentheses."
#>     )
#> 
#>     right_lints <- xml_nodes_to_lints(
#>       right_expr,
#>       source_expression = source_expression,
#>       lint_message = right_msg,
#>       range_start_xpath = "number(./preceding-sibling::*[1]/@col2 + 1)", # start after preceding expression
#>       range_end_xpath = "number(./@col1 - 1)" # end before ) or ]
#>     )
#> 
#>     c(left_lints, right_lints)
#>   }
#> <bytecode: 0x13af50e58>
#> <environment: 0x13af4df08>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "spaces_inside_linter"
#> 
#> $linters$spaces_left_parentheses_linter
#> function(source_expression) {
#>     # else/if structure for trees that are missing XML content (both global & local)
#>     if (is_lint_level(source_expression, "file")) {
#>       # 'x = 1;(x + 2)' can't be detected from the expression-level tree
#>       xml <- source_expression$full_xml_parsed_content
#>       xpath <- file_level_xpath
#>     } else {
#>       xml <- source_expression$xml_parsed_content
#>       xpath <- expression_level_xpath
#>     }
#> 
#>     bad_paren <- xml2::xml_find_all(xml, xpath)
#> 
#>     xml_nodes_to_lints(
#>       bad_paren,
#>       source_expression,
#>       lint_message = "Place a space before left parenthesis, except in a function call.",
#>       type = "style"
#>     )
#>   }
#> <bytecode: 0x13af690f8>
#> <environment: 0x13af64480>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "spaces_left_parentheses_linter"
#> 
#> $linters$T_and_F_symbol_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "expression")) {
#>       return(list())
#>     }
#> 
#>     bad_exprs <- xml2::xml_find_all(source_expression$xml_parsed_content, xpath)
#>     bad_assigns <- xml2::xml_find_all(source_expression$xml_parsed_content, xpath_assignment)
#> 
#>     make_lints <- function(expr, fmt) {
#>       symbol <- xml2::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_exprs, "Use %s instead of the symbol %s."),
#>       make_lints(bad_assigns, "Don't use %2$s as a variable name, as it can break code relying on %2$s being %1$s.")
#>     )
#>   }
#> <bytecode: 0x13af76c60>
#> <environment: 0x13af71bc0>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "T_and_F_symbol_linter"
#> 
#> $linters$trailing_blank_lines_linter
#> function(source_expression) {
#>     blanks <- re_matches(
#>       source_expression$file_lines,
#>       rex(start, any_spaces, end)
#>     )
#> 
#>     line_number <- length(source_expression$file_lines)
#>     lints <- list()
#>     while (line_number > 0L && (is.na(blanks[[line_number]]) || isTRUE(blanks[[line_number]]))) {
#>       if (!is.na(blanks[[line_number]])) {
#>         lints[[length(lints) + 1L]] <- Lint(
#>           filename = source_expression$filename,
#>           line_number = line_number,
#>           column_number = 1L,
#>           type = "style",
#>           message = "Trailing blank lines are superfluous.",
#>           line = source_expression$file_lines[[line_number]]
#>         )
#>       }
#>       line_number <- line_number - 1L
#>     }
#> 
#>     if (identical(source_expression$terminal_newline, FALSE)) { # could use isFALSE, but needs backports
#>       last_line <- tail(source_expression$file_lines, 1L)
#> 
#>       lints[[length(lints) + 1L]] <- Lint(
#>         filename = source_expression$filename,
#>         line_number = length(source_expression$file_lines),
#>         column_number = nchar(last_line) %||% 0L + 1L,
#>         type = "style",
#>         message = "Missing terminal newline.",
#>         line = last_line
#>       )
#>     }
#> 
#>     lints
#>   }
#> <bytecode: 0x13af908e0>
#> <environment: 0x13af91600>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "trailing_blank_lines_linter"
#> 
#> $linters$trailing_whitespace_linter
#> function(source_expression) {
#>     if (!is_lint_level(source_expression, "file")) {
#>       return(list())
#>     }
#> 
#>     res <- re_matches(
#>       source_expression$file_lines,
#>       rex(blanks, end),
#>       locations = TRUE
#>     )
#> 
#>     if (isTRUE(allow_empty_lines)) {
#>       bad_lines <- which(res$start > 1L)
#>     } else {
#>       bad_lines <- which(!is.na(res$start))
#>     }
#> 
#>     if (isTRUE(allow_in_strings) && !is.null(source_expression$full_xml_parsed_content)) {
#>       all_str_consts <- xml2::xml_find_all(source_expression$full_xml_parsed_content, "//STR_CONST")
#>       start_lines <- as.integer(xml2::xml_attr(all_str_consts, "line1"))
#>       end_lines <- as.integer(xml2::xml_attr(all_str_consts, "line2"))
#> 
#>       is_in_str <- vapply(bad_lines, function(ln) {
#>         any(start_lines <= ln & ln < end_lines)
#>       }, logical(1L))
#>       bad_lines <- bad_lines[!is_in_str]
#>     }
#> 
#>     lapply(
#>       bad_lines,
#>       function(line) {
#>         Lint(
#>           filename = source_expression$filename,
#>           line_number = line,
#>           column_number = res$start[[line]],
#>           type = "style",
#>           message = "Trailing whitespace is superfluous.",
#>           line = source_expression$file_lines[[line]],
#>           ranges = list(c(res$start[[line]], res$end[[line]]))
#>         )
#>       }
#>     )
#>   }
#> <bytecode: 0x13afaab48>
#> <environment: 0x13afa6368>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "trailing_whitespace_linter"
#> 
#> $linters$vector_logic_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 = "Conditional expressions require scalar logical operators (&& and ||)",
#>       type = "warning"
#>     )
#>   }
#> <bytecode: 0x13afd2c28>
#> <environment: 0x13afcfae0>
#> attr(,"class")
#> [1] "linter"   "function"
#> attr(,"name")
#> [1] "vector_logic_linter"
#> 
#> 
#> $encoding
#> [1] "UTF-8"
#> 
#> $exclude
#> #[[:space:]]*nolint
#> 
#> $exclude_start
#> #[[:space:]]*nolint start
#> 
#> $exclude_end
#> #[[:space:]]*nolint end
#> 
#> $exclude_linter
#> ^[[:space:]]*:[[:space:]]*(?<linters>(?:(?:[^,.])+[[:space:]]*,[[:space:]]*)*(?:[^,.])+)\.
#> 
#> $exclude_linter_sep
#> [[:space:]]*,[[:space:]]*
#> 
#> $exclusions
#> list()
#> 
#> $cache_directory
#> [1] "/Users/indrajeetpatil/Library/Caches/org.R-project.R/R/lintr"
#> 
#> $comment_token
#> [1] "0a12aa72507e6273daac3443dab7d42a1a71aa28"
#> 
#> $comment_bot
#> [1] TRUE
#> 
#> $error_on_lint
#> [1] FALSE

Created on 2022-10-08 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.

got it, yea that's not very helpful. How about default_settings[setdiff(names(default_settings), "linters")] or just default_settings[c(...)] for the set we think are important?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done!

I am still retaining names(default_settings) and names(default_settings$linters) to show the names of everything included in these two objects.

#' default_settings$exclude
#' default_settings$exclude_start
#' default_settings$exclude_end
#' default_settings$exclude_linter
#' default_settings$exclude_linter_sep
#' default_settings$exclusions
#' default_settings$error_on_lint
#'
#' @seealso [read_settings()], [default_linters]
#' @export
default_settings <- NULL
Expand Down
32 changes: 31 additions & 1 deletion man/default_settings.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.