Skip to content

Recursively extracting checkers for all arguments - #48

Draft
krlmlr wants to merge 23 commits into
mainfrom
f-chk
Draft

Recursively extracting checkers for all arguments#48
krlmlr wants to merge 23 commits into
mainfrom
f-chk

Conversation

@krlmlr

@krlmlr krlmlr commented Nov 18, 2025

Copy link
Copy Markdown
Collaborator

This is to automatically generate efficient argument validity checks to apply to each row of a scenario data frame up front. Imagining a situation where we let the user prepare a large scenario and want to check up front if all arguments are good. Works by recursively looking for chk_() functions. Intended to be run during package build time.

Current scope of ssd_hc_sims()

  1. (A) Validate the grid
  2. (B) Help the user create the grid
  3. (C) Run the grid

Future scope of individual components of this function

  1. One of:
    1. (B) Help the user create the grid
    2. Let the user create the grid
  2. (A) Validate the grid
  3. (C) Run the grid
  4. Optionally: Postprocess results one by one as we see them.

Reason for splitting ssd_hc_sims(): to be able to add custom behaviors without adding too much complexity to ssd_hc_sims() .

Next steps

  • @joethorley: Add remaining checks, see FIXME_ADD_CHECK_CALL(...) in the output.
  • @krlmlr: Propose split of ssd_hc_sims() based on this utility.

Example

pkgload::load_all()
#> ℹ Loading ssdsims

# Test with ssd_hc generic (will analyze all methods)
combine_chk_calls(ssdtools::ssd_hc)
Details
#> ℹ Function `<function>()` is an S3 generic
#> ℹ Found 3 methods: `ssd_hc.fitburrlioz()`, `ssd_hc.fitdists()`, and `ssd_hc.list()`
#> ℹ Collected 16 unique arguments across all methods: `x`, `percent`, `proportion`, `ci`, `level`, `nboot`, `min_pboot`, `parametric`, `samples`, `save_to`, `average`, `multi_est`, `est_method`, `ci_method`, `delta`, and `control`
#> ℹ Analyzing all arguments
#> → Recursively analyzing each method...
#> ℹ   Non-generic function `ssd_hc.fitburrlioz()` with 10 arguments: `x`, `percent`, `proportion`, `ci`, `level`, `nboot`, `min_pboot`, `parametric`, `samples`, and `save_to`
#> →   Step 2: Searching for chk:: calls in function body
#> ℹ Loaded 182 chk package exports
#> ✔   Found 9 chk calls across 3 arguments: `x`, `percent`, and `proportion`
#> ℹ   No chk calls found for 7 arguments: `ci`, `level`, `nboot`, `min_pboot`, `parametric`, `samples`, and `save_to`
#> →   Step 3: Tracing indirect argument usage for 7 arguments
#> →     Tracing `ci`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `ci` maps to parameter `ci`
#> →       Recursively analyzing `hcp()` for `ci`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `ci`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 1 chk call across 1 argument: `ci`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 1 indirect chk call for `ci`
#> →     Tracing `level`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `level` maps to parameter `level`
#> →       Recursively analyzing `hcp()` for `level`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `level`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 2 chk calls across 1 argument: `level`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 2 indirect chk calls for `level`
#> →     Tracing `nboot`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `nboot` maps to parameter `nboot`
#> →       Recursively analyzing `hcp()` for `nboot`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `nboot`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 3 chk calls across 1 argument: `nboot`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 3 indirect chk calls for `nboot`
#> →     Tracing `min_pboot`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `min_pboot` maps to parameter `min_pboot`
#> →       Recursively analyzing `hcp()` for `min_pboot`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `min_pboot`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 2 chk calls across 1 argument: `min_pboot`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 2 indirect chk calls for `min_pboot`
#> →     Tracing `parametric`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `parametric` maps to parameter `parametric`
#> →       Recursively analyzing `hcp()` for `parametric`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `parametric`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 1 chk call across 1 argument: `parametric`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 1 indirect chk call for `parametric`
#> →     Tracing `samples`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `samples` maps to parameter `samples`
#> →       Recursively analyzing `hcp()` for `samples`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `samples`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 1 chk call across 1 argument: `samples`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 1 indirect chk call for `samples`
#> →     Tracing `save_to`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `save_to` maps to parameter `save_to`
#> →       Recursively analyzing `hcp()` for `save_to`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `save_to`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 1 chk call across 1 argument: `save_to`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 1 indirect chk call for `save_to`
#> →   Returning results for 10 arguments
#> ℹ   Non-generic function `ssd_hc.fitdists()` with 16 arguments: `x`, `percent`, `proportion`, `average`, `ci`, `level`, `nboot`, `min_pboot`, `multi_est`, `est_method`, `ci_method`, `parametric`, `delta`, `samples`, `save_to`, and `control`
#> →   Step 2: Searching for chk:: calls in function body
#> ✔   Found 8 chk calls across 4 arguments: `percent`, `proportion`, `multi_est`, and `ci_method`
#> ℹ   No chk calls found for 12 arguments: `x`, `average`, `ci`, `level`, `nboot`, `min_pboot`, `est_method`, `parametric`, `delta`, `samples`, `save_to`, and `control`
#> →   Step 3: Tracing indirect argument usage for 12 arguments
#> →     Tracing `x`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `x` maps to parameter `x`
#> →       Recursively analyzing `hcp()` for `x`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `x`
#> →     Step 2: Searching for chk:: calls in function body
#> !     No chk calls found
#> ℹ     No chk calls found for 1 argument: `x`
#> →     Step 3: Tracing indirect argument usage for 1 argument
#> →       Tracing `x`...
#> ℹ         First usage found in call to `subset()`
#> ℹ         Function has 1 formal: `x`
#> ℹ         Argument `x` maps to parameter `x`
#> →         Recursively analyzing `subset()` for `x`...
#> ℹ       Function `subset()` is an S3 generic
#> ℹ       Found 5 methods: `subset.data.frame()`, `subset.default()`, `subset.fitdists()`, `subset.matrix()`, and `subset.news_db()`
#> ℹ       Collected 6 unique arguments across all methods: `x`, `subset`, `select`, `drop`, `delta`, and `strict`
#> ℹ       Analyzing specific argument: `x`
#> →       Recursively analyzing each method...
#> ℹ         Non-generic function `subset.data.frame()`, analyzing argument: `x`
#> →         Step 2: Searching for chk:: calls in function body
#> !         No chk calls found
#> ℹ         No chk calls found for 1 argument: `x`
#> →         Step 3: Tracing indirect argument usage for 1 argument
#> →           Tracing `x`...
#> ℹ             First usage found in call to `nrow()`
#> ℹ             Function has 1 formal: `x`
#> ℹ             Argument `x` maps to parameter `x`
#> →             Recursively analyzing `nrow()` for `x`...
#> ℹ           Non-generic function `nrow()`, analyzing argument: `x`
#> →           Step 2: Searching for chk:: calls in function body
#> !           No chk calls found
#> ℹ           No chk calls found for 1 argument: `x`
#> →           Step 3: Tracing indirect argument usage for 1 argument
#> →             Tracing `x`...
#> ℹ               First usage found in call to `dim()`
#> ℹ               Function is a primitive (base)
#> →           Returning results for 1 argument
#> ✔             Found 0 indirect chk calls for `x`
#> →         Returning results for 1 argument
#> ℹ         Non-generic function `subset.default()`, analyzing argument: `x`
#> →         Step 2: Searching for chk:: calls in function body
#> !         No chk calls found
#> ℹ         No chk calls found for 1 argument: `x`
#> →         Step 3: Tracing indirect argument usage for 1 argument
#> →           Tracing `x`...
#> ℹ             First usage found in call to `[()`
#> ℹ             Function is a primitive (base)
#> →         Returning results for 1 argument
#> ℹ         Non-generic function `subset.fitdists()`, analyzing argument: `x`
#> →         Step 2: Searching for chk:: calls in function body
#> ✔         Found 2 chk calls across 1 argument: `x`
#> ℹ         All arguments have chk calls
#> →         Returning results for 1 argument
#> ℹ         Non-generic function `subset.matrix()`, analyzing argument: `x`
#> →         Step 2: Searching for chk:: calls in function body
#> !         No chk calls found
#> ℹ         No chk calls found for 1 argument: `x`
#> →         Step 3: Tracing indirect argument usage for 1 argument
#> →           Tracing `x`...
#> ℹ             First usage found in call to `ncol()`
#> ℹ             Function has 1 formal: `x`
#> ℹ             Argument `x` maps to parameter `x`
#> →             Recursively analyzing `ncol()` for `x`...
#> ℹ           Non-generic function `ncol()`, analyzing argument: `x`
#> →           Step 2: Searching for chk:: calls in function body
#> !           No chk calls found
#> ℹ           No chk calls found for 1 argument: `x`
#> →           Step 3: Tracing indirect argument usage for 1 argument
#> →             Tracing `x`...
#> ℹ               First usage found in call to `dim()`
#> ℹ               Function is a primitive (base)
#> →           Returning results for 1 argument
#> ✔             Found 0 indirect chk calls for `x`
#> →         Returning results for 1 argument
#> ℹ         Non-generic function `subset.news_db()`, analyzing argument: `x`
#> →         Step 2: Searching for chk:: calls in function body
#> !         No chk calls found
#> ℹ         No chk calls found for 1 argument: `x`
#> →         Step 3: Tracing indirect argument usage for 1 argument
#> →           Tracing `x`...
#> ℹ             First usage found in call to `list()`
#> ℹ             Function is a primitive (base)
#> →         Returning results for 1 argument
#> →       Combining results from all methods
#> ✔         Found 2 indirect chk calls for `x`
#> →     Returning results for 1 argument
#> ✔       Found 2 indirect chk calls for `x`
#> →     Tracing `average`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `average` maps to parameter `average`
#> →       Recursively analyzing `hcp()` for `average`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `average`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 1 chk call across 1 argument: `average`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 1 indirect chk call for `average`
#> →     Tracing `ci`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `ci` maps to parameter `ci`
#> →       Recursively analyzing `hcp()` for `ci`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `ci`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 1 chk call across 1 argument: `ci`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 1 indirect chk call for `ci`
#> →     Tracing `level`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `level` maps to parameter `level`
#> →       Recursively analyzing `hcp()` for `level`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `level`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 2 chk calls across 1 argument: `level`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 2 indirect chk calls for `level`
#> →     Tracing `nboot`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `nboot` maps to parameter `nboot`
#> →       Recursively analyzing `hcp()` for `nboot`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `nboot`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 3 chk calls across 1 argument: `nboot`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 3 indirect chk calls for `nboot`
#> →     Tracing `min_pboot`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `min_pboot` maps to parameter `min_pboot`
#> →       Recursively analyzing `hcp()` for `min_pboot`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `min_pboot`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 2 chk calls across 1 argument: `min_pboot`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 2 indirect chk calls for `min_pboot`
#> →     Tracing `est_method`...
#> ℹ       First usage found in call to `<-()`
#> ℹ       Function is a primitive (base)
#> →     Tracing `parametric`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `parametric` maps to parameter `parametric`
#> →       Recursively analyzing `hcp()` for `parametric`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `parametric`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 1 chk call across 1 argument: `parametric`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 1 indirect chk call for `parametric`
#> →     Tracing `delta`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `delta` maps to parameter `delta`
#> →       Recursively analyzing `hcp()` for `delta`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `delta`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 2 chk calls across 1 argument: `delta`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 2 indirect chk calls for `delta`
#> →     Tracing `samples`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `samples` maps to parameter `samples`
#> →       Recursively analyzing `hcp()` for `samples`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `samples`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 1 chk call across 1 argument: `samples`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 1 indirect chk call for `samples`
#> →     Tracing `save_to`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `save_to` maps to parameter `save_to`
#> →       Recursively analyzing `hcp()` for `save_to`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `save_to`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 1 chk call across 1 argument: `save_to`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 1 indirect chk call for `save_to`
#> →     Tracing `control`...
#> ℹ       First usage found in call to `hcp()`
#> ℹ       Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ       Argument `control` maps to parameter `control`
#> →       Recursively analyzing `hcp()` for `control`...
#> ℹ     Non-generic function `hcp()`, analyzing argument: `control`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 1 chk call across 1 argument: `control`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ✔       Found 1 indirect chk call for `control`
#> →   Returning results for 16 arguments
#> ℹ   Non-generic function `ssd_hc.list()` with 3 arguments: `x`, `percent`, and `proportion`
#> →   Step 2: Searching for chk:: calls in function body
#> ✔   Found 9 chk calls across 3 arguments: `x`, `percent`, and `proportion`
#> ℹ   All arguments have chk calls
#> →   Returning results for 3 arguments
#> → Combining results from all methods
#> {
#>     chk::chk_length(x, upper = 1L)
#>     chk::chk_named(x)
#>     chk::chk_subset(names(x), c("burrIII3", "invpareto", "llogis", 
#>         "lgumbel"))
#>     chk::chk_superset(names(x), select)
#>     chk::chk_list(x)
#>     chk::chk_unique(names(x))
#>     chk::chk_vector(percent)
#>     chk::chk_numeric(percent)
#>     chk::chk_range(percent, c(0, 100))
#>     chk::chk_vector(proportion)
#>     chk::chk_numeric(proportion)
#>     chk::chk_range(proportion)
#>     chk::chk_flag(ci)
#>     chk::chk_number(level)
#>     chk::chk_range(level)
#>     chk::chk_whole_number(nboot)
#>     chk::chk_gt(nboot)
#>     chk::chk_lt(nboot, 1e+09)
#>     chk::chk_number(min_pboot)
#>     chk::chk_range(min_pboot)
#>     chk::chk_flag(parametric)
#>     chk::chk_flag(samples)
#>     chk::chk_null_or(save_to, vld = vld_dir)
#>     chk::chk_flag(average)
#>     chk::chk_flag(multi_est)
#>     quote(FIXME_ADD_CHECK_CALL(est_method))
#>     chk::chk_string(ci_method)
#>     chk::chk_number(delta)
#>     chk::chk_gte(delta)
#>     chk::chk_null_or(control, vld = vld_list)
#> }



# Test with hc_seed()
combine_chk_calls(hc_seed)
Details
#> ℹ Non-generic function `<function>()` with 11 arguments: `data`, `sim`, `stream`, `nboot`, `est_method`, `ci_method`, `seed`, `proportion`, `ci`, `parametric`, and `save_to`
#> → Step 2: Searching for chk:: calls in function body
#> ! No chk calls found
#> ℹ No chk calls found for 11 arguments: `data`, `sim`, `stream`, `nboot`, `est_method`, `ci_method`, `seed`, `proportion`, `ci`, `parametric`, and `save_to`
#> → Step 3: Tracing indirect argument usage for 11 arguments
#> →   Tracing `data`...
#> ℹ     First usage found in call to `ssdtools::ssd_hc()`
#> ℹ     Function has 1 formal: `x`
#> ℹ     Argument `data` maps to parameter `x`
#> →     Recursively analyzing `ssdtools::ssd_hc()` for `x`...
#> ℹ   Function `ssdtools::ssd_hc()` is an S3 generic
#> ℹ   Found 3 methods: `ssd_hc.fitburrlioz()`, `ssd_hc.fitdists()`, and `ssd_hc.list()`
#> ℹ   Collected 16 unique arguments across all methods: `x`, `percent`, `proportion`, `ci`, `level`, `nboot`, `min_pboot`, `parametric`, `samples`, `save_to`, `average`, `multi_est`, `est_method`, `ci_method`, `delta`, and `control`
#> ℹ   Analyzing specific argument: `x`
#> →   Recursively analyzing each method...
#> ℹ     Non-generic function `ssd_hc.fitburrlioz()`, analyzing argument: `x`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 3 chk calls across 1 argument: `x`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ℹ     Non-generic function `ssd_hc.fitdists()`, analyzing argument: `x`
#> →     Step 2: Searching for chk:: calls in function body
#> !     No chk calls found
#> ℹ     No chk calls found for 1 argument: `x`
#> →     Step 3: Tracing indirect argument usage for 1 argument
#> →       Tracing `x`...
#> ℹ         First usage found in call to `hcp()`
#> ℹ         Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ         Argument `x` maps to parameter `x`
#> →         Recursively analyzing `hcp()` for `x`...
#> ℹ       Non-generic function `hcp()`, analyzing argument: `x`
#> →       Step 2: Searching for chk:: calls in function body
#> !       No chk calls found
#> ℹ       No chk calls found for 1 argument: `x`
#> →       Step 3: Tracing indirect argument usage for 1 argument
#> →         Tracing `x`...
#> ℹ           First usage found in call to `subset()`
#> ℹ           Function has 1 formal: `x`
#> ℹ           Argument `x` maps to parameter `x`
#> →           Recursively analyzing `subset()` for `x`...
#> ℹ         Function `subset()` is an S3 generic
#> ℹ         Found 5 methods: `subset.data.frame()`, `subset.default()`, `subset.fitdists()`, `subset.matrix()`, and `subset.news_db()`
#> ℹ         Collected 6 unique arguments across all methods: `x`, `subset`, `select`, `drop`, `delta`, and `strict`
#> ℹ         Analyzing specific argument: `x`
#> →         Recursively analyzing each method...
#> ℹ           Non-generic function `subset.data.frame()`, analyzing argument: `x`
#> →           Step 2: Searching for chk:: calls in function body
#> !           No chk calls found
#> ℹ           No chk calls found for 1 argument: `x`
#> →           Step 3: Tracing indirect argument usage for 1 argument
#> →             Tracing `x`...
#> ℹ               First usage found in call to `nrow()`
#> ℹ               Function has 1 formal: `x`
#> ℹ               Argument `x` maps to parameter `x`
#> →               Recursively analyzing `nrow()` for `x`...
#> ℹ             Non-generic function `nrow()`, analyzing argument: `x`
#> →             Step 2: Searching for chk:: calls in function body
#> !             No chk calls found
#> ℹ             No chk calls found for 1 argument: `x`
#> →             Step 3: Tracing indirect argument usage for 1 argument
#> →               Tracing `x`...
#> ℹ                 First usage found in call to `dim()`
#> ℹ                 Function is a primitive (base)
#> →             Returning results for 1 argument
#> ✔               Found 0 indirect chk calls for `x`
#> →           Returning results for 1 argument
#> ℹ           Non-generic function `subset.default()`, analyzing argument: `x`
#> →           Step 2: Searching for chk:: calls in function body
#> !           No chk calls found
#> ℹ           No chk calls found for 1 argument: `x`
#> →           Step 3: Tracing indirect argument usage for 1 argument
#> →             Tracing `x`...
#> ℹ               First usage found in call to `[()`
#> ℹ               Function is a primitive (base)
#> →           Returning results for 1 argument
#> ℹ           Non-generic function `subset.fitdists()`, analyzing argument: `x`
#> →           Step 2: Searching for chk:: calls in function body
#> ✔           Found 2 chk calls across 1 argument: `x`
#> ℹ           All arguments have chk calls
#> →           Returning results for 1 argument
#> ℹ           Non-generic function `subset.matrix()`, analyzing argument: `x`
#> →           Step 2: Searching for chk:: calls in function body
#> !           No chk calls found
#> ℹ           No chk calls found for 1 argument: `x`
#> →           Step 3: Tracing indirect argument usage for 1 argument
#> →             Tracing `x`...
#> ℹ               First usage found in call to `ncol()`
#> ℹ               Function has 1 formal: `x`
#> ℹ               Argument `x` maps to parameter `x`
#> →               Recursively analyzing `ncol()` for `x`...
#> ℹ             Non-generic function `ncol()`, analyzing argument: `x`
#> →             Step 2: Searching for chk:: calls in function body
#> !             No chk calls found
#> ℹ             No chk calls found for 1 argument: `x`
#> →             Step 3: Tracing indirect argument usage for 1 argument
#> →               Tracing `x`...
#> ℹ                 First usage found in call to `dim()`
#> ℹ                 Function is a primitive (base)
#> →             Returning results for 1 argument
#> ✔               Found 0 indirect chk calls for `x`
#> →           Returning results for 1 argument
#> ℹ           Non-generic function `subset.news_db()`, analyzing argument: `x`
#> →           Step 2: Searching for chk:: calls in function body
#> !           No chk calls found
#> ℹ           No chk calls found for 1 argument: `x`
#> →           Step 3: Tracing indirect argument usage for 1 argument
#> →             Tracing `x`...
#> ℹ               First usage found in call to `list()`
#> ℹ               Function is a primitive (base)
#> →           Returning results for 1 argument
#> →         Combining results from all methods
#> ✔           Found 2 indirect chk calls for `x`
#> →       Returning results for 1 argument
#> ✔         Found 2 indirect chk calls for `x`
#> →     Returning results for 1 argument
#> ℹ     Non-generic function `ssd_hc.list()`, analyzing argument: `x`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 3 chk calls across 1 argument: `x`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> →   Combining results from all methods
#> ✔     Found 6 indirect chk calls for `data`
#> →   Tracing `sim`...
#> ℹ     First usage found in call to `get_lecuyer_cmrg_seed_stream()`
#> ℹ     Function has 3 formals: `seed`, `stream`, and `start_sim`
#> ℹ     Argument `sim` maps to parameter `start_sim`
#> →     Recursively analyzing `get_lecuyer_cmrg_seed_stream()` for `start_sim`...
#> ℹ   Non-generic function `get_lecuyer_cmrg_seed_stream()`, analyzing argument: `start_sim`
#> →   Step 2: Searching for chk:: calls in function body
#> !   No chk calls found
#> ℹ   No chk calls found for 1 argument: `start_sim`
#> →   Step 3: Tracing indirect argument usage for 1 argument
#> →     Tracing `start_sim`...
#> ℹ       First usage found in call to `get_lecuyer_cmrg_seeds_stream()`
#> ℹ       Function has 4 formals: `seed`, `nsim`, `stream`, and `start_sim`
#> ℹ       Argument `start_sim` maps to parameter `start_sim`
#> →       Recursively analyzing `get_lecuyer_cmrg_seeds_stream()` for `start_sim`...
#> ℹ     Non-generic function `get_lecuyer_cmrg_seeds_stream()`, analyzing argument: `start_sim`
#> →     Step 2: Searching for chk:: calls in function body
#> !     No chk calls found
#> ℹ     No chk calls found for 1 argument: `start_sim`
#> →     Step 3: Tracing indirect argument usage for 1 argument
#> →       Tracing `start_sim`...
#> ℹ         First usage found in call to `-()`
#> ℹ         Function is a primitive (base)
#> →     Returning results for 1 argument
#> ✔       Found 0 indirect chk calls for `start_sim`
#> →   Returning results for 1 argument
#> ✔     Found 0 indirect chk calls for `sim`
#> →   Tracing `stream`...
#> ℹ     First usage found in call to `get_lecuyer_cmrg_seed_stream()`
#> ℹ     Function has 3 formals: `seed`, `stream`, and `start_sim`
#> ℹ     Argument `stream` maps to parameter `stream`
#> →     Recursively analyzing `get_lecuyer_cmrg_seed_stream()` for `stream`...
#> ℹ   Non-generic function `get_lecuyer_cmrg_seed_stream()`, analyzing argument: `stream`
#> →   Step 2: Searching for chk:: calls in function body
#> !   No chk calls found
#> ℹ   No chk calls found for 1 argument: `stream`
#> →   Step 3: Tracing indirect argument usage for 1 argument
#> →     Tracing `stream`...
#> ℹ       First usage found in call to `get_lecuyer_cmrg_seeds_stream()`
#> ℹ       Function has 4 formals: `seed`, `nsim`, `stream`, and `start_sim`
#> ℹ       Argument `stream` maps to parameter `stream`
#> →       Recursively analyzing `get_lecuyer_cmrg_seeds_stream()` for `stream`...
#> ℹ     Non-generic function `get_lecuyer_cmrg_seeds_stream()`, analyzing argument: `stream`
#> →     Step 2: Searching for chk:: calls in function body
#> !     No chk calls found
#> ℹ     No chk calls found for 1 argument: `stream`
#> →     Step 3: Tracing indirect argument usage for 1 argument
#> →       Tracing `stream`...
#> ℹ         First usage found in call to `-()`
#> ℹ         Function is a primitive (base)
#> →     Returning results for 1 argument
#> ✔       Found 0 indirect chk calls for `stream`
#> →   Returning results for 1 argument
#> ✔     Found 0 indirect chk calls for `stream`
#> →   Tracing `nboot`...
#> ℹ     First usage found in call to `ssdtools::ssd_hc()`
#> ℹ     Function has 1 formal: `x`
#> ℹ     Argument `nboot` maps to parameter `nboot`
#> →     Recursively analyzing `ssdtools::ssd_hc()` for `nboot`...
#> ℹ   Function `ssdtools::ssd_hc()` is an S3 generic
#> ℹ   Found 3 methods: `ssd_hc.fitburrlioz()`, `ssd_hc.fitdists()`, and `ssd_hc.list()`
#> ℹ   Collected 16 unique arguments across all methods: `x`, `percent`, `proportion`, `ci`, `level`, `nboot`, `min_pboot`, `parametric`, `samples`, `save_to`, `average`, `multi_est`, `est_method`, `ci_method`, `delta`, and `control`
#> ℹ   Analyzing specific argument: `nboot`
#> →   Recursively analyzing each method...
#> ℹ     Non-generic function `ssd_hc.fitburrlioz()`, analyzing argument: `nboot`
#> →     Step 2: Searching for chk:: calls in function body
#> !     No chk calls found
#> ℹ     No chk calls found for 1 argument: `nboot`
#> →     Step 3: Tracing indirect argument usage for 1 argument
#> →       Tracing `nboot`...
#> ℹ         First usage found in call to `hcp()`
#> ℹ         Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ         Argument `nboot` maps to parameter `nboot`
#> →         Recursively analyzing `hcp()` for `nboot`...
#> ℹ       Non-generic function `hcp()`, analyzing argument: `nboot`
#> →       Step 2: Searching for chk:: calls in function body
#> ✔       Found 3 chk calls across 1 argument: `nboot`
#> ℹ       All arguments have chk calls
#> →       Returning results for 1 argument
#> ✔         Found 3 indirect chk calls for `nboot`
#> →     Returning results for 1 argument
#> ℹ     Non-generic function `ssd_hc.fitdists()`, analyzing argument: `nboot`
#> →     Step 2: Searching for chk:: calls in function body
#> !     No chk calls found
#> ℹ     No chk calls found for 1 argument: `nboot`
#> →     Step 3: Tracing indirect argument usage for 1 argument
#> →       Tracing `nboot`...
#> ℹ         First usage found in call to `hcp()`
#> ℹ         Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ         Argument `nboot` maps to parameter `nboot`
#> →         Recursively analyzing `hcp()` for `nboot`...
#> ℹ       Non-generic function `hcp()`, analyzing argument: `nboot`
#> →       Step 2: Searching for chk:: calls in function body
#> ✔       Found 3 chk calls across 1 argument: `nboot`
#> ℹ       All arguments have chk calls
#> →       Returning results for 1 argument
#> ✔         Found 3 indirect chk calls for `nboot`
#> →     Returning results for 1 argument
#> ℹ     Skipping `ssd_hc.list()` - does not have argument `nboot`
#> →   Combining results from all methods
#> ✔     Found 3 indirect chk calls for `nboot`
#> →   Tracing `est_method`...
#> ℹ     First usage found in call to `ssdtools::ssd_hc()`
#> ℹ     Function has 1 formal: `x`
#> ℹ     Argument `est_method` maps to parameter `est_method`
#> →     Recursively analyzing `ssdtools::ssd_hc()` for `est_method`...
#> ℹ   Function `ssdtools::ssd_hc()` is an S3 generic
#> ℹ   Found 3 methods: `ssd_hc.fitburrlioz()`, `ssd_hc.fitdists()`, and `ssd_hc.list()`
#> ℹ   Collected 16 unique arguments across all methods: `x`, `percent`, `proportion`, `ci`, `level`, `nboot`, `min_pboot`, `parametric`, `samples`, `save_to`, `average`, `multi_est`, `est_method`, `ci_method`, `delta`, and `control`
#> ℹ   Analyzing specific argument: `est_method`
#> →   Recursively analyzing each method...
#> ℹ     Skipping `ssd_hc.fitburrlioz()` - does not have argument `est_method`
#> ℹ     Non-generic function `ssd_hc.fitdists()`, analyzing argument: `est_method`
#> →     Step 2: Searching for chk:: calls in function body
#> !     No chk calls found
#> ℹ     No chk calls found for 1 argument: `est_method`
#> →     Step 3: Tracing indirect argument usage for 1 argument
#> →       Tracing `est_method`...
#> ℹ         First usage found in call to `<-()`
#> ℹ         Function is a primitive (base)
#> →     Returning results for 1 argument
#> ℹ     Skipping `ssd_hc.list()` - does not have argument `est_method`
#> →   Combining results from all methods
#> ✔     Found 0 indirect chk calls for `est_method`
#> →   Tracing `ci_method`...
#> ℹ     First usage found in call to `ssdtools::ssd_hc()`
#> ℹ     Function has 1 formal: `x`
#> ℹ     Argument `ci_method` maps to parameter `ci_method`
#> →     Recursively analyzing `ssdtools::ssd_hc()` for `ci_method`...
#> ℹ   Function `ssdtools::ssd_hc()` is an S3 generic
#> ℹ   Found 3 methods: `ssd_hc.fitburrlioz()`, `ssd_hc.fitdists()`, and `ssd_hc.list()`
#> ℹ   Collected 16 unique arguments across all methods: `x`, `percent`, `proportion`, `ci`, `level`, `nboot`, `min_pboot`, `parametric`, `samples`, `save_to`, `average`, `multi_est`, `est_method`, `ci_method`, `delta`, and `control`
#> ℹ   Analyzing specific argument: `ci_method`
#> →   Recursively analyzing each method...
#> ℹ     Skipping `ssd_hc.fitburrlioz()` - does not have argument `ci_method`
#> ℹ     Non-generic function `ssd_hc.fitdists()`, analyzing argument: `ci_method`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 1 chk call across 1 argument: `ci_method`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ℹ     Skipping `ssd_hc.list()` - does not have argument `ci_method`
#> →   Combining results from all methods
#> ✔     Found 1 indirect chk call for `ci_method`
#> →   Tracing `seed`...
#> ℹ     First usage found in call to `get_lecuyer_cmrg_seed_stream()`
#> ℹ     Function has 3 formals: `seed`, `stream`, and `start_sim`
#> ℹ     Argument `seed` maps to parameter `seed`
#> →     Recursively analyzing `get_lecuyer_cmrg_seed_stream()` for `seed`...
#> ℹ   Non-generic function `get_lecuyer_cmrg_seed_stream()`, analyzing argument: `seed`
#> →   Step 2: Searching for chk:: calls in function body
#> !   No chk calls found
#> ℹ   No chk calls found for 1 argument: `seed`
#> →   Step 3: Tracing indirect argument usage for 1 argument
#> →     Tracing `seed`...
#> ℹ       First usage found in call to `get_lecuyer_cmrg_seeds_stream()`
#> ℹ       Function has 4 formals: `seed`, `nsim`, `stream`, and `start_sim`
#> ℹ       Argument `seed` maps to parameter `seed`
#> →       Recursively analyzing `get_lecuyer_cmrg_seeds_stream()` for `seed`...
#> ℹ     Non-generic function `get_lecuyer_cmrg_seeds_stream()`, analyzing argument: `seed`
#> →     Step 2: Searching for chk:: calls in function body
#> !     No chk calls found
#> ℹ     No chk calls found for 1 argument: `seed`
#> →     Step 3: Tracing indirect argument usage for 1 argument
#> →       Tracing `seed`...
#> ℹ         First usage found in call to `is.null()`
#> ℹ         Function is a primitive (base)
#> →     Returning results for 1 argument
#> ✔       Found 0 indirect chk calls for `seed`
#> →   Returning results for 1 argument
#> ✔     Found 0 indirect chk calls for `seed`
#> →   Tracing `proportion`...
#> ℹ     First usage found in call to `ssdtools::ssd_hc()`
#> ℹ     Function has 1 formal: `x`
#> ℹ     Argument `proportion` maps to parameter `proportion`
#> →     Recursively analyzing `ssdtools::ssd_hc()` for `proportion`...
#> ℹ   Function `ssdtools::ssd_hc()` is an S3 generic
#> ℹ   Found 3 methods: `ssd_hc.fitburrlioz()`, `ssd_hc.fitdists()`, and `ssd_hc.list()`
#> ℹ   Collected 16 unique arguments across all methods: `x`, `percent`, `proportion`, `ci`, `level`, `nboot`, `min_pboot`, `parametric`, `samples`, `save_to`, `average`, `multi_est`, `est_method`, `ci_method`, `delta`, and `control`
#> ℹ   Analyzing specific argument: `proportion`
#> →   Recursively analyzing each method...
#> ℹ     Non-generic function `ssd_hc.fitburrlioz()`, analyzing argument: `proportion`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 3 chk calls across 1 argument: `proportion`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ℹ     Non-generic function `ssd_hc.fitdists()`, analyzing argument: `proportion`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 3 chk calls across 1 argument: `proportion`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> ℹ     Non-generic function `ssd_hc.list()`, analyzing argument: `proportion`
#> →     Step 2: Searching for chk:: calls in function body
#> ✔     Found 3 chk calls across 1 argument: `proportion`
#> ℹ     All arguments have chk calls
#> →     Returning results for 1 argument
#> →   Combining results from all methods
#> ✔     Found 3 indirect chk calls for `proportion`
#> →   Tracing `ci`...
#> ℹ     First usage found in call to `ssdtools::ssd_hc()`
#> ℹ     Function has 1 formal: `x`
#> ℹ     Argument `ci` maps to parameter `ci`
#> →     Recursively analyzing `ssdtools::ssd_hc()` for `ci`...
#> ℹ   Function `ssdtools::ssd_hc()` is an S3 generic
#> ℹ   Found 3 methods: `ssd_hc.fitburrlioz()`, `ssd_hc.fitdists()`, and `ssd_hc.list()`
#> ℹ   Collected 16 unique arguments across all methods: `x`, `percent`, `proportion`, `ci`, `level`, `nboot`, `min_pboot`, `parametric`, `samples`, `save_to`, `average`, `multi_est`, `est_method`, `ci_method`, `delta`, and `control`
#> ℹ   Analyzing specific argument: `ci`
#> →   Recursively analyzing each method...
#> ℹ     Non-generic function `ssd_hc.fitburrlioz()`, analyzing argument: `ci`
#> →     Step 2: Searching for chk:: calls in function body
#> !     No chk calls found
#> ℹ     No chk calls found for 1 argument: `ci`
#> →     Step 3: Tracing indirect argument usage for 1 argument
#> →       Tracing `ci`...
#> ℹ         First usage found in call to `hcp()`
#> ℹ         Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ         Argument `ci` maps to parameter `ci`
#> →         Recursively analyzing `hcp()` for `ci`...
#> ℹ       Non-generic function `hcp()`, analyzing argument: `ci`
#> →       Step 2: Searching for chk:: calls in function body
#> ✔       Found 1 chk call across 1 argument: `ci`
#> ℹ       All arguments have chk calls
#> →       Returning results for 1 argument
#> ✔         Found 1 indirect chk call for `ci`
#> →     Returning results for 1 argument
#> ℹ     Non-generic function `ssd_hc.fitdists()`, analyzing argument: `ci`
#> →     Step 2: Searching for chk:: calls in function body
#> !     No chk calls found
#> ℹ     No chk calls found for 1 argument: `ci`
#> →     Step 3: Tracing indirect argument usage for 1 argument
#> →       Tracing `ci`...
#> ℹ         First usage found in call to `hcp()`
#> ℹ         Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ         Argument `ci` maps to parameter `ci`
#> →         Recursively analyzing `hcp()` for `ci`...
#> ℹ       Non-generic function `hcp()`, analyzing argument: `ci`
#> →       Step 2: Searching for chk:: calls in function body
#> ✔       Found 1 chk call across 1 argument: `ci`
#> ℹ       All arguments have chk calls
#> →       Returning results for 1 argument
#> ✔         Found 1 indirect chk call for `ci`
#> →     Returning results for 1 argument
#> ℹ     Skipping `ssd_hc.list()` - does not have argument `ci`
#> →   Combining results from all methods
#> ✔     Found 1 indirect chk call for `ci`
#> →   Tracing `parametric`...
#> ℹ     First usage found in call to `ssdtools::ssd_hc()`
#> ℹ     Function has 1 formal: `x`
#> ℹ     Argument `parametric` maps to parameter `parametric`
#> →     Recursively analyzing `ssdtools::ssd_hc()` for `parametric`...
#> ℹ   Function `ssdtools::ssd_hc()` is an S3 generic
#> ℹ   Found 3 methods: `ssd_hc.fitburrlioz()`, `ssd_hc.fitdists()`, and `ssd_hc.list()`
#> ℹ   Collected 16 unique arguments across all methods: `x`, `percent`, `proportion`, `ci`, `level`, `nboot`, `min_pboot`, `parametric`, `samples`, `save_to`, `average`, `multi_est`, `est_method`, `ci_method`, `delta`, and `control`
#> ℹ   Analyzing specific argument: `parametric`
#> →   Recursively analyzing each method...
#> ℹ     Non-generic function `ssd_hc.fitburrlioz()`, analyzing argument: `parametric`
#> →     Step 2: Searching for chk:: calls in function body
#> !     No chk calls found
#> ℹ     No chk calls found for 1 argument: `parametric`
#> →     Step 3: Tracing indirect argument usage for 1 argument
#> →       Tracing `parametric`...
#> ℹ         First usage found in call to `hcp()`
#> ℹ         Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ         Argument `parametric` maps to parameter `parametric`
#> →         Recursively analyzing `hcp()` for `parametric`...
#> ℹ       Non-generic function `hcp()`, analyzing argument: `parametric`
#> →       Step 2: Searching for chk:: calls in function body
#> ✔       Found 1 chk call across 1 argument: `parametric`
#> ℹ       All arguments have chk calls
#> →       Returning results for 1 argument
#> ✔         Found 1 indirect chk call for `parametric`
#> →     Returning results for 1 argument
#> ℹ     Non-generic function `ssd_hc.fitdists()`, analyzing argument: `parametric`
#> →     Step 2: Searching for chk:: calls in function body
#> !     No chk calls found
#> ℹ     No chk calls found for 1 argument: `parametric`
#> →     Step 3: Tracing indirect argument usage for 1 argument
#> →       Tracing `parametric`...
#> ℹ         First usage found in call to `hcp()`
#> ℹ         Function has 16 formals: `x`, `value`, `ci`, `level`, `nboot`, `average`, `est_method`, `delta`, `min_pboot`, `parametric`, `ci_method`, `control`, `samples`, `save_to`, `hc`, and `fun`
#> ℹ         Argument `parametric` maps to parameter `parametric`
#> →         Recursively analyzing `hcp()` for `parametric`...
#> ℹ       Non-generic function `hcp()`, analyzing argument: `parametric`
#> →       Step 2: Searching for chk:: calls in function body
#> ✔       Found 1 chk call across 1 argument: `parametric`
#> ℹ       All arguments have chk calls
#> →       Returning results for 1 argument
#> ✔         Found 1 indirect chk call for `parametric`
#> →     Returning results for 1 argument
#> ℹ     Skipping `ssd_hc.list()` - does not have argument `parametric`
#> →   Combining results from all methods
#> ✔     Found 1 indirect chk call for `parametric`
#> →   Tracing `save_to`...
#> !     No usage found for `save_to`
#> → Returning results for 11 arguments
#> {
#>     chk::chk_length(x, upper = 1L)
#>     chk::chk_named(x)
#>     chk::chk_subset(names(x), c("burrIII3", "invpareto", "llogis", 
#>         "lgumbel"))
#>     chk::chk_superset(names(x), select)
#>     chk::chk_list(x)
#>     chk::chk_unique(names(x))
#>     quote(FIXME_ADD_CHECK_CALL(sim))
#>     quote(FIXME_ADD_CHECK_CALL(stream))
#>     chk::chk_whole_number(nboot)
#>     chk::chk_gt(nboot)
#>     chk::chk_lt(nboot, 1e+09)
#>     quote(FIXME_ADD_CHECK_CALL(est_method))
#>     chk::chk_string(ci_method)
#>     quote(FIXME_ADD_CHECK_CALL(seed))
#>     chk::chk_vector(proportion)
#>     chk::chk_numeric(proportion)
#>     chk::chk_range(proportion)
#>     chk::chk_flag(ci)
#>     chk::chk_flag(parametric)
#>     quote(FIXME_ADD_CHECK_CALL(save_to))
#> }

Created on 2025-11-18 with reprex v2.1.1

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a utility system for recursively extracting chk_() validation calls from function bodies to enable upfront validation of scenario data frames. The system analyzes functions (including S3 generics and their methods), identifies all checker function calls, and traces indirect validation through helper functions.

Key Changes:

  • New recursive checker extraction system with S3 generic support
  • Comprehensive test suite with snapshot testing for the new functionality
  • Helper infrastructure for memoizing chk package exports

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
R/chk-infer.R Core implementation for recursively extracting chk validation calls from function bodies, including indirect tracing through helper functions
R/chk-infer-s3.R S3 generic handling logic that collects and combines validation calls from all methods of a generic function
R/chk.R Helper function to retrieve and cache chk package exports for identifying validation calls
R/zzz.R Package load hook to memoize the chk exports function
tests/testthat/test-chk-infer.R Comprehensive tests for the core inference logic with various scenarios (direct calls, indirect calls, nested functions)
tests/testthat/test-chk-infer-s3.R Tests specifically for S3 generic handling including method collection, argument mapping, and result combination
tests/testthat/_snaps/chk-infer.md Snapshot tests capturing expected output for various extraction scenarios
tests/testthat/_snaps/chk-infer-s3.md Snapshot tests for S3-specific extraction scenarios
tests/testthat/test-fit-dists-sims.R Added pillar option configuration to ensure consistent test output across environments

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread R/zzz.R
@@ -0,0 +1,3 @@
.onLoad <- function(libname, pkgname) {
get_chk_exports <<- memoise::memoise(get_chk_exports)

Copilot AI Nov 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The package memoise is used via memoise::memoise() but is not declared in the DESCRIPTION file under Imports or Suggests. This will cause the package to fail when loading if memoise is not installed.

Please add memoise to the Imports field in the DESCRIPTION file.

Copilot uses AI. Check for mistakes.
Comment thread R/chk-infer.R
Comment thread R/chk-infer.R
Comment thread R/chk-infer-s3.R
Comment thread R/chk-infer.R

if (is.call(expr)) {
# First, recursively search in nested calls to find innermost usage
innermost_result <- NULL

Copilot AI Nov 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable innermost_result is assigned but never used. It can be safely removed.

Consider removing this line as it serves no purpose in the current implementation.

Suggested change
innermost_result <- NULL

Copilot uses AI. Check for mistakes.
Comment thread R/chk-infer.R

# Find the first usage of an argument in the function body
# Returns the innermost call that contains the argument
find_first_usage <- function(expr, arg_name, depth = 0) {

Copilot AI Nov 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The parameter depth is passed through recursive calls but never actually used in the function body. If it's not needed for future functionality, consider removing it to simplify the function signature.

Copilot uses AI. Check for mistakes.
Comment thread R/chk-infer-s3.R
Comment on lines +107 to +117
for (expr in all_exprs) {
# Check if this expression is already in unique_exprs
is_duplicate <- FALSE
for (unique_expr in unique_exprs) {
if (identical(expr, unique_expr)) {
is_duplicate <- TRUE
break
}
}
if (!is_duplicate) {
unique_exprs[[length(unique_exprs) + 1]] <- expr

Copilot AI Nov 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The nested loop structure for deduplication has O(n²) time complexity. For each expression in all_exprs, it iterates through all expressions in unique_exprs to check for duplicates. This could be inefficient when dealing with many expressions.

Consider using a more efficient approach, such as:

  1. Converting expressions to strings and using a set/hash for O(1) lookups
  2. Using unique() with a custom comparison function if possible
  3. Or accepting the current approach if the number of expressions is expected to be small
Suggested change
for (expr in all_exprs) {
# Check if this expression is already in unique_exprs
is_duplicate <- FALSE
for (unique_expr in unique_exprs) {
if (identical(expr, unique_expr)) {
is_duplicate <- TRUE
break
}
}
if (!is_duplicate) {
unique_exprs[[length(unique_exprs) + 1]] <- expr
seen_exprs <- character()
for (expr in all_exprs) {
expr_str <- if (exists("deparse1", mode = "function")) deparse1(expr) else paste(deparse(expr), collapse = "")
if (!(expr_str %in% seen_exprs)) {
unique_exprs[[length(unique_exprs) + 1]] <- expr
seen_exprs <- c(seen_exprs, expr_str)

Copilot uses AI. Check for mistakes.
Comment thread R/chk-infer.R
)
arg_results
}

Copilot AI Nov 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The function combine_chk_calls() appears to be a main entry point for this feature (based on the PR description's example usage) but lacks roxygen2 documentation. Even for internal/build-time functions, basic documentation would help users understand:

  • What the function does
  • What parameters it accepts
  • What it returns
  • Example usage

Consider adding roxygen2 documentation with at minimum @param, @return, and @examples tags.

Suggested change
#' Combine chk validation calls for all arguments of a function
#'
#' Extracts chk validation calls for each argument of the given function and combines them
#' into a single expression. If an argument does not have a chk call, a placeholder is inserted.
#'
#' @param fun A function object to analyze for chk validation calls.
#' @return An expression combining all chk calls (and placeholders) for the function's arguments.
#' @examples
#' combine_chk_calls(function(x, y) { chk::chk_numeric(x); chk::chk_integer(y) })

Copilot uses AI. Check for mistakes.
Comment thread R/chk-infer.R
arg_results
}

# Main function to extract chk function calls by argument

Copilot AI Nov 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The function extract_chk_calls() is a key function in this feature but lacks roxygen2 documentation. Even for internal functions, basic documentation would improve maintainability. Consider adding documentation that explains:

  • The purpose of the function
  • The recursive extraction strategy
  • Parameters (especially .depth which controls recursion)
  • Return value structure
  • How it handles S3 generics vs regular functions
Suggested change
# Main function to extract chk function calls by argument
#' Extract chk validation calls by argument from a function
#'
#' Recursively analyzes a function to extract calls to chk validation functions
#' for each argument. If the function is an S3 generic, all methods are analyzed
#' recursively and results are combined. For regular functions, the body is
#' traversed to find chk calls associated with each argument.
#'
#' @param fun The function object to analyze.
#' @param arg Optional. The name of the argument to focus on. If NULL, all arguments are considered.
#' @param fun_name Optional. The name of the function (for messaging). If NULL, defaults to "<function>".
#' @param .depth Internal. Tracks recursion depth for indentation and messaging. Should not be set by users.
#'
#' @return A named list where each element corresponds to a function argument and contains
#' the extracted chk validation calls (as language objects). If no chk calls are found for
#' an argument, the element is an empty list.
#'
#' @details
#' - For S3 generics, all methods are analyzed recursively and results are merged.
#' - For regular functions, the body is traversed to find chk calls for each argument.
#' - The function uses `.depth` to control recursion and indentation for verbose messaging.
#' - Handles both S3 generics and regular functions appropriately.
#'
#' @keywords internal

Copilot uses AI. Check for mistakes.
@poissonconsulting poissonconsulting deleted a comment from Copilot AI Dec 2, 2025
@joethorley

Copy link
Copy Markdown
Member

Joe

Fix

combine_chk_calls(ssdtools::ssd_fit_dists)

@joethorley

Copy link
Copy Markdown
Member
> devtools::load_all()
ℹ Loading ssdsims
> combine_chk_calls(ssdtools::ssd_fit_dists)

→ Returning results for 17 arguments
{
    chk::check_names(data, names = names(values))
    chk::check_data(data, values, nrow = c(nrow, Inf))
    chk::chk_string(left)
    chk::chk_not_subset(left, c("right", "weight"))
    chk::chk_string(right)
    chk::chk_not_subset(right, c("left", "weight"))
    chk::chk_null_or(weight, vld = vld_string)
    chk::chk_null_or(weight, vld = vld_not_subset, values = c("left", 
        "right"))
    chk::abort_chk("`data` has %n row%s with zero weight in '", 
        weight, "'", n = sum(zero_weight))
    chk::abort_chk("`data` has %n row%s with Inf weight in '", 
        weight, "'", n = sum(inf_weight))
    chk::chk_character_or_factor(dists)
    chk::chk_vector(dists)
    chk::check_dim(dists, values = TRUE)
    chk::chk_not_any_na(dists)
    chk::chk_unique(dists)
    chk::chk_subset(dists, ssd_dists_all(valid = NULL))
    chk::chk_whole_number(nrow)
    chk::chk_gte(nrow, 4L)
    chk::chkor_vld(vld_flag(rescale), vld_string(rescale))
    chk::chk_subset(rescale, c("no", "geomean", "odds"))
    chk::chk_number(odds_max)
    chk::chk_range(odds_max, inclusive = FALSE)
    chk::chk_flag(reweight)
    chk::chk_flag(computable)
    chk::chk_flag(at_boundary_ok)
    chk::chk_flag(all_dists)
    chk::chk_number(min_pmix)
    chk::chk_range(min_pmix, c(0, 0.5))
    chk::chk_numeric(range_shape1)
    chk::chk_vector(range_shape1)
    chk::check_dim(range_shape1, values = 2)
    chk::chk_not_any_na(range_shape1)
    chk::chk_gte(range_shape1)
    chk::chk_sorted(range_shape1)
    chk::chk_numeric(range_shape2)
    chk::chk_vector(range_shape2)
    chk::check_dim(range_shape2, values = 2)
    chk::chk_not_any_na(range_shape2)
    chk::chk_gte(range_shape2)
    chk::chk_sorted(range_shape2)
    chk::chk_list(control)
    chk::chk_flag(silent)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants