-
Notifications
You must be signed in to change notification settings - Fork 195
Document default settings #1648
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
Conversation
Codecov Report
@@ Coverage Diff @@
## main #1648 +/- ##
=======================================
Coverage 98.31% 98.31%
=======================================
Files 100 100
Lines 4397 4397
=======================================
Hits 4323 4323
Misses 74 74
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
R/zzz.R
Outdated
| #' names(default_settings$linters) | ||
| #' | ||
| #' # default values for a few of the other settings | ||
| #' default_settings$encoding |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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] FALSECreated on 2022-10-08 with reprex v2.0.2
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
|
I'm not sure this closes the issue -- where do we document what a .lintr file is / looks like? |
Closes #823