diff --git a/NEWS.md b/NEWS.md index b2def51a45..d5d4c514d9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -23,7 +23,8 @@ * `object_name_linter()` gains a new default style, `"symbols"`, which won't lint all-symbol object names (in particular, that means operator names like `%+%` are skipped; #615, #670, @michaelchirico and @AshesITR) * `spaces_inside_linter` ignores spaces preceding trailing comments (#636, @michaelchirico) -* `T_and_F_symbol_linter` is now part of the default linters (#517, #612, @AshesITR) +* `T_and_F_symbol_linter` and `semicolon_terminator_linter` are now part of the default linters + (#517, #612, #683, #684, @AshesITR) * `with_defaults()` no longer duplicates the `lintr_function` class when it is already present (#511, #612, @AshesITR) * New `backport_linter()` for detecting mismatched R version dependencies (#506, @MichaelChirico) * `paren_brace_linter` and `no_tab_linter` also use more reliable matching (e.g., diff --git a/R/tree-utils.R b/R/tree-utils.R index 9349fea581..e72069953c 100644 --- a/R/tree-utils.R +++ b/R/tree-utils.R @@ -22,7 +22,7 @@ component_edges <- function(graph, id) { neis <- unlist(graph$adjlist[newv]) newv <- setdiff(neis, sc) sc <- c(sc, newv) - if (length(sc) == size) break; + if (length(sc) == size) break size <- length(sc) } diff --git a/R/zzz.R b/R/zzz.R index bcaf341685..99e3f00f59 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -89,6 +89,7 @@ default_linters <- with_defaults( open_curly_linter(), paren_brace_linter, pipe_continuation_linter, + semicolon_terminator_linter(), seq_linter, single_quotes_linter, spaces_inside_linter, diff --git a/tests/testthat/default_linter_testcode.R b/tests/testthat/default_linter_testcode.R index fce166aef3..ba7ba7cca1 100644 --- a/tests/testthat/default_linter_testcode.R +++ b/tests/testthat/default_linter_testcode.R @@ -39,7 +39,8 @@ message('single_quotes') # spaces_left_parentheses # trailing_whitespace -y <- 2 +(1:10) +# semicolon_terminator +x <- 42; y <- 2 +(1:10) # trailing_blank_lines diff --git a/tests/testthat/dummy_packages/package/R/default_linter_testcode.R b/tests/testthat/dummy_packages/package/R/default_linter_testcode.R index fce166aef3..ba7ba7cca1 100644 --- a/tests/testthat/dummy_packages/package/R/default_linter_testcode.R +++ b/tests/testthat/dummy_packages/package/R/default_linter_testcode.R @@ -39,7 +39,8 @@ message('single_quotes') # spaces_left_parentheses # trailing_whitespace -y <- 2 +(1:10) +# semicolon_terminator +x <- 42; y <- 2 +(1:10) # trailing_blank_lines diff --git a/tests/testthat/dummy_packages/package/data-raw/default_linter_testcode.R b/tests/testthat/dummy_packages/package/data-raw/default_linter_testcode.R index fce166aef3..ba7ba7cca1 100644 --- a/tests/testthat/dummy_packages/package/data-raw/default_linter_testcode.R +++ b/tests/testthat/dummy_packages/package/data-raw/default_linter_testcode.R @@ -39,7 +39,8 @@ message('single_quotes') # spaces_left_parentheses # trailing_whitespace -y <- 2 +(1:10) +# semicolon_terminator +x <- 42; y <- 2 +(1:10) # trailing_blank_lines diff --git a/tests/testthat/dummy_packages/package/inst/data-raw/default_linter_testcode.R b/tests/testthat/dummy_packages/package/inst/data-raw/default_linter_testcode.R index fce166aef3..ba7ba7cca1 100644 --- a/tests/testthat/dummy_packages/package/inst/data-raw/default_linter_testcode.R +++ b/tests/testthat/dummy_packages/package/inst/data-raw/default_linter_testcode.R @@ -39,7 +39,8 @@ message('single_quotes') # spaces_left_parentheses # trailing_whitespace -y <- 2 +(1:10) +# semicolon_terminator +x <- 42; y <- 2 +(1:10) # trailing_blank_lines diff --git a/tests/testthat/test-exclusions.R b/tests/testthat/test-exclusions.R index 2df58f4750..611f16a9ac 100644 --- a/tests/testthat/test-exclusions.R +++ b/tests/testthat/test-exclusions.R @@ -68,7 +68,7 @@ test_that("it returns all lines between start and end", { test_that("it ignores exclude coverage lines within start and end", { read_settings(NULL) - t1 <- tempfile() + t1 <- tempfile() on.exit(unlink(t1)) writeLines( c("this #TeSt_NoLiNt_StArT", @@ -119,65 +119,97 @@ test_that("it merges two NULL or empty objects as an empty list", { }) test_that("it returns the object if the other is NULL", { - t1 <- list(); t1[[a]] <- 1:10 + t1 <- list() + t1[[a]] <- 1:10 expect_equal(normalize_exclusions(c(t1, NULL)), t1) expect_equal(normalize_exclusions(c(NULL, t1)), t1) }) test_that("it returns the union of two non-overlapping lists", { - t1 <- list(); t1[[a]] <- 1:10 - t2 <- list(); t2[[a]] <- 20:30 - res <- list(); res[[a]] <- c(1:10, 20:30) + t1 <- list() + t2 <- list() + res <- list() + t1[[a]] <- 1:10 + t2[[a]] <- 20:30 + res[[a]] <- c(1:10, 20:30) expect_equal(normalize_exclusions(c(t1, t2)), res) }) test_that("it returns the union of two overlapping lists", { - t1 <- list(); t1[[a]] <- 1:10 - t2 <- list(); t2[[a]] <- 5:15 - res <- list(); res[[a]] <- 1:15 + t1 <- list() + t2 <- list() + res <- list() + t1[[a]] <- 1:10 + t2[[a]] <- 5:15 + res[[a]] <- 1:15 expect_equal(normalize_exclusions(c(t1, t2)), res) }) test_that("it adds names if needed", { - t1 <- list(); t1[[a]] <- 1:10 - t2 <- list(); t2[[b]] <- 5:15 - res <- list(); res[[a]] <- 1:10; res[[b]] <- 5:15 + t1 <- list() + t2 <- list() + res <- list() + t1[[a]] <- 1:10 + t2[[b]] <- 5:15 + res[[a]] <- 1:10 + res[[b]] <- 5:15 expect_equal(normalize_exclusions(c(t1, t2)), res) }) test_that("it handles full file exclusions", { - res <- list(); res[[a]] <- Inf + res <- list() + res[[a]] <- Inf expect_equal(normalize_exclusions(list(a)), res) - t1 <- list(); t1[[1]] <- a; t1[[b]] <- 1 - res <- list(); res[[a]] <- Inf; res[[b]] <- 1 + t1 <- list() + res <- list() + t1[[1]] <- a + t1[[b]] <- 1 + res[[a]] <- Inf + res[[b]] <- 1 expect_equal(normalize_exclusions(t1), res) }) test_that("it handles redundant lines", { - t1 <- list(); t1[[a]] <- c(1, 1, 1:10) - res <- list(); res[[a]] <- 1:10 + t1 <- list() + res <- list() + t1[[a]] <- c(1, 1, 1:10) + res[[a]] <- 1:10 expect_equal(normalize_exclusions(t1), res) - t1 <- list(); t1[[a]] <- c(1, 1, 1:10); t1[[b]] <- 1:10 - res <- list(); res[[a]] <- 1:10; res[[b]] <- 1:10 + t1 <- list() + res <- list() + t1[[a]] <- c(1, 1, 1:10) + t1[[b]] <- 1:10 + res[[a]] <- 1:10 + res[[b]] <- 1:10 expect_equal(normalize_exclusions(t1), res) }) test_that("it handles redundant files", { - t1 <- list(1:10, 10:20); names(t1) <- c(a, a) - res <- list(); res[[a]] <- 1:20 + t1 <- list(1:10, 10:20) + names(t1) <- c(a, a) + res <- list() + res[[a]] <- 1:20 expect_equal(normalize_exclusions(t1), res) }) test_that("it normalizes file paths, removing non-existing files", { - t1 <- list(); t1[[a]] <- 1:10 - t2 <- list(); t2[["notafile"]] <- 5:15 - t3 <- list(); t3[[c]] <- 5:15 - res <- list(); res[[a]] <- 1:10; res[[normalizePath(c)]] <- 5:15 + t1 <- list() + t2 <- list() + t3 <- list() + res <- list() + t1[[a]] <- 1:10 + t2[["notafile"]] <- 5:15 + t3[[c]] <- 5:15 + res[[a]] <- 1:10 + res[[normalizePath(c)]] <- 5:15 expect_equal(normalize_exclusions(c(t1, t2, t3)), res) - res <- list(); res[[a]] <- 1:10; res[["notafile"]] <- 5:15; res[[c]] <- 5:15 + res <- list() + res[[a]] <- 1:10 + res[["notafile"]] <- 5:15 + res[[c]] <- 5:15 expect_equal(normalize_exclusions(c(t1, t2, t3), normalize_path = FALSE), res) })