Skip to content

Commit 64a739a

Browse files
Merge branch 'main' into for-loop
2 parents e03707e + a6254c2 commit 64a739a

13 files changed

+211
-51
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ testthat-problems.rds
1717

1818
docs
1919
inst/doc
20+
.DS_Store

.lintr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ exclusions: list(
1010
"tests/testthat/dummy_packages",
1111
"tests/testthat/dummy_projects",
1212
"tests/testthat/exclusions-test",
13+
"tests/testthat/knitr_extended_formats",
1314
"tests/testthat/knitr_formats",
1415
"tests/testthat/knitr_malformed"
1516
)

.lintr_new

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ exclusions: list(
2727
"tests/testthat/dummy_packages",
2828
"tests/testthat/dummy_projects",
2929
"tests/testthat/exclusions-test",
30+
"tests/testthat/knitr_extended_formats",
3031
"tests/testthat/knitr_formats",
3132
"tests/testthat/knitr_malformed"
3233
)

DESCRIPTION

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Imports:
3737
xml2 (>= 1.0.0),
3838
xmlparsedata (>= 1.0.5)
3939
Suggests:
40+
bookdown,
4041
httr (>= 1.2.1),
4142
mockery,
4243
patrick,
@@ -45,6 +46,7 @@ Suggests:
4546
rstudioapi (>= 0.2),
4647
testthat (>= 3.0.0),
4748
tibble,
49+
tufte,
4850
withr (>= 2.5.0)
4951
VignetteBuilder:
5052
knitr

NEWS.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,26 @@
4444
* `boolean_arithmetic_linter()` for identifying places where logical aggregations are more appropriate, e.g.
4545
`length(which(x == y)) == 0` is the same as `!any(x == y)` or even `all(x != y)` (@MichaelChirico)
4646

47-
* `for_loop_index_linter()` to prevent overwriting local variables in a for loop declared like `for (x in x) { ... }` (@MichaelChirico)
47+
* `for_loop_index_linter()` to prevent overwriting local variables in a `for` loop declared like `for (x in x) { ... }` (@MichaelChirico)
48+
49+
## Notes
50+
51+
* `lint()` continues to support Rmarkdown documents. For users of custom .Rmd engines, e.g.
52+
`marginformat` from {tufte} or `theorem` from {bookdown}, note that those engines must be registered
53+
in {knitr} prior to running `lint()` in order for {lintr} to behave as expected, i.e., they should be
54+
shown as part of `knitr::knit_engines$get()`.
55+
56+
For {tufte} and {bookdown} in particular, one only needs to load the package namespace to accomplish
57+
this (i.e., minimally `loadNamespace("tufte")` or `loadNamespace("bookdown")`, respectively, will
58+
register those packages' custom engines; since `library()` also runs `loadNamespace()`, running
59+
`library()` will also work). Note further that {tufte} only added this code to their `.onLoad()` recently
60+
after our request to do so (see https://github.com/rstudio/tufte/issues/117). Therefore, ensure you're using a
61+
more recent version to get the behavior described here for {tufte}.
62+
63+
However, there is no requirement that `loadNamespace()` will register a package's custom {knitr}
64+
engines, so you may need to work with other package authors to figure out a solution for other engines.
65+
66+
Thanks to Yihui and other developers for their helpful discussions around this issue (#797, @IndrajeetPatil).
4867

4968
# lintr 3.0.1
5069

R/extract.R

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ filter_chunk_end_positions <- function(starts, ends) {
9999
}
100100

101101
defines_knitr_engine <- function(start_lines) {
102+
# Other packages defining custom engines should have them loaded and thus visible
103+
# via knitr_engines$get() below. It seems the simplest way to accomplish this is
104+
# for those packages to set some code in their .onLoad() hook, but that's not
105+
# always done (nor quite recommended as a "best practice" by knitr).
106+
# See the discussion on #1552.
107+
# TODO(#1617): explore running loadNamespace() automatically.
102108
engines <- names(knitr::knit_engines$get())
103109

104110
# {some_engine}, {some_engine label, ...} or {some_engine, ...}

R/trailing_blank_lines_linter.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ trailing_blank_lines_linter <- function() {
2727
}
2828
line_number <- line_number - 1L
2929
}
30+
3031
if (identical(source_expression$terminal_newline, FALSE)) { # could use isFALSE, but needs backports
3132
last_line <- tail(source_expression$file_lines, 1L)
3233

@@ -39,6 +40,7 @@ trailing_blank_lines_linter <- function() {
3940
line = last_line
4041
)
4142
}
43+
4244
lints
4345
})
4446
}

tests/testthat.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
library(testthat)
22
library(lintr)
3+
loadNamespace("rex")
4+
loadNamespace("withr")
35

46
test_check("lintr")
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
documentclass: book
3+
output: bookdown::html_document2
4+
---
5+
6+
# Examples
7+
8+
```{definition}
9+
The characteristic function of a random variable $X$ is defined by
10+
$$\varphi _{X}(t)=\operatorname {E} \left[e^{itX}\right], \; t\in\mathcal{R}$$
11+
```
12+
13+
```{r}
14+
a = 1
15+
```
16+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
output: tufte::tufte_html
3+
---
4+
5+
```{marginfigure}
6+
"Hi"
7+
<span>- X</span>
8+
```
9+
10+
```{r}
11+
a = 1
12+
```
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
test_that("marginfigure engine from tufte package doesn't cause problems", {
2+
skip_if_not_installed("tufte", minimum_version = "0.12.4") # for rstudio/tufte#117
3+
loadNamespace("tufte") # to register additional engines
4+
5+
expect_lint(
6+
file = test_path("knitr_extended_formats", "tufte.Rmd"),
7+
checks = list(rex::rex("Use <-, not =, for assignment."), line_number = 11L),
8+
default_linters,
9+
parse_settings = FALSE
10+
)
11+
})
12+
13+
test_that("engines from bookdown package cause no problems", {
14+
skip_if_not_installed("bookdown")
15+
loadNamespace("bookdown") # to register additional engines
16+
17+
expect_lint(
18+
file = test_path("knitr_extended_formats", "bookdown.Rmd"),
19+
checks = list(rex::rex("Use <-, not =, for assignment."), line_number = 14L),
20+
default_linters,
21+
parse_settings = FALSE
22+
)
23+
})

tests/testthat/test-knitr_formats.R

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,82 +12,85 @@ test_that("it handles dir", {
1212
lints <- lint_dir(path = "knitr_formats", pattern = file_pattern, parse_settings = FALSE)
1313

1414
# For every file there should be at least 1 lint
15-
expect_identical(sort(unique(names(lints))), sort(list.files("knitr_formats", pattern = file_pattern)))
15+
expect_identical(
16+
sort(unique(names(lints))),
17+
sort(list.files(test_path("knitr_formats"), pattern = file_pattern))
18+
)
1619
})
1720

1821
test_that("it handles markdown", {
1922
expect_lint(
20-
file = "knitr_formats/test.Rmd",
23+
file = test_path("knitr_formats", "test.Rmd"),
2124
checks = list(
2225
list(regexes[["assign"]], line_number = 9L),
2326
list(regexes[["local_var"]], line_number = 22L),
2427
list(regexes[["assign"]], line_number = 22L),
2528
list(regexes[["trailing"]], line_number = 24L)
2629
),
27-
default_linters,
30+
linters = default_linters,
2831
parse_settings = FALSE
2932
)
3033
})
3134

3235
test_that("it handles quarto", {
3336
expect_lint(
34-
file = "knitr_formats/test.qmd",
37+
file = test_path("knitr_formats", "test.qmd"),
3538
checks = list(
3639
list(regexes[["assign"]], line_number = 9L),
3740
list(regexes[["local_var"]], line_number = 22L),
3841
list(regexes[["assign"]], line_number = 22L),
3942
list(regexes[["trailing"]], line_number = 24L)
4043
),
41-
default_linters,
44+
linters = default_linters,
4245
parse_settings = FALSE
4346
)
4447
})
4548

4649
test_that("it handles Sweave", {
4750
expect_lint(
48-
file = "knitr_formats/test.Rnw",
51+
file = test_path("knitr_formats", "test.Rnw"),
4952
checks = list(
5053
list(regexes[["assign"]], line_number = 12L),
5154
list(regexes[["local_var"]], line_number = 24L),
5255
list(regexes[["assign"]], line_number = 24L),
5356
list(regexes[["trailing"]], line_number = 26L)
5457
),
55-
default_linters,
58+
linters = default_linters,
5659
parse_settings = FALSE
5760
)
5861
})
5962

6063
test_that("it handles reStructuredText", {
6164
expect_lint(
62-
file = "knitr_formats/test.Rrst",
65+
file = test_path("knitr_formats", "test.Rrst"),
6366
checks = list(
6467
list(regexes[["assign"]], line_number = 10L),
6568
list(regexes[["local_var"]], line_number = 23L),
6669
list(regexes[["assign"]], line_number = 23L),
6770
list(regexes[["trailing"]], line_number = 25L)
6871
),
69-
default_linters,
72+
linters = default_linters,
7073
parse_settings = FALSE
7174
)
7275
})
7376

7477
test_that("it handles HTML", {
7578
expect_lint(
76-
file = "knitr_formats/test.Rhtml",
79+
file = test_path("knitr_formats", "test.Rhtml"),
7780
checks = list(
7881
list(regexes[["assign"]], line_number = 15L),
7982
list(regexes[["local_var"]], line_number = 27L),
8083
list(regexes[["assign"]], line_number = 27L),
8184
list(regexes[["trailing"]], line_number = 29L)
8285
),
83-
default_linters,
86+
linters = default_linters,
8487
parse_settings = FALSE
8588
)
8689
})
8790

8891
test_that("it handles tex", {
8992
expect_lint(
90-
file = "knitr_formats/test.Rtex",
93+
file = test_path("knitr_formats", "test.Rtex"),
9194
checks = list(
9295
list(regexes[["assign"]], line_number = 11L),
9396
list(regexes[["local_var"]], line_number = 23L),
@@ -99,21 +102,21 @@ test_that("it handles tex", {
99102
# "%" as well.
100103
# cf. get_source_expressions("tests/testthat/knitr_formats/test.Rtex")$lines[[25]]
101104
),
102-
default_linters,
105+
linters = default_linters,
103106
parse_settings = FALSE
104107
)
105108
})
106109

107110
test_that("it handles asciidoc", {
108111
expect_lint(
109-
file = "knitr_formats/test.Rtxt",
112+
file = test_path("knitr_formats", "test.Rtxt"),
110113
checks = list(
111114
list(regexes[["assign"]], line_number = 9L),
112115
list(regexes[["local_var"]], line_number = 22L),
113116
list(regexes[["assign"]], line_number = 22L),
114117
list(regexes[["trailing"]], line_number = 24L)
115118
),
116-
default_linters,
119+
linters = default_linters,
117120
parse_settings = FALSE
118121
)
119122
})
@@ -138,16 +141,16 @@ test_that("it does _not_ error with inline \\Sexpr", {
138141

139142
test_that("it does lint .Rmd or .qmd file with malformed input", {
140143
expect_lint(
141-
file = "knitr_malformed/incomplete_r_block.Rmd",
144+
file = test_path("knitr_malformed", "incomplete_r_block.Rmd"),
142145
checks = "Missing chunk end",
143-
default_linters,
146+
linters = default_linters,
144147
parse_settings = FALSE
145148
)
146149

147150
expect_lint(
148-
file = "knitr_malformed/incomplete_r_block.qmd",
151+
file = test_path("knitr_malformed", "incomplete_r_block.qmd"),
149152
checks = "Missing chunk end",
150-
default_linters,
153+
linters = default_linters,
151154
parse_settings = FALSE
152155
)
153156

0 commit comments

Comments
 (0)