summaryrefslogtreecommitdiff
path: root/script/core/diagnostics
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-11-14 20:25:50 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-11-14 20:25:50 +0800
commitccce6e0b430a29cd58bfcffc07fd17ebaba3ddc4 (patch)
treecae77f4b8b96f1b0f7af7e26579e6b7f3a8b34b7 /script/core/diagnostics
parent09c4ae6d4960fc4ac93e202a8419c8b0a2d7a477 (diff)
downloadlua-language-server-ccce6e0b430a29cd58bfcffc07fd17ebaba3ddc4.zip
`duplicate-doc-field` check cross files
Diffstat (limited to 'script/core/diagnostics')
-rw-r--r--script/core/diagnostics/duplicate-doc-field.lua88
1 files changed, 62 insertions, 26 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