diff options
Diffstat (limited to 'script')
-rw-r--r-- | script/core/diagnostics/undefined-field.lua | 2 | ||||
-rw-r--r-- | script/parser/guide.lua | 63 | ||||
-rw-r--r-- | script/vm/eachField.lua | 57 |
3 files changed, 105 insertions, 17 deletions
diff --git a/script/core/diagnostics/undefined-field.lua b/script/core/diagnostics/undefined-field.lua index cc873ab2..31bd9008 100644 --- a/script/core/diagnostics/undefined-field.lua +++ b/script/core/diagnostics/undefined-field.lua @@ -55,7 +55,7 @@ return function (uri, callback) local fields = {} local empty = true for _, docClass in ipairs(allDocClass) do - local refs = vm.getFieldsOfDocClassAnyNotGet(docClass) + local refs = vm.getDefFields(docClass) for _, ref in ipairs(refs) do local name = vm.getKeyName(ref) diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 4c89a09c..a6149dd7 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -29,9 +29,7 @@ end local m = {} -m.ANY = {"ANY"} - -m.ANYNOTGET = {"ANYNOTGET"} +m.ANY = {"<ANY>"} local blockTypes = { ['while'] = true, @@ -1401,6 +1399,16 @@ function m.searchFields(status, obj, key) m.cleanResults(status.results) end +function m.searchDefFields(status, obj, key) + local simple = m.getSimple(obj) + if not simple then + return + end + simple[#simple+1] = key or m.ANY + m.searchSameFields(status, simple, 'deffield') + m.cleanResults(status.results) +end + function m.getObjectValue(obj) while obj.type == 'paren' do obj = obj.exp @@ -1436,7 +1444,7 @@ end function m.checkSameSimpleInValueInMetaTable(status, mt, start, pushQueue) local newStatus = m.status(status) - m.searchFields(newStatus, mt, '__index') + m.searchDefFields(newStatus, mt, '__index') local refsStatus = m.status(status) for i = 1, #newStatus.results do local indexValue = m.getObjectValue(newStatus.results[i]) @@ -1684,7 +1692,8 @@ function m.checkSameSimpleByDoc(status, obj, start, pushQueue, mode) end return true elseif obj.type == 'doc.field' then - if mode ~= 'field' then + if mode ~= 'field' + and mode ~= 'deffield' then return m.checkSameSimpleByDoc(status, obj.extends, start, pushQueue, mode) end elseif obj.type == 'doc.type.array' then @@ -2309,6 +2318,30 @@ function m.pushResult(status, mode, ref, simple) or ref.type == 'doc.field' then results[#results+1] = ref end + elseif mode == 'deffield' then + if ref.type == 'setfield' + or ref.type == 'tablefield' then + results[#results+1] = ref + elseif ref.type == 'setmethod' then + results[#results+1] = ref + elseif ref.type == 'setindex' + or ref.type == 'tableindex' then + results[#results+1] = ref + elseif ref.type == 'setglobal' then + results[#results+1] = ref + elseif ref.type == 'function' then + results[#results+1] = ref + elseif ref.type == 'table' then + results[#results+1] = ref + elseif ref.type == 'call' then + if ref.node.special == 'rawset' then + results[#results+1] = ref + end + elseif ref.type == 'doc.type.function' + or ref.type == 'doc.class.name' + or ref.type == 'doc.field' then + results[#results+1] = ref + end end end @@ -2317,7 +2350,7 @@ function m.checkSameSimpleName(ref, sm) return true end - if sm == m.ANYNOTGET and not m.isGet(ref) then + if sm == m.ANY_DEF and m.isSet(ref) then return true end @@ -2663,13 +2696,16 @@ function m.searchRefs(status, obj, mode) end -- 检查单步引用 + tracy.ZoneBeginN('searchRefs getStepRef') local res = m.getStepRef(status, obj, mode) if res then for i = 1, #res do status.results[#status.results+1] = res[i] end end + tracy.ZoneEnd() -- 检查simple + tracy.ZoneBeginN('searchRefs searchSameFields') if status.depth <= 100 then local simple = m.getSimple(obj) if simple then @@ -2683,6 +2719,7 @@ function m.searchRefs(status, obj, mode) logWarn('status.depth overflow') end end + tracy.ZoneEnd() m.cleanResults(status.results) @@ -4103,8 +4140,8 @@ function m.requestDefinition(obj, interface, deep) return status.results, status.share.count end ---- 请求对象的域 ----@param filterKey nil|string|table nil表fields不做限制;string表fields必须同名;table取值为guild.ANYSET表fields必须满足isSet() +--- 请求对象的字段 +---@param filterKey nil|string|table function m.requestFields(obj, interface, deep, filterKey) local status = m.status(nil, interface, deep) @@ -4113,6 +4150,16 @@ function m.requestFields(obj, interface, deep, filterKey) return status.results, status.share.count end +--- 请求对象的定义字段 +---@param filterKey nil|string|table +function m.requestDefFields(obj, interface, deep, filterKey) + local status = m.status(nil, interface, deep) + + m.searchDefFields(status, obj, filterKey) + + return status.results, status.share.count +end + --- 请求对象的类型推测 function m.requestInfer(obj, interface, deep) local status = m.status(nil, interface, deep) diff --git a/script/vm/eachField.lua b/script/vm/eachField.lua index 7c5c98f8..690f6aa4 100644 --- a/script/vm/eachField.lua +++ b/script/vm/eachField.lua @@ -25,6 +25,27 @@ local function getFields(source, deep, filterKey) return results end +local function getDefFields(source, deep, filterKey) + local unlock = vm.lock('eachDefField', source) + if not unlock then + return {} + end + + while source.type == 'paren' do + source = source.exp + if not source then + return {} + end + end + deep = config.config.intelliSense.searchDepth + (deep or 0) + + await.delay() + local results = guide.requestDefFields(source, vm.interface, deep, filterKey) + + unlock() + return results +end + local function getFieldsBySource(source, deep, filterKey) deep = deep or -999 local cache = vm.getCache('eachField')[source] @@ -38,6 +59,19 @@ local function getFieldsBySource(source, deep, filterKey) return cache end +local function getDefFieldsBySource(source, deep, filterKey) + deep = deep or -999 + local cache = vm.getCache('eachDefField')[source] + if not cache or cache.deep < deep then + cache = getDefFields(source, deep, filterKey) + cache.deep = deep + if not filterKey then + vm.getCache('eachDefField')[source] = cache + end + end + return cache +end + function vm.getFields(source, deep) if source.special == '_G' then return vm.getGlobals '*' @@ -56,13 +90,20 @@ function vm.getFields(source, deep) end end -function vm.getFieldsOfDocClassAnyNotGet(source, deep) - if not guide.isDocClass(source) then - return {} +function vm.getDefFields(source, deep) + if source.special == '_G' then + return vm.getGlobalSets '*' + end + if guide.isGlobal(source) then + local name = guide.getKeyName(source) + if not name then + return {} + end + local cache = vm.getCache('eachDefFieldOfGlobal')[name] + or getDefFieldsBySource(source, deep) + vm.getCache('eachDefFieldOfGlobal')[name] = cache + return cache + else + return getDefFieldsBySource(source, deep) end - - local cache = vm.getCache('eachFieldOfDocClass')[source] - or getFieldsBySource(source, deep, guide.ANYNOTGET) - vm.getCache('eachFieldOfDocClass')[source] = cache - return cache end |