Module:UtilsValidate: Difference between revisions
Jump to navigation
Jump to search
PhantomCaleb (talk | contribs) mNo edit summary |
PhantomCaleb (talk | contribs) No edit summary |
||
(9 intermediate revisions by the same user not shown) | |||
Line 15: | Line 15: | ||
}) | }) | ||
local msg = i18n.getString(str, vars) | local msg = i18n.getString(str, vars) | ||
local quiet = | |||
local stackTrace = options | local options = options or {} | ||
local quiet = options.quiet | |||
local stackTrace = options.stackTrace | |||
local isUsageError = options.isUsageError | |||
if isUsageError then | |||
local invokeFrameTitle = mw.getCurrentFrame():getParent():getTitle() | |||
if mw.title.new(invokeFrameTitle).nsText == "Template" then | |||
msg = string.format("Misuse of [[%s]]: %s", invokeFrameTitle, msg) | |||
end | |||
end | |||
if not quiet then | if not quiet then | ||
utilsError.warn(msg, stackTrace, 2) | utilsError.warn(msg, { | ||
traceBack = stackTrace, | |||
omitFrames = 2 | |||
}) | |||
end | end | ||
return msg | return msg | ||
Line 70: | Line 84: | ||
else | else | ||
return s("msg.enumAccepted", { | return s("msg.enumAccepted", { | ||
values = code(utilsTable.print(enum)) | values = code(utilsTable.print(enum, true)) | ||
}) | }) | ||
end | end | ||
Line 87: | Line 101: | ||
end | end | ||
for k, value in ipairs(values) do | for k, value in ipairs(values) do | ||
if not utilsTable.keyOf(acceptedValues, value) then | if not utilsTable.keyOf(acceptedValues, value) then | ||
local path = utilsTable.concat(path or {}, multivalue and k or nil) | local path = utilsTable.concat(path or {}, multivalue and k or nil) | ||
Line 98: | Line 111: | ||
end | end | ||
end | end | ||
end | |||
end | |||
function p._enum(acceptedValues) | |||
return function (value, name, path, isKey, options) | |||
if type(acceptedValues) == "function" then | |||
acceptedValues = acceptedValues() | |||
end | |||
-- Sometimes the argument is a list of values. It's easier to pretend that's always the case. | |||
local values = value | |||
local multivalue = type(value) == "table" | |||
if not multivalue then | |||
values = { value } | |||
end | |||
local errors = {} | |||
for k, value in ipairs(values) do | |||
if not utilsTable.keyOf(acceptedValues, value) then | |||
local path = utilsTable.concat(path or {}, multivalue and k or nil) | |||
local msg = isKey and "msg.enumKey" or "msg.enum" | |||
table.insert(errors, err(msg, name, path, options, { | |||
actualValue = code(value), | |||
enumDetails = enumDetails(acceptedValues), | |||
key = code(tostring(value)), | |||
})) | |||
end | |||
end | |||
return errors | |||
end | end | ||
end | end |
Latest revision as of 01:38, 12 November 2020
Submodule for Module:UtilsArg and Module:UtilsSchema.
local p = {}
local i18n = require("Module:I18n")
local s = i18n.getString
local utilsError = require("Module:UtilsError")
local utilsTable = require("Module:UtilsTable")
local function code(s)
return string.format("<code>%s</code>", s)
end
local function err(str, name, path, options, vars)
vars = utilsTable.merge(vars or {}, {
path = code(name .. utilsTable.printPath(path))
})
local msg = i18n.getString(str, vars)
local options = options or {}
local quiet = options.quiet
local stackTrace = options.stackTrace
local isUsageError = options.isUsageError
if isUsageError then
local invokeFrameTitle = mw.getCurrentFrame():getParent():getTitle()
if mw.title.new(invokeFrameTitle).nsText == "Template" then
msg = string.format("Misuse of [[%s]]: %s", invokeFrameTitle, msg)
end
end
if not quiet then
utilsError.warn(msg, {
traceBack = stackTrace,
omitFrames = 2
})
end
return msg
end
function p.required(value, name, path, isKey, options)
if value == nil then
return err("msg.required", name, path, options)
end
end
function p.nonEmpty(value, name, path, isKey, options)
local isEmpty =
value == nil
or type(value) == "string" and value == ""
or type(value) == "table" and utilsTable.isEqual({}, value)
if isEmpty then
return err("msg.empty", name, path, options, {
actualValue = code(utilsTable.print(value))
})
end
end
function p.deprecated(value, name, path, isKey, options)
if value ~= nil then
return err("msg.deprecated", name, path, options, {
value = code(value)
})
end
end
function p.type(expectedType)
return function(value, name, path, isKey, options)
local actualType = type(value)
if value ~= nil and actualType ~= expectedType then
local msg = isKey and "msg.typeKey" or "msg.type"
return err(msg, name, path, options, {
expectedType = code(expectedType),
actualType = code(actualType),
key = isKey and code(tostring(value)) or nil,
})
end
end
end
local function enumDetails(enum)
if enum.reference then
return s("msg.enumReference", {
referencePage = enum.reference
})
else
return s("msg.enumAccepted", {
values = code(utilsTable.print(enum, true))
})
end
end
function p.enum(acceptedValues)
return function (value, name, path, isKey, options)
if type(acceptedValues) == "function" then
acceptedValues = acceptedValues()
end
-- Sometimes the argument is a list of values. It's easier to pretend that's always the case.
local values = value
local multivalue = type(value) == "table"
if not multivalue then
values = { value }
end
for k, value in ipairs(values) do
if not utilsTable.keyOf(acceptedValues, value) then
local path = utilsTable.concat(path or {}, multivalue and k or nil)
local msg = isKey and "msg.enumKey" or "msg.enum"
return err(msg, name, path, options, {
actualValue = code(value),
enumDetails = enumDetails(acceptedValues),
key = code(tostring(value)),
})
end
end
end
end
function p._enum(acceptedValues)
return function (value, name, path, isKey, options)
if type(acceptedValues) == "function" then
acceptedValues = acceptedValues()
end
-- Sometimes the argument is a list of values. It's easier to pretend that's always the case.
local values = value
local multivalue = type(value) == "table"
if not multivalue then
values = { value }
end
local errors = {}
for k, value in ipairs(values) do
if not utilsTable.keyOf(acceptedValues, value) then
local path = utilsTable.concat(path or {}, multivalue and k or nil)
local msg = isKey and "msg.enumKey" or "msg.enum"
table.insert(errors, err(msg, name, path, options, {
actualValue = code(value),
enumDetails = enumDetails(acceptedValues),
key = code(tostring(value)),
}))
end
end
return errors
end
end
i18n.loadStrings({
en = {
msg = {
empty = "${path} must be non-empty but is ${actualValue}.",
required = "${path} is required but is <code>nil</code>.",
type = "${path} is type ${actualType} but type ${expectedType} was expected.",
typeKey = "${path} key ${key} is type ${actualType} but type ${expectedType} was expected.",
deprecated = "${path} is deprecated but has value ${value}.",
enum = "${path} has unexpected value ${actualValue}. ${enumDetails}",
enumKey = "${key} is not an acceptable key for ${path}. ${enumDetails}",
enumAccepted = "The accepted values are: ${values}",
enumReference = "For a list of accepted values, refer to ${referencePage}.",
},
},
})
return p