diff options
-rw-r--r-- | script/core/diagnostics/duplicate-doc-field.lua | 88 | ||||
-rw-r--r-- | test/crossfile/diagnostic.lua | 11 | ||||
-rw-r--r-- | test/diagnostics/common.lua | 6 |
3 files changed, 76 insertions, 29 deletions
diff --git a/script/core/diagnostics/duplicate-doc-field.lua b/script/core/diagnostics/duplicate-doc-field.lua index a30dfa88..098b41a4 100644 --- a/script/core/diagnostics/duplicate-doc-field.lua +++ b/script/core/diagnostics/duplicate-doc-field.lua @@ -2,6 +2,7 @@ local files = require 'files' local lang = require 'language' local vm = require 'vm.vm' local await = require 'await' +local guide = require 'parser.guide' local function getFieldEventName(doc) if not doc.extends then @@ -41,34 +42,69 @@ return function (uri, callback) return end - local mark - for _, group in ipairs(state.ast.docs.groups) do - for _, doc in ipairs(group) do - if doc.type == 'doc.class' then - mark = {} - elseif doc.type == 'doc.field' then - if mark then - await.delay() - local name - if doc.field.type == 'doc.type' then - name = ('[%s]'):format(vm.getInfer(doc.field):view(uri)) - else - name = ('%q'):format(doc.field[1]) - end - local eventName = getFieldEventName(doc) - if eventName then - name = name .. '|' .. eventName - end - if mark[name] then - callback { - start = doc.field.start, - finish = doc.field.finish, - message = lang.script('DIAG_DUPLICATE_DOC_FIELD', name), - } - end - mark[name] = true + local cachedKeys = {} + + ---@param field parser.object + ---@return string? + local function viewKey(field) + if not cachedKeys[field] then + local view = vm.viewKey(field, uri) + if view then + local eventName = getFieldEventName(field) + if eventName then + view = view .. '|' .. eventName + end + end + cachedKeys[field] = view or false + end + return cachedKeys[field] or nil + end + + ---@async + ---@param myField parser.object + local function checkField(myField) + await.delay() + local myView = viewKey(myField) + if not myView then + return + end + + local class = myField.class + if not class then + return + end + for _, set in ipairs(vm.getGlobal('type', class.class[1]):getSets(uri)) do + if not set.fields then + goto CONTINUE + end + for _, field in ipairs(set.fields) do + if field == myField then + goto CONTINUE + end + local view = viewKey(field) + if view ~= myView then + goto CONTINUE end + callback { + start = myField.field.start, + finish = myField.field.finish, + message = lang.script('DIAG_DUPLICATE_DOC_FIELD', myView), + related = {{ + start = field.field.start, + finish = field.field.finish, + uri = guide.getUri(field), + }} + } + do return end + ::CONTINUE:: end + ::CONTINUE:: + end + end + + for _, doc in ipairs(state.ast.docs) do + if doc.type == 'doc.field' then + checkField(doc) end end end diff --git a/test/crossfile/diagnostic.lua b/test/crossfile/diagnostic.lua index e574204a..58c89805 100644 --- a/test/crossfile/diagnostic.lua +++ b/test/crossfile/diagnostic.lua @@ -165,3 +165,14 @@ TEST { print(obj.<!x!>) ]]} } + +TEST { + { path = 'a.lua', content = [[ + ---@class A + ---@field <!x!> number + ]]}, + { path = 'b.lua', content = [[ + ---@class A + ---@field <!x!> number + ]]} +} diff --git a/test/diagnostics/common.lua b/test/diagnostics/common.lua index 760f1f6f..5e0b3d2a 100644 --- a/test/diagnostics/common.lua +++ b/test/diagnostics/common.lua @@ -895,7 +895,7 @@ TEST [[ TEST [[ ---@class Class ----@field x Class +---@field <!x!> Class ---@field <!x!> Class ]] @@ -1275,7 +1275,7 @@ local emit = {} TEST [[ --- @class Emit --- @field on fun(eventName: string, cb: function) ---- @field on fun(eventName: '"died"', cb: fun(i: integer)) +--- @field <!on!> fun(eventName: '"died"', cb: fun(i: integer)) --- @field on fun(eventName: '"won"', cb: fun(s: string)) --- @field <!on!> fun(eventName: '"died"', cb: fun(i: integer)) local emit = {} @@ -1738,7 +1738,7 @@ TEST [[ ---@class A ---@class B ----@field [A] A +---@field [<!A!>] A ---@field [<!A!>] true ]] |