diff --git a/projects/core/src/main/resources/data/computercraft/lua/rom/modules/main/cc/expect.lua b/projects/core/src/main/resources/data/computercraft/lua/rom/modules/main/cc/expect.lua index 85b3f5a0b..10daf68d6 100644 --- a/projects/core/src/main/resources/data/computercraft/lua/rom/modules/main/cc/expect.lua +++ b/projects/core/src/main/resources/data/computercraft/lua/rom/modules/main/cc/expect.lua @@ -42,6 +42,21 @@ local function get_type_names(...) return table.concat(types, ", ", 1, #types - 1) .. " or " .. types[#types] end end + + +local function get_display_type(value, t) + -- Lua is somewhat inconsistent in whether it obeys __name just for values which + -- have a per-instance metatable (so tables/userdata) or for everything. We follow + -- Cobalt and only read the metatable for tables/userdata. + if t ~= "table" and t ~= "userdata" then return t end + + local metatable = debug.getmetatable(value) + if not metatable then return t end + + local name = rawget(metatable, "__name") + if type(name) == "string" then return name else return t end +end + --- Expect an argument to have a specific type. -- -- @tparam number index The 1-based argument index. @@ -60,6 +75,8 @@ local function expect(index, value, ...) local ok, info = pcall(debug.getinfo, 3, "nS") if ok and info.name and info.name ~= "" and info.what ~= "C" then name = info.name end + t = get_display_type(value, t) + local type_names = get_type_names(...) if name then error(("bad argument #%d to '%s' (expected %s, got %s)"):format(index, name, type_names, t), 3) @@ -85,6 +102,8 @@ local function field(tbl, index, ...) if t == native_select(i, ...) then return value end end + t = get_display_type(value, t) + if value == nil then error(("field '%s' missing from table"):format(index), 3) else diff --git a/projects/core/src/test/resources/test-rom/spec/modules/cc/expect_spec.lua b/projects/core/src/test/resources/test-rom/spec/modules/cc/expect_spec.lua index 3b1af1eb8..7eb320a39 100644 --- a/projects/core/src/test/resources/test-rom/spec/modules/cc/expect_spec.lua +++ b/projects/core/src/test/resources/test-rom/spec/modules/cc/expect_spec.lua @@ -33,6 +33,12 @@ describe("cc.expect", function() expect.error(trampoline):str_match("^[^:]*expect_spec.lua:31: bad argument #1 to 'worker' %(expected string, got nil%)$") end) + + it("supports custom type names", function() + local value = setmetatable({}, { __name = "some type" }) + + expect.error(e.expect, 1, value, "string"):eq("bad argument #1 (expected string, got some type)") + end) end) describe("field", function()