Mercurial > repo
view share/lua/5.2/luarocks/type_check.lua @ 8065:591b1467ccdf
<int-e> le/rn paste/"Paste" is a short story by Henry James. Its contents has been cut into pieces and distributed over numerous tin boxes on the World Wide Web, little pearls of wisdom buried among ordinary pastes.
author | HackBot |
---|---|
date | Sun, 15 May 2016 13:14:57 +0000 |
parents | d137f631bad5 |
children |
line wrap: on
line source
--- Type-checking functions. -- Functions and definitions for doing a basic lint check on files -- loaded by LuaRocks. module("luarocks.type_check", package.seeall) local cfg = require("luarocks.cfg") rockspec_format = "1.0" rockspec_types = { rockspec_format = "string", MUST_package = "string", MUST_version = "[%w.]+-[%d]+", description = { summary = "string", detailed = "string", homepage = "string", license = "string", maintainer = "string" }, dependencies = { platforms = {}, ANY = "string" }, supported_platforms = { ANY = "string" }, external_dependencies = { platforms = {}, ANY = { program = "string", header = "string", library = "string" } }, MUST_source = { platforms = {}, MUST_url = "string", md5 = "string", file = "string", dir = "string", tag = "string", branch = "string", module = "string", cvs_tag = "string", cvs_module = "string" }, build = { platforms = {}, type = "string", install = { lua = { MORE = true }, lib = { MORE = true }, conf = { MORE = true }, bin = { MORE = true } }, copy_directories = { ANY = "string" }, MORE = true }, hooks = { platforms = {}, post_install = "string" } } function load_extensions() rockspec_format = "1.1" rockspec_types.deploy = { wrap_bin_scripts = true, } end if cfg.use_extensions then load_extensions() end rockspec_types.build.platforms.ANY = rockspec_types.build rockspec_types.dependencies.platforms.ANY = rockspec_types.dependencies rockspec_types.external_dependencies.platforms.ANY = rockspec_types.external_dependencies rockspec_types.MUST_source.platforms.ANY = rockspec_types.MUST_source rockspec_types.hooks.platforms.ANY = rockspec_types.hooks manifest_types = { MUST_repository = { -- packages ANY = { -- versions ANY = { -- items ANY = { MUST_arch = "string", modules = { ANY = "string" }, commands = { ANY = "string" }, dependencies = { ANY = "string" }, -- TODO: to be extended with more metadata. } } } }, MUST_modules = { -- modules ANY = { -- providers ANY = "string" } }, MUST_commands = { -- modules ANY = { -- commands ANY = "string" } }, dependencies = { -- each module ANY = { -- each version ANY = { -- each dependency ANY = { name = "string", constraints = { ANY = { no_upgrade = "boolean", op = "string", version = { string = "string", ANY = 0, } } } } } } } } local type_check_table --- Type check an object. -- The object is compared against an archetypical value -- matching the expected type -- the actual values don't matter, -- only their types. Tables are type checked recursively. -- @param name any: The object name (for error messages). -- @param item any: The object being checked. -- @param expected any: The reference object. In case of a table, -- its is structured as a type reference table. -- @param context string: A string indicating the "context" where the -- error occurred (such as the name of the table the item is a part of), -- to be used by error messages. -- @return boolean or (nil, string): true if type checking -- succeeded, or nil and an error message if it failed. -- @see type_check_table local function type_check_item(name, item, expected, context) name = tostring(name) local item_type = type(item) local expected_type = type(expected) if expected_type == "number" then if not tonumber(item) then return nil, "Type mismatch on field "..context..name..": expected a number" end elseif expected_type == "string" then if type(item) ~= "string" then return nil, "Type mismatch on field "..context..name..": expected a string" end if expected ~= "string" then if not item:match("^"..expected.."$") then return nil, "Type mismatch on field "..context..name..": invalid value "..item end end elseif expected_type == "table" then if item_type ~= expected_type then return nil, "Type mismatch on field "..context..name..": expected a table" else return type_check_table(item, expected, context..name..".") end elseif item_type ~= expected_type then return nil, "Type mismatch on field "..context..name..": expected a "..expected_type end return true end --- Type check the contents of a table. -- The table's contents are compared against a reference table, -- which contains the recognized fields, with archetypical values -- matching the expected types -- the actual values of items in the -- reference table don't matter, only their types (ie, for field x -- in tbl that is correctly typed, type(tbl.x) == type(types.x)). -- If the reference table contains a field called MORE, then -- unknown fields in the checked table are accepted. -- If it contains a field called ANY, then its type will be -- used to check any unknown fields. If a field is prefixed -- with MUST_, it is mandatory; its absence from the table is -- a type error. -- Tables are type checked recursively. -- @param tbl table: The table to be type checked. -- @param types table: The reference table, containing -- values for recognized fields in the checked table. -- @param context string: A string indicating the "context" where the -- error occurred (such as the name of the table the item is a part of), -- to be used by error messages. -- @return boolean or (nil, string): true if type checking -- succeeded, or nil and an error message if it failed. type_check_table = function(tbl, types, context) assert(type(tbl) == "table") assert(type(types) == "table") for k, v in pairs(tbl) do local t = types[k] or (type(k) == "string" and types["MUST_"..k]) or types.ANY if t then local ok, err = type_check_item(k, v, t, context) if not ok then return nil, err end elseif types.MORE then -- Accept unknown field else if not cfg.accept_unknown_fields then return nil, "Unknown field "..k end end end for k, v in pairs(types) do local mandatory_key = k:match("^MUST_(.+)") if mandatory_key then if not tbl[mandatory_key] then return nil, "Mandatory field "..context..mandatory_key.." is missing." end end end return true end --- Type check a rockspec table. -- Verify the correctness of elements from a -- rockspec table, reporting on unknown fields and type -- mismatches. -- @return boolean or (nil, string): true if type checking -- succeeded, or nil and an error message if it failed. function type_check_rockspec(rockspec) assert(type(rockspec) == "table") if rockspec.rockspec_format then -- relies on global state load_extensions() end return type_check_table(rockspec, rockspec_types, "") end --- Type check a manifest table. -- Verify the correctness of elements from a -- manifest table, reporting on unknown fields and type -- mismatches. -- @return boolean or (nil, string): true if type checking -- succeeded, or nil and an error message if it failed. function type_check_manifest(manifest) assert(type(manifest) == "table") return type_check_table(manifest, manifest_types, "") end