summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-01-19 18:04:00 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-01-19 18:04:00 +0800
commit021ceef2e05c781e849e1bac86eaae6e36775cf9 (patch)
tree7fb2371f2377c624f9d7a71e1e1fce2b07adde4e
parentd6859305513099d125f6dad69cb35f29b796bebf (diff)
downloadlua-language-server-021ceef2e05c781e849e1bac86eaae6e36775cf9.zip
stash
-rw-r--r--script/core/collector.lua65
-rw-r--r--script/core/diagnostics/undefined-global.lua4
-rw-r--r--script/core/noder.lua24
-rw-r--r--script/core/searcher.lua16
-rw-r--r--script/vm/getDocs.lua8
-rw-r--r--script/vm/getGlobals.lua8
-rw-r--r--script/workspace/require-path.lua63
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)