diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-01-19 18:04:00 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2022-01-19 18:04:00 +0800 |
commit | 021ceef2e05c781e849e1bac86eaae6e36775cf9 (patch) | |
tree | 7fb2371f2377c624f9d7a71e1e1fce2b07adde4e | |
parent | d6859305513099d125f6dad69cb35f29b796bebf (diff) | |
download | lua-language-server-021ceef2e05c781e849e1bac86eaae6e36775cf9.zip |
stash
-rw-r--r-- | script/core/collector.lua | 65 | ||||
-rw-r--r-- | script/core/diagnostics/undefined-global.lua | 4 | ||||
-rw-r--r-- | script/core/noder.lua | 24 | ||||
-rw-r--r-- | script/core/searcher.lua | 16 | ||||
-rw-r--r-- | script/vm/getDocs.lua | 8 | ||||
-rw-r--r-- | script/vm/getGlobals.lua | 8 | ||||
-rw-r--r-- | script/workspace/require-path.lua | 63 |
7 files changed, 116 insertions, 72 deletions
diff --git a/script/core/collector.lua b/script/core/collector.lua index 57ae3adc..62ca5a7d 100644 --- a/script/core/collector.lua +++ b/script/core/collector.lua @@ -1,28 +1,29 @@ local scope = require 'workspace.scope' -local ws = require 'workspace' -local collect = {} -local subscribed = {} - -local m = {} +---@class collector +---@field subscribed table<uri, table<string, any>> +---@field collect table<string, table<uri, any>> +local mt = {} +mt.__index = mt --- 订阅一个名字 ---@param uri uri ---@param name string ---@param value any -function m.subscribe(uri, name, value) +function mt:subscribe(uri, name, value) + uri = uri or '<fallback>' -- 订阅部分 - local uriSubscribed = subscribed[uri] + local uriSubscribed = self.subscribed[uri] if not uriSubscribed then uriSubscribed = {} - subscribed[uri] = uriSubscribed + self.subscribed[uri] = uriSubscribed end uriSubscribed[name] = true -- 收集部分 - local nameCollect = collect[name] + local nameCollect = self.collect[name] if not nameCollect then nameCollect = {} - collect[name] = nameCollect + self.collect[name] = nameCollect end if value == nil then value = true @@ -32,27 +33,33 @@ end --- 丢弃掉某个 uri 中收集的所有信息 ---@param uri uri -function m.dropUri(uri) - local uriSubscribed = subscribed[uri] +function mt:dropUri(uri) + uri = uri or '<fallback>' + local uriSubscribed = self.subscribed[uri] if not uriSubscribed then return end - subscribed[uri] = nil + self.subscribed[uri] = nil for name in pairs(uriSubscribed) do - collect[name][uri] = nil + self.collect[name][uri] = nil end end +function mt:dropAll() + self.subscribed = {} + self.collect = {} +end + --- 是否包含某个名字的订阅 ---@param name string ---@return boolean -function m.has(name) - local nameCollect = collect[name] +function mt:has(name) + local nameCollect = self.collect[name] if not nameCollect then return false end if next(nameCollect) == nil then - collect[name] = nil + self.collect[name] = nil return false end return true @@ -139,8 +146,9 @@ end --- 迭代某个名字的订阅 ---@param uri uri ---@param name string -function m.each(uri, name) - local nameCollect = collect[name] +function mt:each(uri, name) + uri = uri or '<fallback>' + local nameCollect = self.collect[name] if not nameCollect then return DUMMY_FUNCTION end @@ -160,4 +168,21 @@ function m.each(uri, name) return eachOfFallback(nameCollect, scope.fallback) end -return m +local collectors = {} + +local function new() + return setmetatable({ + collect = {}, + subscribed = {}, + }, mt) +end + +---@return collector +return function (name) + if name then + collectors[name] = collectors[name] or new() + return collectors[name] + else + return new() + end +end diff --git a/script/core/diagnostics/undefined-global.lua b/script/core/diagnostics/undefined-global.lua index 45fc390b..5ac5106d 100644 --- a/script/core/diagnostics/undefined-global.lua +++ b/script/core/diagnostics/undefined-global.lua @@ -4,7 +4,7 @@ local lang = require 'language' local config = require 'config' local guide = require 'parser.guide' local noder = require 'core.noder' -local collector = require 'core.collector' +local collector = require 'core.collector' 'searcher' local await = require 'await' local requireLike = { @@ -39,7 +39,7 @@ return function (uri, callback) end await.delay() local id = 'def:' .. noder.getID(src) - if not collector.has(id) then + if not collector:has(id) then local message = lang.script('DIAG_UNDEF_GLOBAL', key) if requireLike[key:lower()] then message = ('%s(%s)'):format(message, lang.script('DIAG_REQUIRE_LIKE', key)) diff --git a/script/core/noder.lua b/script/core/noder.lua index f648d6c5..4ecfb032 100644 --- a/script/core/noder.lua +++ b/script/core/noder.lua @@ -1,6 +1,6 @@ local util = require 'utility' local guide = require 'parser.guide' -local collector = require 'core.collector' +local collector = require 'core.collector' 'searcher' local files = require 'files' local config = require 'config' @@ -1254,19 +1254,19 @@ compileNodeMap = util.switch() : case 'doc.type.name' : call(function (noders, id, source) local uri = guide.getUri(source) - collector.subscribe(uri, id, noders) + collector:subscribe(uri, id, noders) end) : case 'doc.class.name' : case 'doc.alias.name' : call(function (noders, id, source) local uri = guide.getUri(source) - collector.subscribe(uri, id, noders) + collector:subscribe(uri, id, noders) local defID = 'def:' .. id - collector.subscribe(uri, defID, noders) + collector:subscribe(uri, defID, noders) local defAnyID = 'def:dn:' - collector.subscribe(uri, defAnyID, noders) + collector:subscribe(uri, defAnyID, noders) end) : case 'function' : call(function (noders, id, source) @@ -1511,24 +1511,24 @@ function m.compileNode(noders, source) if id and ssub(id, 1, 2) == 'g:' then local uri = guide.getUri(source) - collector.subscribe(uri, id, noders) + collector:subscribe(uri, id, noders) if guide.isSet(source) -- local t = Global --> t: g:.Global and source.type ~= 'local' and source.type ~= 'setlocal' then local defID = 'def:' .. id - collector.subscribe(uri, defID, noders) + collector:subscribe(uri, defID, noders) local fieldID = m.getLastID(id) if fieldID then local defNodeID = 'field:' .. fieldID - collector.subscribe(uri, defNodeID, noders) + collector:subscribe(uri, defNodeID, noders) end if guide.isGlobal(source) then local defAnyID = 'def:g:' - collector.subscribe(uri, defAnyID, noders) + collector:subscribe(uri, defAnyID, noders) end end end @@ -1737,7 +1737,7 @@ function m.compileAllNodes(source) end root._initedNoders = true if not root._compiledGlobals then - collector.dropUri(guide.getUri(root)) + collector:dropUri(guide.getUri(root)) end root._compiledGlobals = true --log.debug('compileNodes:', guide.getUri(root)) @@ -1876,7 +1876,7 @@ function m.compileGlobalNodes(root) return end if not root._compiledGlobals then - collector.dropUri(guide.getUri(root)) + collector:dropUri(guide.getUri(root)) end root._compiledGlobals = true local noders = m.getNoders(root) @@ -1909,7 +1909,7 @@ files.watch(function (ev, uri) end end if ev == 'remove' then - collector.dropUri(uri) + collector:dropUri(uri) end end) diff --git a/script/core/searcher.lua b/script/core/searcher.lua index 5beaf26b..17e14b9c 100644 --- a/script/core/searcher.lua +++ b/script/core/searcher.lua @@ -4,7 +4,7 @@ local files = require 'files' local generic = require 'core.generic' local rpath = require 'workspace.require-path' local vm = require 'vm.vm' -local collector = require 'core.collector' +local collector = require 'core.collector' 'searcher' local util = require 'utility' local TRACE = TRACE @@ -25,8 +25,6 @@ local sformat = string.format local getUri = guide.getUri -local ceach = collector.each - local getState = files.getState local getNoders = noder.getNoders @@ -817,7 +815,7 @@ function m.searchRefsByID(status, suri, expect, mode) or mode == 'alldef' or field or hasCall(field) then - for _, guri in ceach(suri, 'def:' .. id) do + for _, guri in collector:each(suri, 'def:' .. id) do if uri == guri then goto CONTINUE end @@ -826,14 +824,14 @@ function m.searchRefsByID(status, suri, expect, mode) end elseif mode == 'field' or mode == 'allfield' then - for _, guri in ceach(suri, 'def:' .. id) do + for _, guri in collector:each(suri, 'def:' .. id) do if uri == guri then goto CONTINUE end searchID(guri, id, field, uri) ::CONTINUE:: end - for _, guri in ceach(suri, 'field:' .. id) do + for _, guri in collector:each(suri, 'field:' .. id) do if uri == guri then goto CONTINUE end @@ -841,7 +839,7 @@ function m.searchRefsByID(status, suri, expect, mode) ::CONTINUE:: end else - for _, guri in ceach(suri, id) do + for _, guri in collector:each(suri, id) do if crossed[guri] then goto CONTINUE end @@ -869,7 +867,7 @@ function m.searchRefsByID(status, suri, expect, mode) or ignoredIDs[id] or id == 'dn:string' or hasCall(field) then - for _, guri in ceach(suri, 'def:' .. id) do + for _, guri in collector:each(suri, 'def:' .. id) do if uri == guri then goto CONTINUE end @@ -877,7 +875,7 @@ function m.searchRefsByID(status, suri, expect, mode) ::CONTINUE:: end else - for _, guri in ceach(suri, id) do + for _, guri in collector:each(suri, id) do if crossed[guri] then goto CONTINUE end diff --git a/script/vm/getDocs.lua b/script/vm/getDocs.lua index c635b2a9..cfad021c 100644 --- a/script/vm/getDocs.lua +++ b/script/vm/getDocs.lua @@ -3,7 +3,7 @@ local guide = require 'parser.guide' ---@class vm local vm = require 'vm.vm' local config = require 'config' -local collector = require 'core.collector' +local collector = require 'core.collector' 'searcher' local define = require 'proto.define' local noder = require 'core.noder' @@ -17,7 +17,7 @@ function vm.getDocDefines(uri, name) end local results = {} if name == '*' then - for noders in collector.each(uri, 'def:dn:') do + for noders in collector:each(uri, 'def:dn:') do for id in noder.eachID(noders) do if id:sub(1, 3) == 'dn:' and not id:find(noder.SPLIT_CHAR) then @@ -31,7 +31,7 @@ function vm.getDocDefines(uri, name) end else local id = 'dn:' .. name - for noders in collector.each(uri, 'def:' .. id) do + for noders in collector:each(uri, 'def:' .. id) do for source in noder.eachSource(noders, id) do if source.type == 'doc.class.name' or source.type == 'doc.alias.name' then @@ -49,7 +49,7 @@ function vm.isDocDefined(name) return true end local id = 'def:dn:' .. name - if collector.has(id) then + if collector:has(id) then return true end return false diff --git a/script/vm/getGlobals.lua b/script/vm/getGlobals.lua index f6646559..b9ddedab 100644 --- a/script/vm/getGlobals.lua +++ b/script/vm/getGlobals.lua @@ -1,4 +1,4 @@ -local collector = require 'core.collector' +local collector = require 'core.collector' 'searcher' local guide = require 'parser.guide' ---@class vm local vm = require 'vm.vm' @@ -11,7 +11,7 @@ function vm.hasGlobalSets(name) else id = ('def:g:%s'):format(noder.STRING_CHAR, name) end - return collector.has(id) + return collector:has(id) end function vm.getGlobalSets(uri, name) @@ -22,7 +22,7 @@ function vm.getGlobalSets(uri, name) local results = {} cache[name] = results if name == '*' then - for noders in collector.each(uri, 'def:g:') do + for noders in collector:each(uri, 'def:g:') do for id in noder.eachID(noders) do if id:sub(1, 2) == 'g:' and not id:find(noder.SPLIT_CHAR) then @@ -41,7 +41,7 @@ function vm.getGlobalSets(uri, name) else id = ('g:%s'):format(noder.STRING_CHAR, name) end - for noders in collector.each(uri, 'def:' .. id) do + for noders in collector:each(uri, 'def:' .. id) do for source in noder.eachSource(noders, id) do if guide.isSet(source) then results[#results+1] = source diff --git a/script/workspace/require-path.lua b/script/workspace/require-path.lua index 84541808..577da85e 100644 --- a/script/workspace/require-path.lua +++ b/script/workspace/require-path.lua @@ -3,9 +3,16 @@ local files = require 'files' local furi = require 'file-uri' local workspace = require "workspace" local config = require 'config' +local collector = require 'core.collector' 'require-path' + +---@class require-path local m = {} -m.cache = {} +local function addRequireName(suri, uri, name) + local separator = config.get(uri, 'Lua.completion.requireSeparator') + local fsname = name:gsub('%' .. separator, '/') + collector:subscribe(suri, fsname, uri) +end --- `aaa/bbb/ccc.lua` 与 `?.lua` 将返回 `aaa.bbb.cccc` local function getOnePath(uri, path, searcher) @@ -33,9 +40,11 @@ function m.getVisiblePath(suri, path) path = workspace.normalize(path) local uri = furi.encode(path) local libraryPath = files.getLibraryPath(uri) - if not m.cache[path] then + local scp = workspace.getScope(suri) + local cache = scp:get('visiblePath') or scp:set('visiblePath', {}) + if not cache[path] then local result = {} - m.cache[path] = result + cache[path] = result if libraryPath then libraryPath = libraryPath:gsub('^[/\\]+', '') end @@ -73,11 +82,12 @@ function m.getVisiblePath(suri, path) searcher = mySearcher, expect = expect, } + addRequireName(suri, uri, expect) end until not pos or strict end end - return m.cache[path] + return cache[path] end --- 查找符合指定require path的所有uri @@ -88,11 +98,6 @@ function m.findUrisByRequirePath(suri, path) end local separator = config.get(suri, 'Lua.completion.requireSeparator') local fspath = path:gsub('%' .. separator, '/') - local vm = require 'vm' - local cache = vm.getCache 'findUrisByRequirePath' - if cache[path] then - return cache[path].results, cache[path].searchers - end tracy.ZoneBeginN('findUrisByRequirePath') local results = {} local searchers = {} @@ -105,7 +110,7 @@ function m.findUrisByRequirePath(suri, path) end end - for uri in files.eachFile() do + for uri in collector:each(suri, fspath) do local infos = m.getVisiblePath(suri, furi.decode(uri)) for _, info in ipairs(infos) do local fsexpect = info.expect:gsub('%' .. separator, '/') @@ -117,21 +122,37 @@ function m.findUrisByRequirePath(suri, path) end tracy.ZoneEnd() - cache[path] = { - results = results, - searchers = searchers, - } return results, searchers end -function m.flush() - m.cache = {} +local function createVisiblePath(uri) + for _, scp in ipairs(workspace.folders) do + m.getVisiblePath(scp.uri, furi.decode(uri)) + end + m.getVisiblePath(nil, furi.decode(uri)) end -files.watch(function (ev) - if ev == 'create' - or ev == 'remove' then - m.flush() +function m.flush(suri) + local scp = workspace.getScope(suri) + scp:set('visiblePath', {}) + collector:dropAll() + for uri in files.eachFile() do + createVisiblePath(uri) + end +end + +m.flush(nil) + +files.watch(function (ev, uri) + if ev == 'create' then + createVisiblePath(uri) + end + if ev == 'remove' then + for _, scp in ipairs(workspace.folders) do + scp:get('visiblePath')[uri] = nil + end + workspace.getScope(nil):get('visiblePath')[uri] = nil + collector:dropUri(uri) end end) @@ -139,7 +160,7 @@ config.watch(function (uri, key, value, oldValue) if key == 'Lua.completion.requireSeparator' or key == 'Lua.runtime.path' or key == 'Lua.runtime.pathStrict' then - m.flush() + m.flush(uri) end end) |