Skip to content

Commit 58a5c44

Browse files
Squashed commit of the following:
commit d66d4c5 Author: Michael Chirico <[email protected]> Date: Wed Nov 26 15:36:53 2025 +0000 3.3.0-1 -- downgrade to warning commit c03d466 Author: Michael Chirico <[email protected]> Date: Tue Nov 25 20:25:12 2025 +0000 Rearranging after consulting friendly neighborhood LLM commit d73c532 Author: Michael Chirico <[email protected]> Date: Tue Nov 25 20:14:19 2025 +0000 LLM-assisted copy edit commit 87f820c Author: Michael Chirico <[email protected]> Date: Tue Nov 25 20:07:47 2025 +0000 Revert "re-generate docs from roxygen2" This reverts commit a9ab406. commit 796d489 Merge: 7dd6901 564bd57 Author: Michael Chirico <[email protected]> Date: Tue Nov 25 20:06:23 2025 +0000 Merge branch 'main' into rc-3.3.0 commit 7dd6901 Author: Michael Chirico <[email protected]> Date: Tue Nov 25 19:46:33 2025 +0000 A pass at fine-tuning the NEWS commit 89e6d34 Author: Michael Chirico <[email protected]> Date: Tue Nov 25 19:26:06 2025 +0000 Rearrange NEWS items under deprecations commit a9ab406 Author: Michael Chirico <[email protected]> Date: Tue Nov 25 16:37:12 2025 +0000 re-generate docs from roxygen2 commit 1bac028 Author: Michael Chirico <[email protected]> Date: Tue Nov 25 16:16:26 2025 +0000 Ignore new style of testthat _problems commit 04b004a Author: Michael Chirico <[email protected]> Date: Tue Nov 25 16:15:14 2025 +0000 remove cran-comments commit b1a5e33 Author: Michael Chirico <[email protected]> Date: Tue Nov 25 15:18:08 2025 +0000 NEWS version commit 15022a8 Author: Michael Chirico <[email protected]> Date: Tue Nov 25 15:16:40 2025 +0000 bump DESCRIPTION version
1 parent 564bd57 commit 58a5c44

File tree

7 files changed

+42
-46
lines changed

7 files changed

+42
-46
lines changed

.Rbuildignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
^[^/]+\.R$
44
^travis-tool\.sh$
55
^.*\.gz$
6-
^cran-comments\.md$
76
^lintr\.Rproj$
87
^\.Rproj\.user$
98
^\.idea$
@@ -21,6 +20,7 @@
2120
^\.covrignore$
2221
^script[.]R$
2322
^bench$
23+
^tests/testthat/_problems$
2424
^tests/testthat/dummy_packages/package/[.]Rbuildignore$
2525
^tests/testthat/dummy_packages/cp1252/[.]Rbuildignore$
2626
testthat-problems[.]rds$

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ script.R
1414

1515
*.Rcheck
1616
lintr_*.tar.gz
17+
tests/testthat/_problems
1718
testthat-problems.rds
1819

1920
docs

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: lintr
22
Title: A 'Linter' for R Code
3-
Version: 3.2.0.9000
3+
Version: 3.3.0-1
44
Authors@R: c(
55
person("Jim", "Hester", , role = "aut"),
66
person("Florent", "Angly", role = "aut",

NEWS.md

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
# lintr (development version)
1+
# lintr (3.3.0-1)
22

33
## Deprecations & breaking changes
44

5+
* The default for `pipe_consistency_linter()` is changed from `"auto"` (require one pipe style, either magrittr or native) to `"|>"` (R native pipe required) to coincide with the same change in the Tidyverse Style Guide (#2707, @MichaelChirico).
6+
* `lint()` no longer picks up settings automatically in _ad hoc_ invocations like `lint("text\n")` or `lint(text = "str")`. You should set `parse_settings=TRUE` to force settings to be read. Emacs ESS users may need to update to a recent version, e.g. `ESS>20251003`.
57
* Arguments `allow_cascading_assign=`, `allow_right_assign=`, and `allow_pipe_assign=` to `assignment_linter()` are now defunct.
68
* Six linters marked as deprecated with warning in the previous release are now fully deprecated: `consecutive_stopifnot_linter()`, `extraction_operator_linter()`, `no_tab_linter()`, `single_quotes_linter()`, `unnecessary_nested_if_linter()`, and `unneeded_concatenation_linter()`. They will be removed in the next release.
79
* As previously announced, the following fully-deprecated items are now removed from the package:
@@ -10,17 +12,13 @@
1012
+ `linter=` argument of `Lint()`.
1113
+ `with_defaults()`.
1214
+ Linters `closed_curly_linter()`, `open_curly_linter()`, `paren_brace_linter()`, and `semicolon_terminator_linter()`.
13-
* Argument `interpret_glue` to `object_usage_linter()` is deprecated in favor of the more general `interpret_extensions`, in which `"glue"` is present by default (#1472, @MichaelChirico). See the description below.
14-
* The default for `pipe_consistency_linter()` is changed from `"auto"` (require one pipe style, either magrittr or native) to `"|>"` (R native pipe required) to coincide with the same change in the Tidyverse Style Guide (#2707, @MichaelChirico).
15-
* `lint()` no longer picks up settings automatically in _ad hoc_ invocations like `lint("text\n")` or `lint(text = "str")`. You should set `parse_settings=TRUE` to force settings to be read.
15+
* Argument `interpret_glue` to `object_usage_linter()` is deprecated in favor of the more general `interpret_extensions`, in which `"glue"` is present by default (#1472, @MichaelChirico). See the description below under 'New and improved features'.
16+
* `Lint()`, and thus all linters, require that the returned object's `message` attribute is consistently a simple character string (and not, for example, an object of class `"glue"`; #2740, @MichaelChirico). In general it is good to avoid slower string builders like `glue()` inside a loop (a linter might be run on every expression in your pakcage). Classed character strings return a warning in this release, which will be upgraded to an error subsequently.
1617

1718
## Bug fixes
1819

19-
* `Lint()`, and thus all linters, ensures that the returned object's `message` attribute is consistently a simple character string (and not, for example, an object of class `"glue"`; #2740, @MichaelChirico).
2020
* Files with encoding inferred from settings read more robustly under `lint(parse_settings = TRUE)` (#2803, @MichaelChirico). Thanks also to @bastistician for detecting a regression caused by the initial change for users of Emacs (#2847).
2121
* `assignment_linter()` no longer errors if `"%<>%"` is an allowed operator (#2850, @AshesITR).
22-
* `condition_call_linter()` no longer covers cases where the object type in the ellipsis cannot be determined with certainty (#2888, #2890, @Bisaloo). In particular, this fixes the known false positive of custom conditions created via `errorCondition()` or `warningCondition()` not being compatible with the `call.` argument in `stop()` or `warning()`.
23-
* `package_hooks_linter()` now validates `.onUnload()` hook signatures, requiring exactly one argument starting with 'lib' (#2940, @emmanuel-ferdman).
2422
* `expect_lint()` conforms to {testthat} v3.3.0+ rules for custom expectations, namely that they produce either exactly one success or exactly one failure (#2937, @hadley).
2523

2624
## Changes to default linters
@@ -29,57 +27,53 @@
2927

3028
## New and improved features
3129

32-
* `brace_linter()`' has a new argument `function_bodies` (default `"multi_line"`) which controls when to require function bodies to be wrapped in curly braces, with the options `"always"`, `"multi_line"` (only require curly braces when a function body spans multiple lines), `"not_inline"` (only require curly braces when a function body starts on a new line) and `"never"` (#1807, #2240, @salim-b).
30+
### New linters
31+
32+
* `all_equal_linter()` warns about incorrect use of `all.equal()` in `if` clauses or preceded by `!` (#2885, @Bisaloo). Such usages should wrap `all.equal()` with `isTRUE()`, for example.
33+
* `download_file_linter()` encourages the use of `mode = "wb"` (or `mode = "ab"`) when using `download.file()`, rather than `mode = "w"` or `mode = "a"`, as the latter can produce broken files in Windows (#2882, @Bisaloo).
34+
* `list2df_linter()` encourages the use of the `list2DF()` function, or the `data.frame()` function when recycling is required, over the slower and less readable `do.call(cbind.data.frame, )` alternative (#2834, @Bisaloo).
35+
* `coalesce_linter()` encourages the use of the infix operator `x %||% y`, which is equivalent to `if (is.null(x)) y else x` (#2246, @MichaelChirico). While this has long been used in many tidyverse packages (it was added to {ggplot2} in 2008), it became part of every R installation from R 4.4.0. Thanks also to @emmanuel-ferdman for fixing a false positive before release.
36+
37+
### Linter improvements
38+
39+
* `brace_linter()` has a new argument `function_bodies` (default `"multi_line"`) which controls when to require function bodies to be wrapped in curly braces, with the options `"always"`, `"multi_line"` (only require curly braces when a function body spans multiple lines), `"not_inline"` (only require curly braces when a function body starts on a new line) and `"never"` (#1807, #2240, @salim-b).
3340
* `seq_linter()`:
3441
+ recommends using `seq_along(x)` instead of `seq_len(length(x))` (#2577, @MichaelChirico).
35-
+ recommends using `sequence()` instead of `unlist(lapply(ints, seq))` (#2618, @Bisaloo)
42+
+ recommends using `sequence()` instead of `unlist(lapply(ints, seq))` (#2618, @Bisaloo).
3643
* `undesirable_operator_linter()`:
3744
+ Lints operators in prefix form, e.g. `` `%%`(x, 2)`` (#1910, @MichaelChirico). Disable this by setting `call_is_undesirable=FALSE`.
3845
+ Accepts unnamed entries, treating them as undesirable operators, e.g. `undesirable_operator_linter("%%")` (#2536, @MichaelChirico).
39-
* `indentation_linter()` handles `for` un-braced for loops correctly (#2564, @MichaelChirico).
46+
* `undesirable_function_linter()` accepts unnamed entries, treating them as undesirable functions, e.g. `undesirable_function_linter("sum")` (#2536, @MichaelChirico).
47+
* `indentation_linter()` handles un-braced `for` loops correctly (#2564, @MichaelChirico).
4048
* Setting `exclusions` supports globs like `knitr*` to exclude files/directories with a pattern (#1554, @MichaelChirico).
41-
* `get_source_expression()` captures warnings emitted by the R parser (currently always for mis-specified literal integers like `1.1L`) and `lint()` returns them as lints (#2065, @MichaelChirico).
4249
* `object_name_linter()` and `object_length_linter()` apply to objects assigned with `assign()` or generics created with `setGeneric()` (#1665, @MichaelChirico).
4350
* `object_usage_linter()` gains argument `interpret_extensions` to govern which false positive-prone common syntaxes should be checked for used objects (#1472, @MichaelChirico). Currently `"glue"` (renamed from earlier argument `interpret_glue`) and `"rlang"` are supported. The latter newly covers usage of the `.env` pronoun like `.env$key`, where `key` was previously missed as being a used variable.
4451
* `boolean_arithmetic_linter()` finds many more cases like `sum(x | y) == 0` where the total of a known-logical vector is compared to 0 (#1580, @MichaelChirico).
45-
* `expect_lint()` has a new argument `ignore_order` (default `FALSE`), which, if `TRUE`, allows the `checks=` to be provided in arbitary order vs. how `lint()` produces them (@MichaelChirico).
46-
* `undesirable_function_linter()` accepts unnamed entries, treating them as undesirable functions, e.g. `undesirable_function_linter("sum")` (#2536, @MichaelChirico).
4752
* `any_duplicated_linter()` is extended to recognize some usages from {dplyr} and {data.table} that could be replaced by `anyDuplicated()`, e.g. `n_distinct(col) == n()` or `uniqueN(col) == .N` (#2482, @MichaelChirico).
48-
* New `gitlab_output()` function to output lints to GitLab format (#2858, @lschneiderbauer)
4953
* `fixed_regex_linter()` recognizes usage of the new (R 4.5.0) `grepv()` wrapper of `grep()`; `regex_subset_linter()` also recommends `grepv()` alternatives (#2855, @MichaelChirico).
5054
* `object_usage_linter()` lints missing packages that may cause false positives (#2872, @AshesITR)
51-
* New argument `include_s4_slots` for the `xml_find_function_calls()` entry in the `get_source_expressions()` to govern whether calls of the form `s4Obj@fun()` are included in the result (#2820, @MichaelChirico).
5255
* `sprintf_linter()` lints `sprintf()` and `gettextf()` calls when a constant string is passed to `fmt` (#2894, @Bisaloo).
53-
* `use_lintr()` adds the created `.lintr` file to the `.Rbuildignore` if run in a package (#2926, initial work by @MEO265, finalized by @Bisaloo).
5456
* `length_test_linter()` is extended to check incorrect usage of `nrow()`, `ncol()`, `NROW()`, `NCOL()` (#2933, @mcol).
5557
* `implicit_assignment_linter()` gains argument `allow_paren_print` to disable lints for the use of `(` for auto-printing (#2962, @TimTaylor).
5658
* `line_length_linter()` has a new argument `ignore_string_bodies` (defaulting to `FALSE`) which governs whether the contents of multi-line string bodies should be linted (#856, @MichaelChirico). We think the biggest use case for this is writing SQL in R strings, especially in cases where the recommended string width for SQL & R differ.
57-
58-
### New linters
59-
60-
* `all_equal_linter()` warns about incorrect use of `all.equal()` in `if` clauses or preceded by `!` (#2885, @Bisaloo).
61-
* `download_file_linter()` encourages the use of `mode = "wb"` (or `mode = "ab"`) when using `download.file()`, rather than `mode = "w"` or `mode = "a"`, as the latter can produce broken
62-
files in Windows (#2882, @Bisaloo).
63-
* `lint2df_linter()` encourages the use of the `list2DF()` function, or the `data.frame()` function when recycling is required, over the slower and less readable `do.call(cbind.data.frame, )` alternative (#2834, @Bisaloo).
64-
* `coalesce_linter()` encourages the use of the infix operator `x %||% y`, which is equivalent to `if (is.null(x)) y else x` (#2246, @MichaelChirico). While this has long been used in many tidyverse packages (it was added to {ggplot2} in 2008), it became part of every R installation from R 4.4.0. Thanks also to @emmanuel-ferdman for fixing a false positive before release.
59+
* `package_hooks_linter()` now validates `.onUnload()` hook signatures, requiring exactly one argument starting with 'lib' (#2940, @emmanuel-ferdman).
6560

6661
### Lint accuracy fixes: removing false positives
6762

6863
* `unnecessary_nesting_linter()`:
6964
+ Treats function bodies under the shorthand lambda (`\()`) the same as normal function bodies (#2748, @MichaelChirico).
7065
+ Treats `=` assignment the same as `<-` when deciding to combine consecutive `if()` clauses (#2245, @MichaelChirico).
71-
72-
* `unnecessary_nesting_linter()` treats function bodies under the shorthand lambda (`\()`) the same as normal function bodies (#2748, @MichaelChirico).
7366
* `string_boundary_linter()` omits lints of patterns like `\\^` which have an anchor but are not regular expressions (#2636, @MichaelChirico).
7467
* `implicit_integer_linter(allow_colon = TRUE)` is OK with negative literals, e.g. `-1:1` or `1:-1` (#2673, @MichaelChirico).
7568
* `missing_argument_linter()` allows empty calls like `foo()` even if there are comments between `(` and `)` (#2741, @MichaelChirico).
7669
* `return_linter()` works on functions that happen to use braced expressions in their formals (#2616, @MichaelChirico).
7770
* `object_name_linter()` and `object_length_linter()` account for S3 class correctly when the generic is assigned with `=` (#2507, @MichaelChirico).
7871
* `assignment_linter()` with `operator = "="` does a better job of skipping implicit assignments, which are intended to be governed by `implicit_assignment_linter()` (#2765, @MichaelChirico).
79-
* `expect_true_false_linter()` is pipe-aware, so that `42 |> expect_identical(x, ignore_attr = TRUE)` no longer lints (#1520, @MichaelChirico).
80-
* `T_and_F_symbol_linter()` ignores `T` and `F` used as symbols in formulas (`y ~ T + F`), which can represent variables in data not controlled by the author (#2637, @MichaelChirico).
81-
* `T_and_F_symbol_linter()` ignores `T` and `F` if followed by `[` or `[[` (#2944, @mcol).
8272
* `implicit_assignment_linter()` with `allow_scoped=TRUE` doesn't lint for `if (a <- 1) print(a)` (#2913, @MichaelChirico).
73+
* `expect_true_false_linter()` is pipe-aware, so that `42 |> expect_identical(x, ignore_attr = TRUE)` no longer lints (#1520, @MichaelChirico).
74+
* `T_and_F_symbol_linter()` ignores `T` and `F`:
75+
+ When used as symbols in formulas (`y ~ T + F`), which can represent variables in data not controlled by the author (#2637, @MichaelChirico).
76+
+ If followed by `[` or `[[` (#2944, @mcol).
8377

8478
### Lint accuracy fixes: removing false negatives
8579

@@ -88,11 +82,20 @@ files in Windows (#2882, @Bisaloo).
8882
+ `library_call_linter()`
8983
+ `terminal_close_linter()`
9084
+ `unnecessary_lambda_linter()`
91-
* More consistency on handling `@` extractions (#2820, @MichaelChirico).
85+
* More consistency on handling `@` extractions to match how similar `$` extractions would be linted (#2820, @MichaelChirico).
9286
+ `function_left_parentheses_linter()`
9387
+ `indentation_linter()`
9488
+ `library_call_linter()`
9589
+ `missing_argument_linter()`
90+
* `condition_call_linter()` no longer covers cases where the object type in the ellipsis cannot be determined with certainty (#2888, #2890, @Bisaloo). In particular, this fixes the known false positive of custom conditions created via `errorCondition()` or `warningCondition()` not being compatible with the `call.` argument in `stop()` or `warning()`.
91+
92+
### Other improvements
93+
94+
* `get_source_expression()` captures warnings emitted by the R parser (currently always for mis-specified literal integers like `1.1L`) and `lint()` returns them as lints (#2065, @MichaelChirico).
95+
* `expect_lint()` has a new argument `ignore_order` (default `FALSE`), which, if `TRUE`, allows the `checks=` to be provided in arbitary order vs. how `lint()` produces them (@MichaelChirico).
96+
* New `gitlab_output()` function to output lints to GitLab format (#2858, @lschneiderbauer).
97+
* New argument `include_s4_slots` for the `xml_find_function_calls()` entry in the `get_source_expressions()` to govern whether calls of the form `s4Obj@fun()` are included in the result (#2820, @MichaelChirico).
98+
* `use_lintr()` adds the created `.lintr` file to the `.Rbuildignore` if run in a package (#2926, initial work by @MEO265, finalized by @Bisaloo).
9699

97100
## Notes
98101

R/lint.R

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,11 @@ validate_lint_object <- function(message, line, line_number, column_number, rang
410410
cli_abort("{.arg message} must be a character string")
411411
}
412412
if (is.object(message)) {
413-
cli_abort("{.arg message} must be a simple string, but has class {.cls {class(message)}}")
413+
cli_warn(c(
414+
"{.arg message} must be a simple string, but has class {.cls {class(message)}}",
415+
i = "This will be an error in the next lintr release"
416+
))
417+
message <- unclass(message)
414418
}
415419
if (length(line) != 1L || !is.character(line)) {
416420
cli_abort("{.arg line} must be a character string.")

cran-comments.md

Lines changed: 0 additions & 12 deletions
This file was deleted.

tests/testthat/test-Lint-builder.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ test_that("Lint() errors on invalid input", {
4545
"`message` must be a character string",
4646
fixed = TRUE
4747
)
48-
expect_error(
48+
expect_warning(
4949
Lint("dummy.R", message = glue("a")),
5050
"`message` must be a simple string",
5151
fixed = TRUE

0 commit comments

Comments
 (0)