This repository has been archived by the owner on May 10, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
check_namespace.R
95 lines (81 loc) · 2.57 KB
/
check_namespace.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#' Read a package NAMESPACE and check for dangerous imports
#'
#' Given a path to a package source tree, return a data.frame of Imports (both whole
#' packages and fully qualified references).
#'
#' @md
#' @param pkg_path path to package source tree
#' @param imports_to_flag character vector of dangerous items to find
#' @export
#' @examples \dontrun{
#' check_namespace("../testevil")
#' check_namespace(
#' "../testevil",
#' dangerous_imports(additional_dangerous_imports = "sys::exec_background")
#' )
#' }
check_namespace <- function(pkg_path, imports_to_flag = dangerous_imports()) {
assert_path_exists(pkg_path)
assert_is_package(pkg_path)
imports_list <- parse_ns_file(pkg_path)$imports
parsed_imports <- parse_all_imports(imports_list)
all_imports <- summarize_imports(
parsed_imports[["imported_packages"]], parsed_imports[["imported_functions"]]
)
all_imports %>%
subset(.$import %in% imports_to_flag) %>%
`row.names<-`(NULL)
}
parse_all_imports <- function(imports_list) {
whole_pkg_imports <- extract_whole_pkg_imports(imports_list)
fqrs <- extract_fully_qualified_references(imports_list)
imported_packages <- c(
whole_pkg_imports,
extract_pkgs_from_fully_qualified_references(fqrs)
) %>%
unique()
imported_functions <- transform_fully_qualified_refereces(fqrs)
list(
"imported_packages" = imported_packages,
"imported_functions" = imported_functions
)
}
summarize_imports <- function(imported_packages, imported_functions) {
if (length(imported_packages) > 0) {
pkgs <- data.frame(type = "package", import = as.character(imported_packages), stringsAsFactors = FALSE)
} else {
pkgs <- data.frame()
}
if (length(imported_functions) > 0) {
funs <- data.frame(type = "function", import = as.character(imported_functions), stringsAsFactors = FALSE)
} else {
funs <- data.frame()
}
all_imports <- rbind(pkgs, funs)
all_imports$package <- vapply(
strsplit(all_imports$import, "::"),
function(x) x[[1]],
"character"
)
all_imports
}
parse_ns_file <- function(pkg_path) {
parseNamespaceFile(
basename(pkg_path), dirname(pkg_path),
mustExist = FALSE
)
}
extract_whole_pkg_imports <- function(imports) {
unlist(imports[lengths(imports) == 1], use.names = FALSE)
}
extract_fully_qualified_references <- function(imports) {
imports[(lengths(imports) == 2)]
}
extract_pkgs_from_fully_qualified_references <- function(fqrs) {
sapply(fqrs, function(x) x[[1]])
}
transform_fully_qualified_refereces <- function(fqrs) {
sapply(fqrs, function(x) {
sprintf("%s::%s", x[[1]], x[[2]])
})
}