diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2023-08-23 15:13:51 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2023-08-23 15:13:51 +0800 |
commit | c2018e05de0e9eebadbe094357d22883a608fdf5 (patch) | |
tree | 9a95a05a88f0e828c37c973732ef15fc80ce216b /script/core | |
parent | cb16010fbb4128e2a5a31013e02b8cc4a4318be8 (diff) | |
download | lua-language-server-c2018e05de0e9eebadbe094357d22883a608fdf5.zip |
support `---@class (exact)`
#1990
Diffstat (limited to 'script/core')
-rw-r--r-- | script/core/diagnostics/inject-field.lua | 81 |
1 files changed, 68 insertions, 13 deletions
diff --git a/script/core/diagnostics/inject-field.lua b/script/core/diagnostics/inject-field.lua index 570ca270..2866eef8 100644 --- a/script/core/diagnostics/inject-field.lua +++ b/script/core/diagnostics/inject-field.lua @@ -37,14 +37,29 @@ return function (uri, callback) return end + local isExact local class = vm.getDefinedClass(uri, node) if class then - return + for _, doc in ipairs(class:getSets(uri)) do + if vm.docHasAttr(doc, 'exact') then + isExact = true + break + end + end + if not isExact then + return + end + if src.type == 'setmethod' + and not guide.getSelfNode(node) then + return + end end for _, def in ipairs(vm.getDefs(src)) do local dnode = def.node - if dnode and vm.getDefinedClass(uri, dnode) then + if dnode + and not isExact + and vm.getDefinedClass(uri, dnode) then return end if def.type == 'doc.type.field' then @@ -55,16 +70,19 @@ return function (uri, callback) end end - local howToFix = lang.script('DIAG_INJECT_FIELD_FIX_CLASS', { - node = hname(node), - fix = '---@class', - }) - for _, ndef in ipairs(vm.getDefs(node)) do - if ndef.type == 'doc.type.table' then - howToFix = lang.script('DIAG_INJECT_FIELD_FIX_TABLE', { - fix = '[any]: any', - }) - break + local howToFix = '' + if not isExact then + howToFix = lang.script('DIAG_INJECT_FIELD_FIX_CLASS', { + node = hname(node), + fix = '---@class', + }) + for _, ndef in ipairs(vm.getDefs(node)) do + if ndef.type == 'doc.type.table' then + howToFix = lang.script('DIAG_INJECT_FIELD_FIX_TABLE', { + fix = '[any]: any', + }) + break + end end end @@ -79,7 +97,7 @@ return function (uri, callback) finish = src.field.finish, message = message, } - elseif src.type == 'setfield' and src.method then + elseif src.type == 'setmethod' and src.method then callback { start = src.method.start, finish = src.method.finish, @@ -89,4 +107,41 @@ return function (uri, callback) end guide.eachSourceType(ast.ast, 'setfield', checkInjectField) guide.eachSourceType(ast.ast, 'setmethod', checkInjectField) + + ---@async + local function checkExtraTableField(src) + await.delay() + + if not src.bindSource then + return + end + if not vm.docHasAttr(src, 'exact') then + return + end + local value = src.bindSource.value + if not value or value.type ~= 'table' then + return + end + for _, field in ipairs(value) do + local defs = vm.getDefs(field) + for _, def in ipairs(defs) do + if def.type == 'doc.field' then + goto nextField + end + end + local message = lang.script('DIAG_INJECT_FIELD', { + class = vm.getInfer(src):view(uri), + field = guide.getKeyName(src), + fix = '', + }) + callback { + start = field.start, + finish = field.finish, + message = message, + } + ::nextField:: + end + end + + guide.eachSourceType(ast.ast, 'doc.class', checkExtraTableField) end |