Skip to content

Commit 67234eb

Browse files
Update docs and adds tests for Quarto files (#1487)
* Updates docs and adds tests for Quarto files Closes #1486 * Update get_source_expressions.Rd * Update test-trailing_blank_lines_linter.R * Update test-trailing_blank_lines_linter.R * Update test-trailing_blank_lines_linter.R * comment out the offending test example * Update NEWS and remove lint * Update test.qmd * get rid of lints and style Co-authored-by: Michael Chirico <[email protected]>
1 parent 00ff659 commit 67234eb

File tree

11 files changed

+208
-48
lines changed

11 files changed

+208
-48
lines changed

NEWS.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@
9191
* The minimum needed version for soft dependency `{withr}` has been bumped to `2.5.0`
9292
(#1404, @IndrajeetPatil).
9393
* Changed the deprecation warning for `with_defaults()` to also mention `modify_defaults()` (#1438, @AshesITR).
94-
94+
* Quarto files (`.qmd`) were supported out of the box. The documentation and the
95+
testing infrastructure are updated to reflect this (#1486, @IndrajeetPatil).
96+
9597
# lintr 3.0.0
9698

9799
## Breaking changes

R/extract.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ filter_chunk_start_positions <- function(starts, lines) {
6969
filter_chunk_end_positions <- function(starts, ends) {
7070
# In a valid file, possibly with plain-code-blocks,
7171
# - there should be at least as many ends as starts
72-
# In Rmarkdown, unevaluated blocks may open & close with the same ``` pattern
72+
# In Rmarkdown and Quarto, unevaluated blocks may open & close with the same ``` pattern
7373
# that defines the end-pattern for an evaluated block
7474

7575
# This returns the first end-position that succeeds each start-position

R/get_source_expressions.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
#' \item{`filename` (`character`)}
4040
#' \item{`file_lines` (`character`) the [readLines()] output for this file}
4141
#' \item{`content` (`character`) for .R files, the same as `file_lines`;
42-
#' for .Rmd scripts, this is the extracted R source code (as text)}
42+
#' for .Rmd or .qmd scripts, this is the extracted R source code (as text)}
4343
#' \item{`full_parsed_content` (`data.frame`) as given by
4444
#' [utils::getParseData()] for the full content}
4545
#' \item{`full_xml_parsed_content` (`xml_document`) the XML parse tree of all

R/lint.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ lint <- function(filename, linters = NULL, ..., cache = FALSE, parse_settings =
119119
#' @param relative_path if `TRUE`, file paths are printed using their path relative to the base directory.
120120
#' If `FALSE`, use the full absolute path.
121121
#' @param exclusions exclusions for [exclude()], relative to the package path.
122-
#' @param pattern pattern for files, by default it will take files with any of the extensions .R, .Rmd, .Rnw, .Rhtml,
123-
#' .Rrst, .Rtex, .Rtxt allowing for lowercase r (.r, ...)
122+
#' @param pattern pattern for files, by default it will take files with any of the extensions
123+
#' .R, .Rmd, .qmd, .Rnw, .Rhtml, .Rrst, .Rtex, .Rtxt allowing for lowercase r (.r, ...)
124124
#' @examples
125125
#' \dontrun{
126126
#' lint_dir()

man/get_source_expressions.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/lint.Rd

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/knitr_formats/test.qmd

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Test #
2+
3+
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
4+
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
5+
vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
6+
no sea takimata sanctus est Lorem ipsum dolor sit amet.
7+
8+
```{r}
9+
a = 1
10+
```
11+
12+
Test
13+
====
14+
15+
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
16+
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
17+
vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
18+
no sea takimata sanctus est Lorem ipsum dolor sit amet.
19+
20+
```{r}
21+
b <- function(x) {
22+
d = 1
23+
}
24+
25+
```
26+
27+
```{r engine="python"}
28+
a=[]
29+
30+
a[0]=1
31+
```
32+
33+
```
34+
Plain code blocks can be written after three or more backticks
35+
- R Markdown: The Definitive Guide. Xie, Allaire and Grolemund (2.5.2)
36+
```
37+
38+
```r
39+
# This is a non-evaluated block of R code for formatting in markdown.
40+
# It should not be linted
41+
abc = 123
42+
```
43+
44+
```cpp
45+
// Some C++ code for formatting by markdown
46+
47+
```
48+
49+
Calls to a non-R knitr-engine using {engine_name} syntax.
50+
51+
```{python}
52+
# Python that looks like R
53+
a = list()
54+
b = {2}
55+
print(a)
56+
```
57+
58+
```{python}
59+
# Python that's definitely not R
60+
a = []
61+
a.append(2)
62+
print(a)
63+
```
64+
65+
The following are only supported by Quarto and shouldn't lint either.
66+
67+
```{.r}
68+
1+1
69+
```
70+
71+
```{{r}}
72+
1+1
73+
```
74+
75+
```{.python}
76+
# Python that's definitely not R
77+
a = []
78+
a.append(2)
79+
print(a)
80+
```
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Test #
2+
3+
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
4+
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
5+
vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
6+
no sea takimata sanctus est Lorem ipsum dolor sit amet.
7+
8+
```{r}
9+
a = 1
10+
11+
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
12+
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
13+
vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
14+
no sea takimata sanctus est Lorem ipsum dolor sit amet.

tests/testthat/test-get_source_expressions.R

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,22 @@ with_content_to_parse <- function(content, code) {
1212
}
1313

1414
test_that("tab positions have been corrected", {
15-
with_content_to_parse("1\n\t",
15+
with_content_to_parse(
16+
"1\n\t",
1617
expect_length(pc, 2L)
1718
)
1819

19-
with_content_to_parse("TRUE",
20+
with_content_to_parse(
21+
"TRUE",
2022
expect_identical(unlist(pc[[1L]][pc[[1L]][["text"]] == "TRUE", c("col1", "col2")], use.names = FALSE), c(1L, 4L))
2123
)
22-
with_content_to_parse("\tTRUE",
24+
with_content_to_parse(
25+
"\tTRUE",
2326
expect_identical(unlist(pc[[1L]][pc[[1L]][["text"]] == "TRUE", c("col1", "col2")], use.names = FALSE), c(2L, 5L))
2427
)
2528

26-
with_content_to_parse("\t\tTRUE",
29+
with_content_to_parse(
30+
"\t\tTRUE",
2731
expect_identical(unlist(pc[[1L]][pc[[1L]][["text"]] == "TRUE", c("col1", "col2")], use.names = FALSE), c(3L, 6L))
2832
)
2933

@@ -83,7 +87,7 @@ test_that("Multi-byte characters correct columns", {
8387

8488
with_content_to_parse("`\U2020` <- 1", {
8589
# fix_column_numbers corrects the start of <-
86-
expect_equal(pc[[1L]]$col1[4L], pc[[1L]]$col1[2L] + 4L)
90+
expect_identical(pc[[1L]]$col1[4L], pc[[1L]]$col1[2L] + 4L)
8791
})
8892
})
8993

@@ -92,8 +96,8 @@ test_that("Multi-byte character truncated by parser is ignored", {
9296
# \U2013 is the Unicode character 'en dash', which is
9397
# almost identical to a minus sign in monospaced fonts.
9498
with_content_to_parse("y <- x \U2013 42", {
95-
expect_equal(error$message, "unexpected input")
96-
expect_equal(error$column_number, 8L)
99+
expect_identical(error$message, "unexpected input")
100+
expect_identical(error$column_number, 8L)
97101
})
98102
})
99103

@@ -117,17 +121,17 @@ test_that("Warns if encoding is misspecified", {
117121
msg <- "unexpected '<'"
118122
}
119123

120-
expect_equal(the_lint$linter, "error")
121-
expect_equal(the_lint$message, msg)
122-
expect_equal(the_lint$line_number, 4L)
124+
expect_identical(the_lint$linter, "error")
125+
expect_identical(the_lint$message, msg)
126+
expect_identical(the_lint$line_number, 4L)
123127

124128
file <- test_path("dummy_projects", "project", "cp1252_parseable.R")
125129
read_settings(NULL)
126130
the_lint <- lint(filename = file, parse_settings = FALSE)[[1L]]
127131
expect_s3_class(the_lint, "lint")
128-
expect_equal(the_lint$linter, "error")
129-
expect_equal(the_lint$message, "Invalid multibyte string. Is the encoding correct?")
130-
expect_equal(the_lint$line_number, 1L)
132+
expect_identical(the_lint$linter, "error")
133+
expect_identical(the_lint$message, "Invalid multibyte string. Is the encoding correct?")
134+
expect_identical(the_lint$line_number, 1L)
131135
})
132136

133137
test_that("Can extract line number from parser errors", {
@@ -138,38 +142,44 @@ test_that("Can extract line number from parser errors", {
138142
trim_some('
139143
"ok"
140144
R"---a---"
141-
'), {
142-
expect_equal(error$message, "Malformed raw string literal.")
143-
expect_equal(error$line_number, 2L)
144-
})
145+
'),
146+
{
147+
expect_identical(error$message, "Malformed raw string literal.")
148+
expect_identical(error$line_number, 2L)
149+
}
150+
)
145151

146152
# invalid \u{xxxx} sequence (line 3)
147153
with_content_to_parse(
148154
trim_some('
149155
ok
150156
ok
151157
"\\u{9999"
152-
'), {
153-
expect_equal(error$message, "Invalid \\u{xxxx} sequence.")
154-
expect_equal(error$line_number, 3L)
155-
})
158+
'),
159+
{
160+
expect_identical(error$message, "Invalid \\u{xxxx} sequence.")
161+
expect_identical(error$line_number, 3L)
162+
}
163+
)
156164

157165
# invalid \u{xxxx} sequence (line 4)
158166
with_content_to_parse(
159167
trim_some('
160168
ok
161169
ok
162170
"\\u{9999
163-
'), {
164-
# parser erroneously reports line 4
165-
expect_equal(error$message, "Invalid \\u{xxxx} sequence.")
166-
expect_equal(error$line_number, 3L)
167-
})
171+
'),
172+
{
173+
# parser erroneously reports line 4
174+
expect_identical(error$message, "Invalid \\u{xxxx} sequence.")
175+
expect_identical(error$line_number, 3L)
176+
}
177+
)
168178

169179
# repeated formal argument 'a' on line 1
170180
with_content_to_parse("function(a, a) {}", {
171-
expect_equal(error$message, "Repeated formal argument 'a'.")
172-
expect_equal(error$line_number, 1L)
181+
expect_identical(error$message, "Repeated formal argument 'a'.")
182+
expect_identical(error$line_number, 1L)
173183
})
174184
})
175185

@@ -235,8 +245,10 @@ test_that("returned data structure is complete", {
235245
expect_identical(full_expr$file_lines, lines_with_attr)
236246
expect_identical(full_expr$content, lines_with_attr)
237247
expect_identical(nrow(full_expr$full_parsed_content), 2L * length(lines))
238-
expect_identical(xml2::xml_find_num(full_expr$full_xml_parsed_content, "count(//SYMBOL)"),
239-
as.numeric(length(lines)))
248+
expect_identical(
249+
xml2::xml_find_num(full_expr$full_xml_parsed_content, "count(//SYMBOL)"),
250+
as.numeric(length(lines))
251+
)
240252
expect_true(full_expr$terminal_newline)
241253

242254
expect_null(exprs$error)
@@ -284,7 +296,7 @@ test_that("#743, #879, #1406: get_source_expressions works on R files matching a
284296
expect_null(source_expressions$error)
285297
})
286298

287-
test_that("Syntax errors in Rmd don't choke lintr", {
299+
test_that("Syntax errors in Rmd or qmd don't choke lintr", {
288300
tmp <- withr::local_tempfile(lines = c(
289301
"```{r}",
290302
"if (TRUE) {",
@@ -321,7 +333,7 @@ param_df <- expand.grid(
321333
stringsAsFactors = FALSE
322334
)
323335
param_df$.test_name <-
324-
with(param_df, sprintf("%s on expression %d", linter, expression_idx))
336+
with(param_df, sprintf("%s on expression %d", linter, expression_idx))
325337

326338
patrick::with_parameters_test_that(
327339
"linters pass with xml_missing() content",

0 commit comments

Comments
 (0)