diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2021-06-17 16:45:53 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2021-06-17 16:45:53 +0800 |
commit | e67dd05a15a76d9ee6addb6519fd98e6527d2b09 (patch) | |
tree | 520a569d1a4bb8a3e4e0bbbc219e62bc5ed5a969 | |
parent | 844bc87bcb11fade43e06b5e8ac8421f2b0d3630 (diff) | |
download | lua-language-server-e67dd05a15a76d9ee6addb6519fd98e6527d2b09.zip |
stash
-rw-r--r-- | script/core/collector.lua | 71 | ||||
-rw-r--r-- | script/core/noder.lua | 32 | ||||
-rw-r--r-- | script/core/searcher.lua | 29 | ||||
-rw-r--r-- | script/parser/guide.lua | 6 | ||||
-rw-r--r-- | script/vm/docs.lua | 51 | ||||
-rw-r--r-- | script/vm/getDocs.lua | 86 | ||||
-rw-r--r-- | script/vm/globals.lua | 51 | ||||
-rw-r--r-- | script/vm/init.lua | 2 |
8 files changed, 138 insertions, 190 deletions
diff --git a/script/core/collector.lua b/script/core/collector.lua new file mode 100644 index 00000000..763d145b --- /dev/null +++ b/script/core/collector.lua @@ -0,0 +1,71 @@ +local collect = {} +local subscribed = {} + +local m = {} + +--- 订阅一个名字 +---@param uri uri +---@param name string +---@param value any +function m.subscribe(uri, name, value) + -- 订阅部分 + local uriSubscribed = subscribed[uri] + if not uriSubscribed then + uriSubscribed = {} + subscribed[uri] = uriSubscribed + end + uriSubscribed[name] = true + -- 收集部分 + local nameCollect = collect[name] + if not nameCollect then + nameCollect = {} + collect[name] = nameCollect + end + if value == nil then + value = true + end + nameCollect[uri] = value +end + +--- 丢弃掉某个 uri 中收集的所有信息 +---@param uri uri +function m.dropUri(uri) + local uriSubscribed = subscribed[uri] + if not uriSubscribed then + return + end + subscribed[uri] = nil + for name in pairs(uriSubscribed) do + collect[name][uri] = nil + end +end + +--- 是否包含某个名字的订阅 +---@param name string +---@return boolean +function m.has(name) + local nameCollect = collect[name] + if not nameCollect then + return false + end + if next(nameCollect) == nil then + return false + end + return true +end + +--- 迭代某个名字的订阅 +---@param name string +function m.each(name) + local nameCollect = collect[name] + if not nameCollect then + return function () end + end + local uri, value + return function () + uri, value = next(nameCollect, uri) + return value + end +end + +return m diff --git a/script/core/noder.lua b/script/core/noder.lua index 7ec02c69..43d349ee 100644 --- a/script/core/noder.lua +++ b/script/core/noder.lua @@ -1,5 +1,6 @@ -local util = require 'utility' -local guide = require 'parser.guide' +local util = require 'utility' +local guide = require 'parser.guide' +local collector = require 'core.collector' local LastIDCache = {} local FirstIDCache = {} @@ -516,10 +517,11 @@ local function compileCall(noders, call, sourceID, returnIndex) pushForward(noders, sourceID, funcXID) end +---@param uri uri ---@param noders noders ---@param source parser.guide.object ---@return parser.guide.object[] -function m.compileNode(noders, source) +function m.compileNode(uri, noders, source) local id = getID(source) bindValue(noders, source, id) if source.special == 'setmetatable' @@ -694,6 +696,26 @@ function m.compileNode(noders, source) ) pushForward(noders, keyID, 'dn:integer') end + if source.type == 'doc.type.name' then + collector.subscribe(uri, id, getNode(noders, id)) + end + if source.type == 'doc.class.name' then + collector.subscribe(uri, id, getNode(noders, id)) + collector.subscribe(uri, 'def:' .. id, getNode(noders, id)) + collector.subscribe(uri, 'def:dn', getNode(noders, id)) + end + if source.type == 'doc.alias.name' then + collector.subscribe(uri, id, getNode(noders, id)) + collector.subscribe(uri, 'def:' .. id, getNode(noders, id)) + collector.subscribe(uri, 'def:dn', getNode(noders, id)) + end + if guide.isGlobal(source) then + collector.subscribe(uri, id, getNode(noders, id)) + if guide.isSet(source) then + collector.subscribe(uri, 'def:' .. id, getNode(noders, id)) + collector.subscribe(uri, 'def:g', getNode(noders, id)) + end + end -- 将函数的返回值映射到具体的返回值上 if source.type == 'function' then local hasDocReturn = {} @@ -971,10 +993,12 @@ function m.compileNodes(source) if next(noders) then return noders end + local uri = guide.getUri(root) + collector.dropUri(uri) log.debug('compileNodes:', guide.getUri(root)) guide.eachSource(root, function (src) m.pushSource(noders, src) - m.compileNode(noders, src) + m.compileNode(uri, noders, src) end) log.debug('compileNodes finish:', guide.getUri(root)) return noders diff --git a/script/core/searcher.lua b/script/core/searcher.lua index 972350fd..5a417765 100644 --- a/script/core/searcher.lua +++ b/script/core/searcher.lua @@ -1,12 +1,11 @@ -local noder = require 'core.noder' -local guide = require 'parser.guide' -local files = require 'files' -local generic = require 'core.generic' -local ws = require 'workspace' -local vm = require 'vm.vm' -local globals = require 'vm.globals' -local docs = require 'vm.docs' -local await = require 'await' +local noder = require 'core.noder' +local guide = require 'parser.guide' +local files = require 'files' +local generic = require 'core.generic' +local ws = require 'workspace' +local vm = require 'vm.vm' +local await = require 'await' +local collector = require 'core.collector' local NONE = {'NONE'} local LAST = {'LAST'} @@ -466,10 +465,6 @@ function m.searchRefsByID(status, uri, expect, mode) end local function checkGlobal(id, node, field) - local uris = globals.getUrisByID(id) - if not uris then - return - end if status.crossed[id] then return end @@ -482,7 +477,7 @@ function m.searchRefsByID(status, uri, expect, mode) if FOOTPRINT then status.footprint[#status.footprint+1] = ('checkGlobal:%s + %s, isCall: %s'):format(id, field, isCall, tid) end - for guri, def in pairs(uris) do + for guri, def in collector.each(id) do if def then crossSearch(status, guri, tid, mode, uri) goto CONTINUE @@ -506,16 +501,12 @@ function m.searchRefsByID(status, uri, expect, mode) end local function checkClass(id, node, field) - local uris = docs.getUrisByID(id) - if not uris then - return - end if status.crossed[id] then return end status.crossed[id] = true local tid = id .. (field or '') - for guri in pairs(uris) do + for guri in collector.each(id) do if not files.eq(uri, guri) then crossSearch(status, guri, tid, mode, uri) end diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 8d2708cf..ad07e90e 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -972,9 +972,13 @@ end ---@param source parser.guide.object ---@return boolean function m.isGlobal(source) + if source._isGlobal ~= nil then + return source._isGlobal + end if source.type == 'setglobal' or source.type == 'getglobal' then if source.node and source.node.tag == '_ENV' then + source._isGlobal = true return true end end @@ -982,8 +986,10 @@ function m.isGlobal(source) source = source.parent end if source.special == '_G' then + source._isGlobal = true return true end + source._isGlobal = false return false end diff --git a/script/vm/docs.lua b/script/vm/docs.lua deleted file mode 100644 index df87d46a..00000000 --- a/script/vm/docs.lua +++ /dev/null @@ -1,51 +0,0 @@ -local files = require 'files' -local noder = require 'core.noder' - -local docsMap = {} -local subscribeMap = {} - -local function popDocs(uri) - if not subscribeMap[uri] then - return - end - for id in pairs(subscribeMap[uri]) do - if docsMap[id] then - docsMap[id][uri] = nil - end - end - subscribeMap[uri] = nil -end - -local function pushDocs(uri) - subscribeMap[uri] = {} - local state = files.getState(uri) - if not state then - return - end - local nodes = noder.compileNodes(state.ast) - for id in pairs(nodes) do - if id:sub(1, 3) == 'dn:' - and noder.getFirstID(id) == id then - if not docsMap[id] then - docsMap[id] = {} - end - docsMap[id][uri] = true - subscribeMap[uri][id] = true - end - end -end - -files.watch(function (ev, uri) - if ev == 'update' then - popDocs(uri) - pushDocs(uri) - end -end) - -local m = {} - -function m.getUrisByID(id) - return docsMap[id] -end - -return m diff --git a/script/vm/getDocs.lua b/script/vm/getDocs.lua index bf99a247..16b82278 100644 --- a/script/vm/getDocs.lua +++ b/script/vm/getDocs.lua @@ -1,51 +1,32 @@ -local files = require 'files' -local guide = require 'parser.guide' ----@type vm -local vm = require 'vm.vm' -local config = require 'config' -local docs = require 'vm.docs' -local define = require 'proto.define' -local noder = require 'core.noder' - -local function getDocDefinesInAst(results, root, name) - for _, doc in ipairs(root.docs) do - if doc.type == 'doc.class' then - if not name or name == doc.class[1] then - results[#results+1] = doc.class - end - elseif doc.type == 'doc.alias' then - if not name or name == doc.alias[1] then - results[#results+1] = doc.alias - end - end - end -end +local files = require 'files' +local guide = require 'parser.guide' +local vm = require 'vm.vm' +local config = require 'config' +local collector = require 'core.collector' +local define = require 'proto.define' +local noder = require 'core.noder' ---获取class与alias ---@param name? string ---@return parser.guide.object[] function vm.getDocDefines(name) + local cache = vm.getCache 'getDocDefines' + if cache[name] then + return cache[name] + end local results = {} - if name then - local id = 'dn:' .. name - local uris = docs.getUrisByID(id) - if not uris then - return results - end - for uri in pairs(uris) do - local state = files.getState(uri) - if state then - getDocDefinesInAst(results, state.ast, name) - end - end - else - for uri in files.eachFile() do - local state = files.getState(uri) - if state then - getDocDefinesInAst(results, state.ast, name) + local id = 'def:dn:' .. (name or '') + for node in collector.each(id) do + if node.sources then + for _, source in ipairs(node.sources) do + if source.type == 'doc.class.name' + or source.type == 'doc.alias.name' then + results[#results+1] = source + end end end end + cache[name] = results return results end @@ -53,31 +34,10 @@ function vm.isDocDefined(name) if define.BuiltinClass[name] then return true end - local cache = vm.getCache 'isDocDefined' - if cache[name] ~= nil then - return cache[name] - end - local id = 'dn:' .. name - local uris = docs.getUrisByID(id) - if not uris then - cache[name] = false - return - end - for uri in pairs(uris) do - local state = files.getState(uri) - local node = noder.getNodeByID(state.ast, id) - if node and node.sources then - for _, source in ipairs(node.sources) do - local doc = source.parent - if doc.type == 'doc.class' - or doc.type == 'doc.alias' then - cache[name] = true - return true - end - end - end + local id = 'def:dn:' .. name + if collector.has(id) then + return true end - cache[name] = false return false end diff --git a/script/vm/globals.lua b/script/vm/globals.lua deleted file mode 100644 index 3c74f8b0..00000000 --- a/script/vm/globals.lua +++ /dev/null @@ -1,51 +0,0 @@ -local files = require 'files' -local noder = require 'core.noder' - -local globalsMap = {} -local subscribeMap = {} - -local function popGlobals(uri) - if not subscribeMap[uri] then - return - end - for id in pairs(subscribeMap[uri]) do - if globalsMap[id] then - globalsMap[id][uri] = nil - end - end - subscribeMap[uri] = nil -end - -local function pushGlobals(uri) - subscribeMap[uri] = {} - local state = files.getState(uri) - if not state then - return - end - local nodes = noder.compileNodes(state.ast) - for id in pairs(nodes) do - if id:sub(1, 2) == 'g:' - and noder.getFirstID(id) == id then - if not globalsMap[id] then - globalsMap[id] = {} - end - globalsMap[id][uri] = true - subscribeMap[uri][id] = true - end - end -end - -files.watch(function (ev, uri) - if ev == 'update' then - popGlobals(uri) - pushGlobals(uri) - end -end) - -local m = {} - -function m.getUrisByID(id) - return globalsMap[id] -end - -return m diff --git a/script/vm/init.lua b/script/vm/init.lua index 705a7117..c38f01d5 100644 --- a/script/vm/init.lua +++ b/script/vm/init.lua @@ -6,6 +6,4 @@ require 'vm.eachDef' require 'vm.eachRef' require 'vm.getLinks' require 'vm.guideInterface' -require 'vm.globals' -require 'vm.docs' return vm |