Skip to content

Commit

Permalink
Refactor dependency scanning files
Browse files Browse the repository at this point in the history
  • Loading branch information
gaborcsardi committed Oct 18, 2024
1 parent a29dd67 commit 0b20a96
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 77 deletions.
36 changes: 36 additions & 0 deletions R/scan-deps-queries.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# match any library() and require calls
# we use these as fallbacks. If a call is not identified some other way
# we parse it with R and match the call.
q_library_0 <- function() {
'((call function: (identifier) @fn-name) @dep-code
(#any-of? @fn-name "library" "require")
)'
}

# library(foo)
# - function call is library or require
# - the only argument (. argument .) is not named (. value:)
# - the only argument is a symbol or a string
# - this should catch most of the usage, the rest we check with
# `match.call()`
q_library_1 <- function() {
'(call function: (identifier) @fn-name
arguments: (arguments . argument: (argument . value: [
(identifier) @pkg-name
(string (string_content) @pkg-name)
]) . )
(#any-of? @fn-name "library" "require")
) @dep-code'
}

q_colon <- function() {
'(namespace_operator lhs: (identifier) @pkg-name) @dep-code'
}

q_deps <- function() {
c(
q_library_0 = q_library_0(),
q_library_1 = q_library_1(),
q_colon = q_colon()
)
}
77 changes: 0 additions & 77 deletions R/scan-dependencies.R → R/scan-deps.R
Original file line number Diff line number Diff line change
@@ -1,80 +1,3 @@
code_query <- function(code = NULL, query, file = NULL) {
qlen <- nchar(query, type = "bytes") + 1L # + \n
qbeg <- c(1L, cumsum(qlen))
qnms <- names(query) %||% rep(NA_character_, length(query))
query1 <- paste0(query, "\n", collapse = "")

if (!is.null(code)) {
if (is.character(code)) code <- charToRaw(paste(code, collapse = "\n"))
res <- call_with_cleanup(c_code_query, code, query1)
} else {
res <- call_with_cleanup(c_code_query_path, file, query1)
}

qorig <- as.integer(cut(res[[1]][[3]], breaks = qbeg, include.lowest = TRUE))

list(
patterns = data_frame(
id = seq_along(res[[1]][[1]]),
name = qnms[qorig],
pattern = res[[1]][[1]],
match_count = res[[1]][[2]]
),
matched_captures = data_frame(
id = viapply(res[[2]], "[[", 3L),
pattern = viapply(res[[2]], "[[", 1L),
match = viapply(res[[2]], "[[", 2L),
start_byte = viapply(res[[2]], "[[", 6L),
start_row = viapply(res[[2]], "[[", 7L),
start_column = viapply(res[[2]], "[[", 8L),
name = vcapply(res[[2]], "[[", 4L),
code = vcapply(res[[2]], "[[", 5L)
)
)
}

s_expr <- function(code) {
if (is.character(code)) code <- charToRaw(paste(code, collapse = "\n"))
call_with_cleanup(c_s_expr, code)
}

# match any library() and require calls
# we use these as fallbacks. If a call is not identified some other way
# we parse it with R and match the call.
q_library_0 <- function() {
'((call function: (identifier) @fn-name) @dep-code
(#any-of? @fn-name "library" "require")
)'
}

# library(foo)
# - function call is library or require
# - the only argument (. argument .) is not named (. value:)
# - the only argument is a symbol or a string
# - this should catch most of the usage, the rest we check with
# `match.call()`
q_library_1 <- function() {
'(call function: (identifier) @fn-name
arguments: (arguments . argument: (argument . value: [
(identifier) @pkg-name
(string (string_content) @pkg-name)
]) . )
(#any-of? @fn-name "library" "require")
) @dep-code'
}

q_colon <- function() {
'(namespace_operator lhs: (identifier) @pkg-name) @dep-code'
}

q_deps <- function() {
c(
q_library_0 = q_library_0(),
q_library_1 = q_library_1(),
q_colon = q_colon()
)
}

scan_path_deps <- function(path) {
code <- readBin(path, "raw", file.size(path))
has_library <- length(grepRaw("library", code, fixed = TRUE)) > 0
Expand Down
39 changes: 39 additions & 0 deletions R/tree-sitter.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
s_expr <- function(code) {
if (is.character(code)) code <- charToRaw(paste(code, collapse = "\n"))
call_with_cleanup(c_s_expr, code)
}

code_query <- function(code = NULL, query, file = NULL) {
qlen <- nchar(query, type = "bytes") + 1L # + \n
qbeg <- c(1L, cumsum(qlen))
qnms <- names(query) %||% rep(NA_character_, length(query))
query1 <- paste0(query, "\n", collapse = "")

if (!is.null(code)) {
if (is.character(code)) code <- charToRaw(paste(code, collapse = "\n"))
res <- call_with_cleanup(c_code_query, code, query1)
} else {
res <- call_with_cleanup(c_code_query_path, file, query1)
}

qorig <- as.integer(cut(res[[1]][[3]], breaks = qbeg, include.lowest = TRUE))

list(
patterns = data_frame(
id = seq_along(res[[1]][[1]]),
name = qnms[qorig],
pattern = res[[1]][[1]],
match_count = res[[1]][[2]]
),
matched_captures = data_frame(
id = viapply(res[[2]], "[[", 3L),
pattern = viapply(res[[2]], "[[", 1L),
match = viapply(res[[2]], "[[", 2L),
start_byte = viapply(res[[2]], "[[", 6L),
start_row = viapply(res[[2]], "[[", 7L),
start_column = viapply(res[[2]], "[[", 8L),
name = vcapply(res[[2]], "[[", 4L),
code = vcapply(res[[2]], "[[", 5L)
)
)
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 0b20a96

Please sign in to comment.