Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- CodeMetrics 1.1
- Written by George Thomas (GeorgeEpicGen)
- Changelog:
- 1.1 Renamed 'script#get_coroutine_count' tok
- 'script#get_subroutine_count' to avoid confusion
- with Lua's 'coroutine' API.
- Look, I know the code is not the neatest you've ever seen,
- but it works, and it works well. If you seriously hate the
- code, feel free to modify and redistribute it as you wish,
- but make sure you give me at least SOME credit for, you know,
- actually writing the damn thing!
- In all seriousness, please, modify and redistribute this
- file as much as you want. I would really appreciate it if
- you be decent enough as to give me a little credit for
- the base code, but make sure you credit yourself, too!
- --]]
- VERSION = 1.1
- local CMD_HELP = "\n [ CodeMetrics "..VERSION.." ]\n\n"
- .. "CodeMetrics is a lightweight API used to calculate\n"
- .. "Lua script properties such as line count and code \n"
- .. "complexity. \n"
- .. " \n"
- .. "To use CodeMetrics from the command line, simply \n"
- .. "execute \n"
- .. " \n"
- .. "\t\tCodeMetrics [\"path_to_script\"] \n"
- .. " \n"
- .. "and the script's properties will be printed to the\n"
- .. "shell. \n"
- .. " \n"
- .. "To use CodeMetrics from another script, write \n"
- .. " \n"
- .. "\t\tos.loadAPI(\"CodeMetrics\") \n"
- .. "\t\tmy_script = CodeMetrics.new(path) \n"
- .. " \n"
- .. "and then invoke the desired functions: \n"
- .. " \n"
- .. "\t\tmy_script:get_character_count() \n"
- .. "\t\tmy_script:get_subroutine_count() \n"
- .. "\t\tmy_script:get_cyclo_complexity() \n"
- .. "\t\tmy_script:get_function_count() \n"
- .. "\t\tmy_script:get_line_count() \n"
- function new(path)
- self = setmetatable({
- get_character_count = function(self)
- return self["chars"]
- end,
- get_subroutine_count = function(self)
- local tokens = self["tokens"]
- local subroutineCount = 0
- for k,v in pairs(tokens) do
- if (v == "do"
- or v == "else"
- or v == "function"
- or v == "repeat"
- or v == "then") then
- subroutineCount = subroutineCount + 1
- end
- end
- return subroutineCount
- end,
- get_count = function(self, token)
- return self["tokens"]:get_occurences(token)
- end,
- get_cyclo_complexity = function(self)
- local tokens = self["tokens"]
- local complexity = 1
- local depth = 0
- for i=1, #tokens do
- local ppv = tokens[i-2]
- local pv = tokens[i-1]
- local v = tokens[i]
- local nv = tokens[i+1]
- if (v == "do"
- or v == "function"
- or v == "repeat"
- or v == "then") then
- depth = depth + 1
- complexity = complexity + (depth*2)
- elseif (v == "}"
- or v == "return"
- or v == "until") then
- depth = depth - 1
- end
- end
- return complexity
- end,
- get_function_count = function(self)
- return self["funcs"]
- end,
- get_line_count = function(self)
- return self["lines"]
- end,
- r = function(self)
- local p = self["path"]
- if ((not fs.exists(p))
- or (fs.isDir(p))) then
- error("File '" .. p .. "' is a "
- .. "directory or does not exist!")
- end
- local f = fs.open(p, "r")
- local cont = f.readAll()
- f.close()
- self["cont"] = cont
- self:parse()
- return cont
- end,
- parse = function(self)
- local parsed = {
- set_tokens = function(self, tokens)
- self["tokens"] = tokens
- end,
- get_tokens = function(self)
- return self["tokens"]
- end,
- }
- local cont = self:get_contents()
- local chars, subts, funcs, lns = 0,0,0,1
- cont = cont:gsub("%-%-.\n", "")
- cont = cont:gsub("--%[%[.--]]", "")
- cont = cont:gsub("\".\"", "")
- chars = #cont
- cont = cont:gsub("elseif", "elif")
- local tokens = {
- add = function(self, tok)
- self[#self + 1] = tok
- end,
- get_occurences = function(self, token)
- local occr = 0
- for i=1,#self do
- if (self[i] == token) then
- occr = occr + 1
- end
- end
- return occr
- end
- }
- local token = ""
- for i=1, #cont do
- local c = cont:sub(i, i)
- if (token == "do"
- or token == "else"
- or token == "repeat"
- or token == "then") then
- subts = subts + 1
- tokens:add(token)
- token = ""
- elseif (token == "function") then
- subts = subts + 1
- funcs = funcs + 1
- tokens:add(token)
- token = ""
- elseif (token == "elif") then
- tokens:add("elseif")
- token = ""
- elseif (token == "and"
- or token == "break"
- or token == "else"
- or token == "end"
- or token == "false"
- or token == "for"
- or token == "if"
- or token == "in"
- or token == "local"
- or token == "nil"
- or token == "not"
- or token == "or"
- or token == "return"
- or token == "true"
- or token == "while") then
- tokens:add(token)
- token = ""
- else
- if (c == "{" or c == "}"
- or c == "(" or c == ")"
- or c == "[" or c == "]") then
- tokens:add(c)
- token = ""
- elseif (c == "\f"
- or c == "\n"
- or c == "\v") then
- lns = lns + 1
- token = ""
- elseif (c == "\f"
- or c == "\t"
- or c == " ") then
- token = ""
- else
- token = token .. c
- end
- end
- end
- cont = cont:gsub("elif", "elseif")
- self["chars"] = chars
- self["subts"] = subts
- self["funcs"] = funcs
- self["lines"] = lns
- self["tokens"] = tokens
- tokens.add = nil
- parsed:set_tokens(tokens)
- return parsed
- end,
- get_contents = function(self)
- return self["cont"]
- end,
- get_path = function(self)
- return self["path"]
- end,
- }, {
- __tostring = function(self)
- local path = self:get_path()
- local chars = self:get_character_count()
- local subts = self:get_subroutine_count()
- local cyclo = self:get_cyclo_complexity()
- local funcs = self:get_function_count()
- local lns = self:get_line_count()
- return "Script '" .. path .. "'\n"
- .. "\tCharacters: " .. chars .. "\n"
- .. "\tSubroutines: " .. subts .. "\n"
- .. "\tFunctions: " .. funcs .. "\n"
- .. "\tLines: " .. lns .. "\n"
- .. "\tComplexity: " .. cyclo .. "\n"
- end
- })
- self["path"] = path
- self:r()
- return self
- end
- function main(args)
- if (args == nil
- or #args == 0) then
- return
- end
- local scr = new(args[1])
- if (#args == 1) then
- if (args[1] == "-help") then
- textutils.pagedPrint(CMD_HELP)
- else
- print(scr)
- end
- end
- end
- main({...})
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement