Module:LibraryUtil

-- From MediaWiki source file

-- Set 'type' function to custom one to force use in other modules local _type = type type = nil local function __type(v) local tp = _type(v) local __t = (getmetatable(v) or {}).__type if __t ~= nil then if _type(__t) == "function" then return __t(v, tp) else return __t end else return tp	end end _G.type = __type

local function makeArgNumber(val) return table.concat{ type(val) == 'number' and '#' or '\, val, type(val) ~= "number" and '\ or '' } end

local function getParentName(level) local stack = debug.traceback(, (level or 0) + 3):gsub('\nstack traceback:\n', ):match('in function ([^\n]+)'):gsub('^\'(.-)\'$', '%1') stack = stack:match('[<>:]') and '?' or stack return stack end

local function typeMatches(val, types, nilOk) local valType = type(val) if type(types) == "string" then types = { types } end if nilOk and val == nil then return true end for _, v in ipairs(types) do		if valType == v:lower then return true end end return false end

local function generateTypes(types) if type(types) == "string" then types = { types } end local n = #types local typeList if n > 1 then typeList = table.concat(types, '/') else typeList = types[1] end return typeList end

local function generateMsg(name, index, val, types) types = generateTypes(types) local msg = string.format("bad argument %s to '%s' (%s expected, got %s)",		makeArgNumber(index),		name,		typeList or types,		type(val)  ); return msg end

_G.typeMatches = typeMatches _G.getParentName = getParentName _G.makeArgNumber = makeArgNumber _G.generateMsg = generateMsg

function _G.setRequiredArgs(name, amount, checkTable) for i = 1, amount, 1 do		local v = checkTable[i]

if v == nil then local msg = string.format('failed to execute %q (%d arguments required, but only %d present)',				name,				amount,				i-1			) error(msg, 3) end end end

function _G.checkTypeField(formats, value, types) local valType = type(value) local index, parent, name = unpack{ formats[1] or formats.index or formats.i,		formats[2] or formats.parent or formats.p,		formats[3] or formats.name or formats.n,	} if type(types) == "table" then for _, i in ipairs(types) do			if i:lower == valType then return; end end elseif types:lower == valType then return; end local types = (#types > 1 and type(types) == "table") and table.concat(types, '/') or #types == 1 and types[1] or types

local msg = string.format("bad table index to %s to argument %s in function '%s' (%s expected, got %s)",		makeArgNumber(index),		makeArgNumber(parent),		name,		types,		valType	) error(msg, 3) end

function _G.checkType(name, argIdx, arg, expectTypes, nilOk) local isConstructor if name == true then name = nil isConstructor = true end if type(name) == "number" or name == nil and argIdx == nil then nilOk = expectTypes expectTypes = arg or 'string' arg = argIdx or nil argIdx = name or 1 name = nil name = getParentName(isConstructor and 1 or 0) end local t = {} t.checkType = error if not typeMatches(arg, expectTypes, nilOk) then local msg = generateMsg(name or getParentName(isConstructor and 1 or 0), argIdx, arg, expectTypes) t.checkType(msg, isConstructor and 4 or 3) end end

function _G.checkTypeMulti(t, types) checkType(1, t, 'table') checkType(2, types, 'table') for i = 1, #types do		if select('#', unpack(t)) < #types then assertTrue(true, getParentName, i, '%s expected, got no value', generateTypes(types[i])) else checkType(true, i, t[i], types[i]) end end end

function _G.alertDeprecation(name, useInstead) local t = {} t.alertDeprecation = error if type(name) == "table" then name, useInstead = unpack{ name.name or name[1], name.useInstead or name.use or name[2], }	end t.alertDeprecation(string.format( 'function %q is deprecated%s', name or getParentName, useInstead and string.format(', use the function %q instead', useInstead) or '' ), 3) end

function _G.makeCheckFunction(name, isConstructor) return function(index, val, expectTypes, nilOk) if not typeMatches(val, expectTypes, nilOk) then local t = {} t.checkType = error msg = generateMsg(name, index, val, expectTypes) t.checkType(msg, isConstructor and 6 or 3) end end end

function _G.assertTrue(cond, name, index, msg, ...) local tmp = { ... }	local t = {} t.assertTrue = error if #tmp == 1 and type(tmp[1]) == "table" then params = tmp[1] else params = tmp end if cond then t.assertTrue(string.format('bad argument to %s to \'%s\' (%s)', makeArgNumber(index), name, params and string.format(msg, unpack(params)) or msg ), 3) end end

_G.customArgError = assertTrue

function _G.forEachArgs(args, types, cb) checkType(1, args, 'table') for i, arg in ipairs(args or {}) do		checkType(i, arg, types) cb(i, arg, args) end return args end

function _G.makeCheckSelfFunction(libraryName, varName, selfObj, selfObjDesc) return function (self, method) if self ~= selfObj then error(string.format( "%s: invalid %s. Did you call %s with a dot instead of a colon, i.e. " .. "%s.%s instead of %s:%s?", libraryName, selfObjDesc, method, varName, method, varName, method ), 3)		end end end

-- Deprecated functions function _G.customListError alertDeprecation end

function _G.customFieldError alertDeprecation end

return _G