Module:log globals

From Wiktionary, the free dictionary
Jump to navigation Jump to search

Sends a log message if any nil global variables are set or read by any module involved in the current module invocation. A less drastic version of the strict library, which triggers an error in the same situation.

This module logs uses of nil global variables in code that is executed after the module is loaded. There is no deduplication so the same message can appear many times if it is triggered by more than one template.

After the name of the variable and whether it was set or accessed, a backtrace is shown. The first line of the backtrace gives the line of the module where a global variable was used, which is often the line that needs to be changed. Sometimes a global variable is used because of a misspelling; sometimes a variable is defined and local needs to be added to its definition (which requires refactoring or forward declaration if the variable is used before it is defined).

To use it, add require("Module:log globals") temporarily at the top of the module. Preview a page by entering a page in the "Preview page with this template" box and pressing the "Show preview" button. Click to open the "Parser profiling data:" box at the bottom of the page, if it is not open already, and click the "Expand" button next to the "Lua logs" label. Inside is a log of global variables that were accessed or set in any code that was executed after this module was loaded. This includes global variables in code in other modules. After changing the global variables to local, and before saving the module, remove require("Module:log globals").


local mt = getmetatable(_G) or {}

local function print(val)
	if type(val) == "table" then
		local printout = {}
		local i = 1
		for k, v in pairs(val) do
			table.insert(printout, ("[%s] = %s"):format(tostring(k), tostring(v)) )
			i = i + 1
			if i > 5 then
				table.insert(printout, "...")
				break
			end
		end
		printout = { table.concat(printout, ", ") }
		table.insert(printout, 1, "{")
		table.insert(printout, "}")
		return table.concat(printout)
	elseif type(val) == "string" then
		return '"' .. val .. '"'
	else
		return tostring(val)
	end
end
		

mt.__newindex = function (self, key, value)
	if key ~= "arg" then
		mw.log("Global variable " .. print(key) .. " was set to "
			.. print(value) .. " somewhere:",
			debug.traceback("", 2))
	end
	return rawset(self, key, value)
end

mt.__index = function (self, key)
	if key ~= "arg" then
		mw.log("Nil global variable " .. print(key) .. " was read somewhere:",
			debug.traceback("", 2))
	end
	return rawget(self, key)
end

setmetatable(_G, mt)