Skip to content

Commit

Permalink
types: reports record functions in record field list
Browse files Browse the repository at this point in the history
Also, strip typedecls from type report, and represent records
in the "str" field by their declared name.

Thanks @pdesaulniers for the report!
  • Loading branch information
hishamhm committed Sep 21, 2024
1 parent b618edb commit 6117c8c
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 4 deletions.
28 changes: 28 additions & 0 deletions spec/api/get_types_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,32 @@ describe("tl.get_types", function()
local type_at_y_x = tr.by_pos[""][y][x]
assert(tr.types[type_at_y_x].str == "function(string)")
end)

it("reports record functions in record field list", function()
local env = tl.init_env()
env.report_types = true
local result = assert(tl.check_string([[
local record Point
x: number
y: number
end
function Point:init(x: number, y: number)
self.x = x
self.y = y
end
]], env))

local tr, trenv = tl.get_types(result)
local y = 1
local x = 10
local type_at_y_x = tr.by_pos[""][y][x]
assert(tr.types[type_at_y_x].str == "Point")
local fields = {}
for k, _ in pairs(tr.types[type_at_y_x].fields) do
table.insert(fields, k)
end
table.sort(fields)
assert.same(fields, {"init", "x", "y"})
end)
end)
15 changes: 13 additions & 2 deletions tl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5860,7 +5860,7 @@ function TypeReporter:get_typenum(t)
end

if rt.typename == "typedecl" then
rt = rt.def
return self:get_typenum(rt.def)
end

local ti = {
Expand Down Expand Up @@ -5916,6 +5916,13 @@ function TypeReporter:get_typenum(t)
return n
end

function TypeReporter:add_field(rtype, fname, ftype)
local n = self:get_typenum(rtype)
local ti = self.tr.types[n]
assert(ti.fields)
ti.fields[fname] = self:get_typenum(ftype)
end




Expand Down Expand Up @@ -6758,7 +6765,7 @@ local function show_type_base(t, short, seen)
elseif t.typename == "enum" then
return t.declname or "enum"
elseif t.fields then
return short and t.typename or t.typename .. show_fields(t, show)
return short and (t.declname or t.typename) or t.typename .. show_fields(t, show)
elseif t.typename == "function" then
local out = { "function" }
if t.typeargs then
Expand Down Expand Up @@ -11981,6 +11988,10 @@ self:expand_type(node, values, elements) })
if self.feat_lax or rtype == open_t then
rtype.fields[node.name.tk] = fn_type
table.insert(rtype.field_order, node.name.tk)

if self.collector then
self.env.reporter:add_field(rtype, node.name.tk, fn_type)
end
else
self.errs:add(node, "cannot add undeclared function '" .. node.name.tk .. "' outside of the scope where '" .. owner_name .. "' was originally declared")
return
Expand Down
15 changes: 13 additions & 2 deletions tl.tl
Original file line number Diff line number Diff line change
Expand Up @@ -5860,7 +5860,7 @@ function TypeReporter:get_typenum(t: Type): integer
end

if rt is TypeDeclType then
rt = rt.def
return self:get_typenum(rt.def)
end

local ti: TypeInfo = {
Expand Down Expand Up @@ -5916,6 +5916,13 @@ function TypeReporter:get_typenum(t: Type): integer
return n
end

function TypeReporter:add_field(rtype: RecordLikeType, fname: string, ftype: Type)
local n = self:get_typenum(rtype)
local ti = self.tr.types[n]
assert(ti.fields)
ti.fields[fname] = self:get_typenum(ftype)
end

local record TypeCollector
record Symbol
x: integer
Expand Down Expand Up @@ -6758,7 +6765,7 @@ local function show_type_base(t: Type, short: boolean, seen: {Type:string}): str
elseif t is EnumType then
return t.declname or "enum"
elseif t is RecordLikeType then
return short and t.typename or t.typename .. show_fields(t, show)
return short and (t.declname or t.typename) or t.typename .. show_fields(t, show)
elseif t is FunctionType then
local out: {string} = {"function"}
if t.typeargs then
Expand Down Expand Up @@ -11981,6 +11988,10 @@ do
if self.feat_lax or rtype == open_t then
rtype.fields[node.name.tk] = fn_type
table.insert(rtype.field_order, node.name.tk)

if self.collector then
self.env.reporter:add_field(rtype, node.name.tk, fn_type)
end
else
self.errs:add(node, "cannot add undeclared function '" .. node.name.tk .. "' outside of the scope where '" .. owner_name .. "' was originally declared")
return
Expand Down

0 comments on commit 6117c8c

Please sign in to comment.