@@ -34,18 +34,17 @@ get_code_dependency <- function(code, names, check_names = TRUE) {
3434 }
3535
3636 # If code is bound in curly brackets, remove them.
37+ # TODO: rethink if this is still needed when code is divided by calls?
3738 tcode <- trimws(code )
3839 if (any(grepl(" ^\\ {.*\\ }$" , tcode ))) {
3940 code <- sub(" ^\\ {(.*)\\ }$" , " \\ 1" , tcode )
4041 }
4142
4243 parsed_code <- parse(text = code , keep.source = TRUE )
43- code_split <- split_code(code , parsed_code )
4444
4545 pd <- utils :: getParseData(parsed_code )
4646 pd <- normalize_pd(pd )
4747 calls_pd <- extract_calls(pd )
48- # comments <- extract_comments(parsed_code)
4948
5049 if (check_names ) {
5150 # Detect if names are actually in code.
@@ -67,8 +66,7 @@ get_code_dependency <- function(code, names, check_names = TRUE) {
6766 lib_ind <- detect_libraries(calls_pd )
6867
6968 code_ids <- sort(unique(c(lib_ind , ind )))
70- code_split [code_ids ]
71- # trimws(paste(as.character(code[code_ids]), comments[code_ids]))
69+ code [code_ids ]
7270
7371}
7472
@@ -457,20 +455,105 @@ normalize_pd <- function(pd) {
457455 pd
458456}
459457
460- # ' #' Extract comments from parsed code
461- # ' #'
462- # ' #' @param parsed_code `expression`, result of `parse()` function
463- # ' #'
464- # ' #' @return `character` vector of length of `parsed_code` with comments included in `parsed_code`
465- # ' #' @keywords internal
466- # ' #' @noRd
467- # ' extract_comments <- function(parsed_code) {
468- # ' get_comments <- function(call) {
469- # ' comment <- call[call$token == "COMMENT", "text"]
470- # ' if (length(comment) == 0) "" else comment
471- # ' }
472- # ' calls <- extract_calls(utils::getParseData(parsed_code))
473- # ' fixed_calls <- fix_shifted_comments(calls, pattern = "#")
474- # '
475- # ' unlist(lapply(fixed_calls, get_comments))
476- # ' }
458+ # ' Get line and cols ids of starts and ends of calls
459+ # '
460+ # ' @param pd `data.frame` resulting from `utils::getParseData()` call.
461+ # '
462+ # ' @return list of `data.frames` containing number of lines and columns of starts and ends of calls included in `pd`.
463+ # '
464+ # ' @keywords internal
465+ # ' @noRd
466+ get_line_ids <- function (pd ) {
467+ if (pd $ token [1 ] == " COMMENT" ) {
468+ first_comment <- 1 : (which(pd $ parent == 0 )[1 ] - 1 )
469+ pd_first_comment <- pd [first_comment , ]
470+ pd <- pd [- first_comment , ]
471+
472+ n <- nrow(pd_first_comment )
473+ first_comment_ids <- data.frame (
474+ lines = c(pd_first_comment [1 , " line1" ], pd_first_comment [n , " line2" ]),
475+ cols = c(pd_first_comment [1 , " col1" ], pd_first_comment [n , " col2" ])
476+ )
477+ } else {
478+ first_comment_ids <- NULL
479+ }
480+
481+ if (pd $ token [nrow(pd )] == " COMMENT" ) {
482+ last_comment <- which(pd $ parent == 0 & pd $ token == " COMMENT" )
483+ pd_last_comment <- pd [last_comment , ]
484+ pd <- pd [- last_comment , ]
485+
486+ n <- nrow(pd_last_comment )
487+ last_comment_ids <- data.frame (
488+ lines = c(pd_last_comment [1 , " line1" ], pd_last_comment [n , " line2" ]),
489+ cols = c(pd_last_comment [1 , " col1" ], pd_last_comment [n , " col2" ])
490+ )
491+ } else {
492+ last_comment_ids <- NULL
493+ }
494+
495+
496+ calls_start <- which(pd $ parent == 0 )
497+ calls_end <- c(which(pd $ parent == 0 )[- 1 ] - 1 , nrow(pd ))
498+
499+ call_ids <- list ()
500+ for (i in seq_along(calls_start )) {
501+ call <- pd [c(calls_start [i ], calls_end [i ]), ]
502+ call_ids [[i ]] <-
503+ data.frame (
504+ lines = c(call [1 , " line1" ], call [2 , " line2" ]),
505+ cols = c(call [1 , " col1" ], call [2 , " col2" ])
506+ )
507+ }
508+
509+ if (! is.null(first_comment_ids )) {
510+ call_ids [[1 ]] <- rbind(first_comment_ids [1 , ], call_ids [[1 ]][2 , ])
511+ }
512+ if (! is.null(last_comment_ids )) {
513+ n <- length(call_ids )
514+ call_ids [[n ]] <- rbind(call_ids [[n ]][1 , ], last_comment_ids [2 , ])
515+ }
516+ call_ids
517+ }
518+
519+ # ' Split code by calls
520+ # '
521+ # ' @param code `character` with the code.
522+ # '
523+ # ' @return list of `character`s of the length equal to the number of calls in `code`.
524+ # '
525+ # ' @keywords internal
526+ # ' @noRd
527+ split_code <- function (code ) {
528+ parsed_code <- parse(text = code , keep.source = TRUE )
529+ pd <- utils :: getParseData(parsed_code )
530+ pd <- pd [pd $ token != " ';'" , ]
531+ lines_ids <- get_line_ids(pd )
532+
533+ code_split <- strsplit(code , split = " \n " , fixed = TRUE )[[1 ]]
534+ code_split_calls <- list ()
535+
536+ for (i in seq_along(lines_ids )) {
537+ code_lines <- code_split [lines_ids [[i ]]$ lines [1 ]: lines_ids [[i ]]$ lines [2 ]]
538+
539+ if (length(code_lines ) == 1 ) {
540+ code_lines_candidate <- substr(code_lines , lines_ids [[i ]]$ cols [1 ], lines_ids [[i ]]$ cols [2 ])
541+ # in case only indentantion is changed, do not trim the indentation
542+ if (! identical(code_lines_candidate , trimws(code_lines ))) {
543+ # case of multiple calls in one line, keep the original indentation
544+ indentation <- gsub(" ^(\\ s+).*" , " \\ 1" , code_lines )
545+ code_lines <- paste0(indentation , code_lines_candidate )
546+ }
547+ } else {
548+ code_lines_candidate <- substr(code_lines [1 ], lines_ids [[i ]]$ cols [1 ], nchar(code_lines [1 ]))
549+ # in case only indentantion is changed, do not trim the indentation
550+ if (! identical(code_lines_candidate , trimws(code_lines [1 ]))) {
551+ code_lines [1 ] <- code_lines_candidate
552+ }
553+ code_lines [length(code_lines )] <- substr(code_lines [length(code_lines )], 1 , lines_ids [[i ]]$ cols [2 ])
554+ }
555+
556+ code_split_calls [[i ]] <- paste(code_lines , collapse = " \n " )
557+ }
558+ code_split_calls
559+ }
0 commit comments