diff --git a/R/standalone-types-check.R b/R/standalone-types-check.R index 22ea57ba8..5eeea7d57 100644 --- a/R/standalone-types-check.R +++ b/R/standalone-types-check.R @@ -1,7 +1,7 @@ # --- # repo: r-lib/rlang # file: standalone-types-check.R -# last-updated: 2023-03-13 +# last-updated: 2024-08-18 # license: https://unlicense.org # dependencies: standalone-obj-type.R # imports: rlang (>= 1.1.0) @@ -9,6 +9,12 @@ # # ## Changelog # +# 2024-08-18 +# - `check_logical()` and `check_character()` gain `allow_empty` to disallow +# `logical(0)` and `character(0)` respectively. +# +# - `check_logical()` gain `allow_na` to disallow NA values. +# # 2024-08-15: # - `check_character()` gains an `allow_na` argument (@martaalcalde, #1724) # @@ -464,14 +470,16 @@ check_formula <- function(x, check_character <- function(x, ..., + allow_empty = TRUE, allow_na = TRUE, allow_null = FALSE, arg = caller_arg(x), call = caller_env()) { if (!missing(x)) { - if (is_character(x)) { - if (!allow_na && any(is.na(x))) { + problematic <- !allow_empty && length(x) == 0L + if (!problematic && is_character(x)) { + if (!allow_na && anyNA(x)) { abort( sprintf("`%s` can't contain NA values.", arg), arg = arg, @@ -499,11 +507,22 @@ check_character <- function(x, check_logical <- function(x, ..., + allow_empty = TRUE, + allow_na = TRUE, allow_null = FALSE, arg = caller_arg(x), call = caller_env()) { if (!missing(x)) { - if (is_logical(x)) { + if (!allow_na && anyNA(x)) { + abort( + sprintf("`%s` can't contain NA values.", arg), + arg = arg, + call = call + ) + } + problematic <- !allow_empty && length(x) == 0 + + if (!problematic && is_logical(x)) { return(invisible(NULL)) } if (allow_null && is_null(x)) { diff --git a/tests/testthat/_snaps/standalone-types-check.md b/tests/testthat/_snaps/standalone-types-check.md index a54db03a6..f5fc554f3 100644 --- a/tests/testthat/_snaps/standalone-types-check.md +++ b/tests/testthat/_snaps/standalone-types-check.md @@ -456,6 +456,12 @@ Error in `checker()`: ! `foo` can't contain NA values. + Code + err(checker(character(0), check_character, allow_empty = FALSE)) + Output + + Error in `checker()`: + ! `foo` must be a character vector, not an empty character vector. # `check_logical()` checks @@ -489,6 +495,12 @@ Error in `checker()`: ! `foo` must be a logical vector or `NULL`, not a list. + Code + err(checker(logical(0), check_logical, allow_empty = FALSE)) + Output + + Error in `checker()`: + ! `foo` must be a logical vector, not an empty logical vector. # non-numeric types are not numbers diff --git a/tests/testthat/test-standalone-types-check.R b/tests/testthat/test-standalone-types-check.R index a8a6e177c..7cfce6e25 100644 --- a/tests/testthat/test-standalone-types-check.R +++ b/tests/testthat/test-standalone-types-check.R @@ -157,7 +157,7 @@ test_that("`check_character()` checks", { expect_null(check_character(chr())) expect_null(check_character("foo")) expect_null(check_character(letters)) - expect_null(check_character(NULL, allow_null = TRUE)) + expect_null(check_character(NULL, allow_null = TRUE, allow_empty = FALSE)) expect_snapshot({ err(checker(, check_character)) @@ -166,6 +166,7 @@ test_that("`check_character()` checks", { err(checker(1, check_character)) err(checker(list("foo", "bar"), check_character, allow_null = TRUE)) err(checker(c("a", NA), check_character, allow_na = FALSE)) + err(checker(character(0), check_character, allow_empty = FALSE)) }) }) @@ -175,7 +176,7 @@ test_that("`check_logical()` checks", { expect_null(check_logical(na_lgl)) expect_null(check_logical(lgl())) expect_null(check_logical(c(TRUE, FALSE, NA))) - expect_null(check_logical(NULL, allow_null = TRUE)) + expect_null(check_logical(NULL, allow_null = TRUE, allow_empty = FALSE)) expect_snapshot({ err(checker(, check_logical)) @@ -183,6 +184,7 @@ test_that("`check_logical()` checks", { err(checker(NA_integer_, check_logical)) err(checker(1, check_logical)) err(checker(list("foo", "bar"), check_logical, allow_null = TRUE)) + err(checker(logical(0), check_logical, allow_empty = FALSE)) }) })