summaryrefslogtreecommitdiff
path: root/extras/luacov/src/bin/luacov
diff options
context:
space:
mode:
Diffstat (limited to 'extras/luacov/src/bin/luacov')
-rwxr-xr-xextras/luacov/src/bin/luacov142
1 files changed, 142 insertions, 0 deletions
diff --git a/extras/luacov/src/bin/luacov b/extras/luacov/src/bin/luacov
new file mode 100755
index 0000000..6a24bc6
--- /dev/null
+++ b/extras/luacov/src/bin/luacov
@@ -0,0 +1,142 @@
+#!/usr/bin/env lua
+
+local luacov = require("luacov.stats")
+
+local data, most_hits = luacov.load()
+
+if not data then
+ print("Could not load stats file "..luacov.statsfile..".")
+ print("Run your Lua program with -lluacov and then rerun luacov.")
+ os.exit(1)
+end
+
+local report = io.open("luacov.report.out", "w")
+
+-- only report on files specified on the command line
+local patterns = {}
+local exclude_patterns = {}
+local exclude_next = false
+for i = 1, #arg do
+ if arg[i] == "-X" then
+ exclude_next = true
+ else
+ if exclude_next then
+ exclude_patterns[#exclude_patterns+1] = arg[i]
+ exclude_next = false
+ else
+ patterns[#patterns+1] = arg[i]
+ end
+ end
+end
+
+local names = {}
+for filename, _ in pairs(data) do
+ if not patterns[1] then
+ table.insert(names, filename)
+ else
+ local path = filename:gsub("/", "."):gsub("%.lua$", "")
+ local include = false
+ for _, p in ipairs(patterns) do
+ if path:match(p) then
+ include = true
+ break
+ end
+ end
+ if include then
+ for _, p in ipairs(exclude_patterns) do
+ if path:match(p) then
+ include = false
+ break
+ end
+ end
+ end
+ if include then
+ table.insert(names, filename)
+ end
+ end
+end
+
+table.sort(names)
+
+local most_hits_length = ("%d"):format(most_hits):len()
+local empty_format = (" "):rep(most_hits_length+1)
+local false_negative_format = ("!%% %dd"):format(most_hits_length)
+local zero_format = ("*"):rep(most_hits_length).."0"
+local count_format = ("%% %dd"):format(most_hits_length+1)
+
+local exclusions =
+{
+ { false, "^#!" }, -- Unix hash-bang magic line
+ { true, "" }, -- Empty line
+ { true, "}" }, -- Just a close-brace
+ { true, "end,?" }, -- Single "end"
+ { true, "else" }, -- Single "else"
+ { true, "repeat" }, -- Single "repeat"
+ { true, "do" }, -- Single "do"
+ { true, "local%s+[%w_,%s]+" }, -- "local var1, ..., varN"
+ { true, "local%s+[%w_,%s]+%s*=" }, -- "local var1, ..., varN ="
+ { true, "local%s+function%s*%([%w_,%.%s]*%)" }, -- "local function(arg1, ..., argN)"
+ { true, "local%s+function%s+[%w_]*%s*%([%w_,%.%s]*%)" }, -- "local function f (arg1, ..., argN)"
+}
+
+local function excluded(line)
+ for _, e in ipairs(exclusions) do
+ if e[1] then
+ if line:match("^%s*"..e[2].."%s*$") or line:match("^%s*"..e[2].."%s*%-%-") then return true end
+ else
+ if line:match(e[2]) then return true end
+ end
+ end
+ return false
+end
+
+for _, filename in ipairs(names) do
+ local filedata = data[filename]
+ local file = io.open(filename, "r")
+ if file then
+ report:write("\n")
+ report:write("==============================================================================\n")
+ report:write(filename, "\n")
+ report:write("==============================================================================\n")
+ local line_nr = 1
+ block_comment, equals = false, ""
+ while true do
+ local line = file:read("*l")
+ if not line then break end
+ local true_line = line
+
+ local new_block_comment = false
+ if not block_comment then
+ local l, equals = line:match("^(.*)%-%-%[(=*)%[")
+ if l then
+ line = l
+ new_block_comment = true
+ end
+ else
+ local l = line:match("%]"..equals.."%](.*)$")
+ if l then
+ line = l
+ block_comment = false
+ end
+ end
+
+ local hits = filedata[line_nr] or 0
+ if block_comment or excluded(line) then
+ if hits > 0 then
+ report:write(false_negative_format:format(hits))
+ else
+ report:write(empty_format)
+ end
+ else
+ if hits == 0 then
+ report:write(zero_format)
+ else
+ report:write(count_format:format(hits))
+ end
+ end
+ report:write("\t", true_line, "\n")
+ if new_block_comment then block_comment = true end
+ line_nr = line_nr + 1
+ end
+ end
+end