-
Notifications
You must be signed in to change notification settings - Fork 119
/
Copy pathcompiled.R
118 lines (92 loc) · 3.64 KB
/
compiled.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# this does not handle LCOV_EXCL_START ect.
parse_gcov <- function(file, package_path = "") {
if (!file.exists(file)) {
return(NULL)
}
lines <- readLines(file)
source_file <- rex::re_matches(lines[1], rex::rex("Source:", capture(name = "source", anything)))$source
# retrieve full path to the source files
source_file <- normalize_path(source_file)
# If the source file does not start with the package path or does not exist ignore it.
if (!file.exists(source_file) || !grepl(rex::rex(start, rex::regex(paste0(rex::escape(package_path), collapse = "|"))), source_file)) {
return(NULL)
}
re <- rex::rex(any_spaces,
capture(name = "coverage", some_of(digit, "-", "#", "=")),
":", any_spaces,
capture(name = "line", digits),
":"
)
matches <- rex::re_matches(lines, re)
# Exclude lines with no match to the pattern
lines <- lines[!is.na(matches$coverage)]
matches <- na.omit(matches)
# gcov lines which have no coverage
matches$coverage[matches$coverage == "#####"] <- 0 # nolint
# gcov lines which have parse error, so make untracked
matches$coverage[matches$coverage == "====="] <- "-"
coverage_lines <- matches$line != "0" & matches$coverage != "-"
matches <- matches[coverage_lines, ]
values <- as.numeric(matches$coverage)
if (any(is.na(values))) {
stop("values could not be coerced to numeric ", matches$coverage)
}
# There are no functions for gcov, so we set everything to NA
functions <- rep(NA_character_, length(values))
line_coverages(source_file, matches, values, functions)
}
clean_gcov <- function(path) {
src_dir <- file.path(path, "src")
gcov_files <- list.files(src_dir,
pattern = rex::rex(or(".gcda", ".gcno", ".gcov"), end),
full.names = TRUE,
recursive = TRUE)
unlink(gcov_files)
}
run_gcov <- function(path, quiet = TRUE, clean = TRUE,
gcov_path = getOption("covr.gcov", ""),
gcov_args = getOption("covr.gcov_args", NULL)) {
src_path <- normalize_path(file.path(path, "src"))
if (!file.exists(src_path)) {
return()
}
gcov_inputs <- list.files(path, pattern = rex::rex(".gcno", end), recursive = TRUE, full.names = TRUE)
if (!nzchar(gcov_path)) {
if (length(gcov_inputs)) stop('gcov not found')
return()
}
run_gcov_one <- function(src) {
system_check(gcov_path,
args = c(gcov_args, src, "-p", "-o", dirname(src)),
quiet = quiet, echo = !quiet)
gcov_outputs <- list.files(path, pattern = rex::rex(".gcov", end), recursive = TRUE, full.names = TRUE)
if (clean) {
on.exit(unlink(gcov_outputs))
}
unlist(lapply(gcov_outputs, parse_gcov, package_path = c(path, getOption("covr.gcov_additional_paths", NULL))), recursive = FALSE)
}
res <- withr::with_dir(src_path, {
compact(unlist(lapply(gcov_inputs, run_gcov_one), recursive = FALSE))
})
if (!length(res) & length(gcov_inputs))
warning('parsed gcov output was empty')
res
}
line_coverages <- function(source_file, matches, values, functions) {
# create srcfile reference from the source file
src_file <- srcfilecopy(source_file, readLines(source_file))
line_lengths <- vapply(src_file$lines[as.numeric(matches$line)], nchar, numeric(1))
res <- Map(function(line, length, value, func) {
src_ref <- srcref(src_file, c(line, 1, line, length))
res <- list(srcref = src_ref, value = value, functions = func)
class(res) <- "line_coverage"
res
},
matches$line, line_lengths, values, functions)
if (!length(res)) {
return(NULL)
}
names(res) <- lapply(res, function(x) key(x$srcref))
class(res) <- "line_coverages"
res
}