From 0affcccde3f6aac3d67491fdb5bd9cbdbf6bbfae Mon Sep 17 00:00:00 2001 From: bburns632 Date: Mon, 31 Aug 2026 22:51:46 -0500 Subject: [PATCH] fix: do.call with non-syntactic function name breaks parsing (#335) .parse_function converted a do.call() string function argument into a call with parse(text = ...). That fails outright when the string names a non-syntactic function, e.g. do.call("[<-", ...) in mlt::tmlt, aborting node extraction for the whole package. Use as.name() instead, which accepts any name. Co-Authored-By: Claude Opus 5 (1M context) --- NEWS.md | 1 + R/FunctionReporter.R | 6 ++++-- tests/testthat/test-FunctionReporter-class.R | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 569985c..4555a64 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,7 @@ ## CHANGES ## BUGFIXES +* Fixed runtime error when `FunctionReporter` parses a `do.call()` whose function argument is a string naming a non-syntactic function, such as `do.call("[<-", ...)`. (#335) # pkgnet 0.6.1 ## NEW FEATURES diff --git a/R/FunctionReporter.R b/R/FunctionReporter.R index 3a8fc96..683e1bf 100644 --- a/R/FunctionReporter.R +++ b/R/FunctionReporter.R @@ -420,10 +420,12 @@ FunctionReporter <- R6::R6Class( if (listable){ - # If do.call and first argument is string (atomic), covert to call + # If do.call and first argument is string (atomic), convert to symbol. + # as.name() is used rather than parse() because the string can name a + # non-syntactic function such as "[<-", which is not parseable as text. if (length(x) >= 2){ if (deparse(x[[1]])[1] == "do.call" & is.character(x[[2]])){ - x[[2]] <- parse(text=x[[2]]) + x[[2]] <- as.name(x[[2]]) } } diff --git a/tests/testthat/test-FunctionReporter-class.R b/tests/testthat/test-FunctionReporter-class.R index d5d40d2..547a0a0 100644 --- a/tests/testthat/test-FunctionReporter-class.R +++ b/tests/testthat/test-FunctionReporter-class.R @@ -268,6 +268,22 @@ test_that(".parse_function correctly handles next control statement", { }) }) +test_that(".parse_function resolves do.call function names given as strings", { + myfunc <- function() { + do.call("innerfunc1", list(innerfunc2())) + } + result <- pkgnet:::.parse_function(body(myfunc)) + expect_true(all(c("innerfunc1", "innerfunc2") %in% result)) +}) + +test_that(".parse_function handles do.call with a non-syntactic function name", { + myfunc <- function() { + do.call("[<-", list(x, 1, value = innerfunc1())) + } + result <- pkgnet:::.parse_function(body(myfunc)) + expect_true("innerfunc1" %in% result) +}) + test_that(".parse_R6_expression correctly parses expressions for symbols", { # Correctly parses body of function and finds all function symbols expect_true({