Module:Module introspection: Difference between revisions
introspection should now ignore strings, on the offchance that strings contain code |
ArrowHead294 (talk | contribs) mNo edit summary |
||
| (89 intermediate revisions by 2 users not shown) | |||
| Line 1: | Line 1: | ||
-- This module follows [[User:Ganaram inukshuk/Provisional style guide for Lua]] | -- This module follows [[User:Ganaram inukshuk/Provisional style guide for Lua]] | ||
local getArgs = require("Module:Arguments").getArgs | local getArgs = require("Module:Arguments").getArgs | ||
local iutils = require("Module:Introspection utils") | |||
local yesno = require("Module:Yesno") | |||
local | |||
local p = {} | local p = {} | ||
-- Helper function | -- Helper function | ||
-- | -- Given the output of the above function, create a mediawiki table | ||
function p.make_dependency_table(module_deps) | |||
function p. | |||
-- | -- Table headers | ||
local lines = {} | local lines = {} | ||
table.insert(lines, '{| class="wikitable sortable"') | |||
table.insert(lines, "|+ style=\"font-size: 105%;\" | " .. string.format("Lua modules required (%d)", #module_deps)) | |||
table.insert(lines, "|-") | |||
table.insert(lines, "! Variable") | |||
table.insert(lines, "! Module") | |||
table.insert(lines, "! Functions used") | |||
-- Table | -- Table rows (assuming they're all alphabetized) | ||
for _, info in ipairs(module_deps) do | |||
for | |||
local funcs_text | local funcs_text | ||
if #info.funcs == 0 then | if #info.funcs == 0 then | ||
funcs_text = "''dependency not used''" | funcs_text = "''dependency not used''" | ||
else | else | ||
funcs_text = table.concat( | local func_lines = {} | ||
for _, func in ipairs(info.funcs) do | |||
table.insert(func_lines, string.format("<code>%s</code>", func)) | |||
end | |||
funcs_text = table.concat(func_lines, "<br />") | |||
end | end | ||
table.insert(lines, | table.insert(lines, "|-") | ||
table.insert(lines, | table.insert(lines, "| " .. info.var) | ||
table.insert(lines, | table.insert(lines, "| [[" .. info.dep .. "]]") | ||
table.insert(lines, | table.insert(lines, "| " .. funcs_text) | ||
end | end | ||
-- Table footer | -- Table footer | ||
table.insert(lines, | table.insert(lines, "|}") | ||
-- Join all lines into a single string | -- Join all lines into a single string | ||
return table.concat(lines, | return table.concat(lines, "\n") | ||
end | end | ||
| Line 212: | Line 48: | ||
-- Lists module's own functions; requires module name to produce links to each | -- Lists module's own functions; requires module name to produce links to each | ||
-- function. | -- function. | ||
function p.make_function_table(module_name, | function p.make_function_table(module_name, module_funcs, descriptions, main_function) | ||
-- | -- Check whether descriptions was passed in | ||
local | local has_descriptions = false | ||
if | if type(descriptions) == "table" then | ||
for _, _ in pairs(descriptions) do | |||
has_descriptions = true | |||
break | |||
end | |||
end | end | ||
local | -- Table headers | ||
--table.insert( | local lines = {} | ||
table.insert( | --table.insert(lines, string.format("'''Module:%s''' provides %d function(s):", module_name, #module_funcs)) | ||
table.insert( | table.insert(lines, '{| class="wikitable sortable"') | ||
table.insert( | table.insert(lines, "|+ style=\"font-size: 105%;\" | " .. string.format("Functions provided (%d)", #module_funcs)) | ||
table.insert( | table.insert(lines, "|-") | ||
table.insert(lines, "! Line") | |||
table.insert(lines, "! Function") | |||
table.insert(lines, "! Params") | |||
-- If there are descriptions, add a column for that | |||
if has_descriptions then | |||
table.insert(lines, "! Description") | |||
end | |||
for _, | -- Table rows | ||
local link = string.format("[[Module:%s#L-%d|% | for _, info in ipairs(module_funcs) do | ||
-- Find params for that function, or say "none" if none | |||
local params = {} | |||
for _, param in ipairs(info.params) do | |||
table.insert(params, param) | |||
end | |||
local params_string = "" | |||
if #params == 0 then | |||
params_string = "''none''" | |||
else | |||
params_string = string.format("<code>(%s)</code>", table.concat(params, ", ")) | |||
end | |||
-- Create link to line for that function | |||
local line_num = string.format("[[Module:%s#L-%d|%d]]", module_name, info.line, info.line) | |||
-- Create text for function | |||
local func = "" | |||
if info.name then | |||
func = string.format("<code>%s</code>", info.name) | |||
else | |||
func = "''none''" | |||
end | |||
-- If the function is the main function, add "main" to that cell | -- If the function is the main function, add "main" to that cell | ||
if | if info.name == main_function then | ||
func = func .. " '''(main)'''" | |||
end | end | ||
table.insert( | -- If the function is invokable (it has one param called "frame"), add | ||
table.insert( | -- "invokable" to that cell | ||
table.insert( | if #params == 1 and params[1] == "frame" then | ||
func = func .. " '''(invokable)'''" | |||
end | |||
table.insert(lines, "|-") | |||
table.insert(lines, "| " .. line_num) | |||
table.insert(lines, "| " .. func) | |||
table.insert(lines, "| " .. params_string) | |||
if has_descriptions then | |||
table.insert(lines, "| " .. (descriptions[info.name] or "")) | |||
end | |||
end | end | ||
table.insert( | table.insert(lines, "|}") | ||
return | return table.concat(lines, "\n") | ||
end | end | ||
-- Main function; to be called by wrapper | -- Main function; to be called by wrapper | ||
| Line 253: | Line 130: | ||
local module_name = args["module_name" ] | local module_name = args["module_name" ] | ||
local main_function = args["main_function"] | local main_function = args["main_function"] | ||
local descriptions = args["descriptions" ] | |||
local is_doc = args["is_doc"] | |||
-- Check whether this page is a docpage | |||
-- If so, don't bother | |||
if is_doc then | |||
return "''To see introspection summary, see this module's main page.''" | |||
end | |||
-- Preprocess module and blank-out comments | -- Preprocess module and blank-out comments | ||
local title = mw.title.new('Module:' .. module_name) | --local title = mw.title.new('Module:' .. module_name) | ||
local code = title:getContent() | --local code = title:getContent() | ||
code = | --code = iutils.preprocess_code(code) -- Blank-out comments | ||
code = | local code = iutils.get_and_preprocess_content("Module", module_name) | ||
-- Get dependencies and their functions used, then build a table | -- Get dependencies and their functions used, then build a table | ||
local module_deps = | local module_deps = iutils.find_dependencies(code) | ||
local dep_table = p.make_dependency_table(module_deps) | local dep_table = p.make_dependency_table(module_deps) | ||
-- Get module's functions, then build a table using that information | -- Get module's functions, then build a table using that information | ||
local | local module_funcs = iutils.find_functions(code) | ||
local | local func_table = p.make_function_table(module_name, module_funcs, descriptions, main_function) | ||
-- Return the tables | -- Return the tables | ||
local | -- Styling may be improved at a later time | ||
local lines = { | |||
'{| class="wikitable mw-collapsible"', | |||
'|-', | |||
'! colspan="2" style="font-size: 105%;" | ' .. string.format("Introspection summary for Module:%s ", module_name), | |||
"|-", | |||
'| style="vertical-align: top; border-right: none;" | ', | |||
func_table, | |||
'| style="vertical-align: top; border-left: none;" | ', | |||
dep_table, | |||
"|}" | |||
} | |||
-- Check whether descriptions was passed in | |||
local has_descriptions = false | |||
if type(descriptions) == "table" then | |||
for _, _ in pairs(descriptions) do | |||
has_descriptions = true | |||
break | |||
end | |||
end | |||
-- If no descriptions were provided, add text below that points to the code. | |||
if not has_descriptions then | |||
table.insert(lines, "''No function descriptions were provided. The Lua code may have further information.''") | |||
end | |||
return table.concat(lines, "\n") | |||
end | end | ||
-- Wrapper function for modules | -- Wrapper function for modules | ||
| Line 283: | Line 193: | ||
-- Strip trailing "/doc" if the template is used on a documentation subpage | -- Strip trailing "/doc" if the template is used on a documentation subpage | ||
module_name = module_name:gsub("/doc$", "") | --module_name = module_name:gsub("/doc$", "") | ||
-- Check whether page is the doc page | |||
-- To ensure proper referencing, do not display introspection on a docpage. | |||
local is_doc = string.find(module_name, "/doc$") | |||
-- Normalize module name so it can be used to find the main function, which | -- Normalize module name so it can be used to find the main function, which | ||
| Line 290: | Line 204: | ||
local normalized_name = module_name:gsub("[^%w]", "_"):lower() | local normalized_name = module_name:gsub("[^%w]", "_"):lower() | ||
local main_function = args["main_function"] or "_" .. normalized_name | local main_function = args["main_function"] or "_" .. normalized_name | ||
-- Process all function descriptions, if provided as desc_function_name | |||
local func_descriptions = {} | |||
for key, val in pairs(args) do | |||
local func_name = key:match("^desc_([%w_]+)$") | |||
if func_name and val and val ~= "" then | |||
func_descriptions[func_name] = val | |||
end | |||
end | |||
-- Return | -- Return | ||
local result = p._module_introspection({ | |||
["module_name"] | ["module_name" ] = module_name, | ||
["main_function"] = main_function, | ["main_function"] = main_function, | ||
["descriptions" ] = func_descriptions, | |||
["is_doc"] = is_doc | |||
}) | }) | ||
-- Debugger option to show generated WikiText | |||
local wtext = yesno(frame.args["wtext"] or args["wtext"]) | |||
if wtext == true then | |||
result = "<syntaxhighlight lang=\"wikitext\">" .. result .. "</syntaxhighlight>" | |||
end | |||
return | return frame:preprocess(result) | ||
end | end | ||
return p | return p | ||