Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function summary table generator #5

Merged
merged 23 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c516e1d
adding a function summary tabulater so users can see all functions us…
RobertASmith Jan 16, 2024
b216e42
adding new functionality - but tests not working
RobertASmith Jan 21, 2024
b518533
removing comments from tests
RobertASmith Jan 23, 2024
55114e6
overwriting testthat path with two levels up?
RobertASmith Jan 23, 2024
703ce97
if in package testing mode then go two levels up from testing folder,…
RobertASmith Jan 23, 2024
3b1f9a9
summary table first version
RobertASmith Jan 25, 2024
0ca5c72
Merge pull request #10 from dark-peak-analytics/RS_cheers
RobertASmith Jan 25, 2024
0594f00
Merge pull request #8 from dark-peak-analytics/RS_bugfix
RobertASmith Jan 25, 2024
5a6c4b3
refined regex for finding functions
Smit-tay Jan 26, 2024
bb11003
Merge pull request #12 from Smit-tay/RS_foo_finder
RobertASmith Jan 26, 2024
9e015aa
this will still break if there is a comment between function and defi…
RobertASmith Jan 26, 2024
5963845
minor edits
RobertASmith Jan 26, 2024
1d421fe
Fix find_previous_vector_element
Smit-tay Jan 29, 2024
5e11e4c
Fix find_next_vector_element
Smit-tay Jan 29, 2024
628e783
Merge branch 'RS_foo_finder' into RS_foo_finder
RobertASmith Jan 30, 2024
d31204d
Merge pull request #13 from Smit-tay/RS_foo_finder
RobertASmith Jan 30, 2024
fb3e855
order of lines change, foo_name rather than v_chars
RobertASmith Jan 30, 2024
501c1fb
All extract_function_name2 to handle extreme abuse
Smit-tay Jan 30, 2024
1db31c4
Merge branch 'RS_foo_finder' into RS_foo_finder
Smit-tay Jan 30, 2024
6e7377c
extract_function_name2 refined even more
Smit-tay Jan 30, 2024
6091f92
Merge pull request #15 from Smit-tay/RS_foo_finder
RobertASmith Jan 30, 2024
fe8fdb2
adaptation to function name 2 and improved tests
RobertASmith Jan 30, 2024
fc72cd0
first pass, identifies functions from scripts
RobertASmith Jan 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ export(check_markov_trace)
export(check_trans_prob_array)
export(check_trans_prob_mat)
export(plot_PSA_stability)
export(tabulate_functions_in_folder)
import(assertthat)
importFrom(tidyr,pivot_longer)
importFrom(utils,capture.output)
importFrom(utils,find)
importFrom(utils,getParseData)
importFrom(utils,stack)
112 changes: 112 additions & 0 deletions R/check_functions.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#' List all of the functions in a script
#'
#' This function lists all of the functions in a script. It expects the script to be
#' an R file, and requires that package libraries are loaded when identifying packages.
#'
#' @param filename The name of the file to be checked.
#' @param alphabetic If TRUE, return the functions in alphabetic order.
#'
#' @return A named list of functions in the script, by package.
#' @importFrom utils find getParseData stack
list_functions_in_script <- function(filename,
alphabetic=TRUE) {

# from hrbrmstr, StackExchange 3/1/2015
if(!file.exists(filename)) { stop("couldn't find file ",filename) }
if(!tools::file_ext(filename) == "R") { warning("expecting *.R file, will try to proceed") }
# read in parsed data from script
tmp <- utils::getParseData(parse(filename, keep.source=TRUE))
# only keep those lines that are identified as function calls
nms <- tmp$text[which(tmp$token=="SYMBOL_FUNCTION_CALL")]
# only keep unique functions for script
funs <- unique(if(alphabetic) { sort(nms) } else { nms })
# return a list of functions and the file they were found in
src <- paste(as.vector(sapply(funs, utils::find)))
outlist <- tapply(funs, factor(src), c)

return(outlist)

}


#' Create table of all of the functions in a script
#'
#' This function tabulates all of the functions in a script. It expects the script to be
#' an R file, and requires that package libraries are loaded when identifying packages.
#'
#' @param filename The name of the file to be checked.
#' @param packages_to_exclude A vector of packages to exclude from the output (e.g. "base")
#'
#' @return A data-frame of functions and the package the function is from.
tabulate_functions_in_script <- function(filename,
packages_to_exclude = c("base", "stats", "utils")) {
# list the functions in the file.
my_packages <- list_functions_in_script(filename)

# convert nested list to a dataframe where each row gives the function name
# and the package it belongs to:
df <- stack(my_packages)
colnames(df) <- c("function", "package")

# remove 'package:' from the strings
df$package <- gsub("package:", "", df$package)

# remove 'character(0)' and replace with 'local'
df$package[df$package == "character(0)"] <- "unknown"

# exclude unwanted packages (to reduce size)
exclude_index <- df$package %in% packages_to_exclude
df <- df[!exclude_index, ]

return(df)
}


#' Create table of all of the functions identified in a project folder
#'
#' This function tabulates all of the functions identified in R scripts within a
#' project folder. It requires that package libraries are loaded when identifying
#' a function's package.
#'
#' @param path The path to the folder to be checked.
#' @param collapse If TRUE, return a single data-frame of all functions. Else return a list by file.
#' @param packages_to_exclude A vector of packages to exclude from the output (e.g. "base")
#'
#' @return Either a data-frame of functions and the package the function is from, or a list of functions by file.
#' @export
#' @examples
#'
#' \dontrun{
#' tabulate_functions_in_folder(
#' path = ".",
#' collapse = T,
#' packages_to_exclude = c("base", "stats", "utils")
#' )
#' }
tabulate_functions_in_folder <- function(path = ".",
collapse = T,
packages_to_exclude = c("base", "stats", "utils")) {
# get all files from the path folder, i.e. everything in repo.
my_R_scripts <- list.files(
path = path,
pattern = "\\.R$",
recursive = TRUE,
full.names = TRUE
)

l_foo <- lapply(X = my_R_scripts,
FUN = tabulate_functions_in_script,
packages_to_exclude = packages_to_exclude)

# collapse the list into a single dataframe
if (collapse) {
df_foo <- do.call(rbind, l_foo)
# remove duplicates
df_foo <- unique(df_foo)
return(df_foo)
} else{
names(l_foo) <- my_R_scripts
return(l_foo)
}

}
30 changes: 30 additions & 0 deletions inst/example_script/example_script.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Example R script which calls the foo.
v_hs_names <- c("H", "S", "D")
n_hs <- length(v_hs_names)
n_t <- 10
m_TR <- matrix(data = NA,
nrow = n_t,
ncol = n_hs,
dimnames = list(NULL, v_hs_names))

m_TR[, "H"] <- seq(1, 0, length.out = n_t)
m_TR[, "S"] <- seq(0, 0.5, length.out = n_t)
m_TR[, "D"] <- 1 - m_TR[, "H"] - m_TR[, "S"]

check_markov_trace(m_TR = m_TR, dead_state = "D", confirm_ok = T)

m_TR[10, "D"] <- 0
m_TR[9, "S"] <- 1

check_markov_trace(m_TR = m_TR, stop_if_not = T, dead_state = "D", confirm_ok = T)


# test function 1
foo1 <- function(x){
x
}

foo1 (10)

#
any_of(c("H", "S", "D"))
20 changes: 20 additions & 0 deletions man/list_functions_in_script.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions man/tabulate_functions_in_folder.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions man/tabulate_functions_in_script.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions tests/testthat/test-check_functions.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
test_that("test no error when running folder function", {
testthat::expect_silent(
tmp <<- tabulate_functions_in_folder(
path = ".",
collapse = T,
packages_to_exclude = c("base", "stats", "utils")
)
)

testthat::expect_s3_class(
tmp,
"data.frame"
)

testthat::expect_type(
tabulate_functions_in_folder(
path = ".",
collapse = F,
packages_to_exclude = c("base", "stats", "utils")
),
"list"
)


testthat::expect_type(
tabulate_functions_in_folder(
path = ".",
collapse = F,
packages_to_exclude = NULL
),
"list"
)

})