summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2020-05-26 13:51:26 +0800
committerGitHub <noreply@github.com>2020-05-26 13:51:26 +0800
commitd7b7bd258df58c8b9fea5d5ac110975e7387cd9c (patch)
treed400a9cb6f1a897913ff9fe56d7d0e83c45c078b
parent0583236680b16588c52c7c98ac5a3f8a7071b868 (diff)
parent9dc816f99f4a4329a3daff55a7199a8265a00c2c (diff)
downloadlua-language-server-d7b7bd258df58c8b9fea5d5ac110975e7387cd9c.zip
Merge pull request #167 from Ruin0x11/multi-workspace
Support multiple workspace folders
-rw-r--r--script/core/completion.lua16
-rw-r--r--script/core/hover/hover.lua8
-rw-r--r--script/method/init.lua1
-rw-r--r--script/method/initialize.lua13
-rw-r--r--script/method/initialized.lua63
-rw-r--r--script/method/textDocument/codeAction.lua3
-rw-r--r--script/method/textDocument/completion.lua3
-rw-r--r--script/method/textDocument/didChange.lua12
-rw-r--r--script/method/textDocument/didClose.lua3
-rw-r--r--script/method/textDocument/didOpen.lua3
-rw-r--r--script/method/textDocument/documentHighlight.lua3
-rw-r--r--script/method/textDocument/documentSymbol.lua3
-rw-r--r--script/method/textDocument/foldingRange.lua3
-rw-r--r--script/method/textDocument/hover.lua3
-rw-r--r--script/method/textDocument/implementation.lua3
-rw-r--r--script/method/textDocument/onTypeFormatting.lua3
-rw-r--r--script/method/textDocument/publishDiagnostics.lua3
-rw-r--r--script/method/textDocument/references.lua3
-rw-r--r--script/method/textDocument/rename.lua3
-rw-r--r--script/method/textDocument/semanticTokens.lua3
-rw-r--r--script/method/textDocument/signatureHelp.lua3
-rw-r--r--script/method/workspace/didChangeConfiguration.lua47
-rw-r--r--script/method/workspace/didChangeWatchedFiles.lua33
-rw-r--r--script/method/workspace/didChangeWorkspaceFolders.lua43
-rw-r--r--script/method/workspace/executeCommand.lua16
-rw-r--r--script/service.lua101
-rw-r--r--script/vm/vm.lua12
-rw-r--r--script/workspace.lua12
-rw-r--r--test/crossfile/completion.lua4
-rw-r--r--test/crossfile/definition.lua3
-rw-r--r--test/crossfile/document_symbol.lua3
-rw-r--r--test/crossfile/hover.lua4
-rw-r--r--test/crossfile/references.lua4
33 files changed, 324 insertions, 116 deletions
diff --git a/script/core/completion.lua b/script/core/completion.lua
index 6b503bd5..a62a5f1c 100644
--- a/script/core/completion.lua
+++ b/script/core/completion.lua
@@ -663,14 +663,21 @@ local function buildTextEdit(start, finish, str, quo)
}
end
+--- @param vm VM
+--- @param source table
+--- @param callback function
local function searchInRequire(vm, source, callback)
- if not vm.lsp or not vm.lsp.workspace then
+ if not vm.lsp then
+ return
+ end
+ local ws = vm.lsp:findWorkspaceFor(vm.uri)
+ if not ws then
return
end
if source.type ~= 'string' then
return
end
- local list, map = vm.lsp.workspace:matchPath(vm.uri, source[1])
+ local list, map = ws:matchPath(vm.uri, source[1])
if not list then
return
end
@@ -1039,6 +1046,11 @@ local function getSource(vm, pos, text, filter)
return source, pos, word
end
+--- @param vm VM
+--- @param text string
+--- @param pos table
+--- @param oldText string
+--- @return table
return function (vm, text, pos, oldText)
local filter = {
['name'] = true,
diff --git a/script/core/hover/hover.lua b/script/core/hover/hover.lua
index 2ee5cf46..1e8cf4d1 100644
--- a/script/core/hover/hover.lua
+++ b/script/core/hover/hover.lua
@@ -294,10 +294,14 @@ end
local function hoverAsTargetUri(source, lsp)
local uri = source:get 'target uri'
- if not lsp or not lsp.workspace then
+ if not lsp then
return nil
end
- local path = lsp.workspace:relativePathByUri(uri)
+ local ws = lsp:findWorkspaceFor(uri)
+ if not ws then
+ return nil
+ end
+ local path = ws:relativePathByUri(uri)
if not path then
return nil
end
diff --git a/script/method/init.lua b/script/method/init.lua
index 41ff3ec3..dd662a2d 100644
--- a/script/method/init.lua
+++ b/script/method/init.lua
@@ -27,6 +27,7 @@ init 'textDocument/semanticTokens'
init 'textDocument/signatureHelp'
init 'workspace/didChangeConfiguration'
init 'workspace/didChangeWatchedFiles'
+init 'workspace/didChangeWorkspaceFolders'
init 'workspace/executeCommand'
return method
diff --git a/script/method/initialize.lua b/script/method/initialize.lua
index be553325..0f986dc1 100644
--- a/script/method/initialize.lua
+++ b/script/method/initialize.lua
@@ -11,15 +11,21 @@ local function allWords()
return list
end
+--- @param lsp LSP
+--- @param params table
+--- @return table
return function (lsp, params)
lsp._inited = true
lsp.client = params
client.init(params)
log.info(table.dump(params))
- if params.rootUri then
- lsp.workspace = workspace(lsp, 'root')
- lsp.workspace:init(params.rootUri)
+ if params.workspaceFolders then
+ for _, folder in ipairs(params.workspaceFolders) do
+ lsp:addWorkspace(folder.name, folder.uri)
+ end
+ elseif params.rootUri then
+ lsp:addWorkspace('root', params.rootUri)
end
local server = {
@@ -45,6 +51,7 @@ return function (lsp, params)
workspace = {
workspaceFolders = {
supported = true,
+ changeNotifications = true,
}
},
documentOnTypeFormattingProvider = {
diff --git a/script/method/initialized.lua b/script/method/initialized.lua
index e4ab585b..9e37fb37 100644
--- a/script/method/initialized.lua
+++ b/script/method/initialized.lua
@@ -1,8 +1,37 @@
-local rpc = require 'rpc'
-local workspace = require 'workspace'
+local rpc = require 'rpc'
+
+--- @param lsp LSP
+--- @return boolean
+return function (lsp)
+ local ws = lsp.workspaces[1]
+
+ if ws then
+ -- 请求工作目录
+ local uri = ws.uri
+ -- 请求配置
+ rpc:request('workspace/configuration', {
+ items = {
+ {
+ scopeUri = uri,
+ section = 'Lua',
+ },
+ {
+ scopeUri = uri,
+ section = 'files.associations',
+ },
+ {
+ scopeUri = uri,
+ section = 'files.exclude',
+ }
+ },
+ }, function (configs)
+ lsp:onUpdateConfig(configs[1], {
+ associations = configs[2],
+ exclude = configs[3],
+ })
+ end)
+ end
-local function initAfterConfig(lsp)
- -- 必须动态注册的事件:
rpc:request('client/registerCapability', {
registrations = {
-- 监视文件变化
@@ -27,32 +56,6 @@ local function initAfterConfig(lsp)
}, function ()
log.debug('client/registerCapability Success!')
end)
-end
-return function (lsp)
- local uri = lsp.workspace and lsp.workspace.uri
- -- 请求配置
- rpc:request('workspace/configuration', {
- items = {
- {
- scopeUri = uri,
- section = 'Lua',
- },
- {
- scopeUri = uri,
- section = 'files.associations',
- },
- {
- scopeUri = uri,
- section = 'files.exclude',
- }
- },
- }, function (configs)
- lsp:onUpdateConfig(configs[1], {
- associations = configs[2],
- exclude = configs[3],
- })
- initAfterConfig(lsp)
- end)
return true
end
diff --git a/script/method/textDocument/codeAction.lua b/script/method/textDocument/codeAction.lua
index 3c6e8d49..80a40a0c 100644
--- a/script/method/textDocument/codeAction.lua
+++ b/script/method/textDocument/codeAction.lua
@@ -1,5 +1,8 @@
local core = require 'core'
+--- @param lsp LSP
+--- @param params table
+--- @return table
return function (lsp, params)
local uri = params.textDocument.uri
local vm, lines = lsp:getVM(uri)
diff --git a/script/method/textDocument/completion.lua b/script/method/textDocument/completion.lua
index d622fe73..0ede5903 100644
--- a/script/method/textDocument/completion.lua
+++ b/script/method/textDocument/completion.lua
@@ -82,6 +82,9 @@ local function cuterFactory(lines, text, position)
end
end
+--- @param lsp LSP
+--- @param params table
+--- @return table
return function (lsp, params)
local uri = params.textDocument.uri
local text, oldText = lsp:getText(uri)
diff --git a/script/method/textDocument/didChange.lua b/script/method/textDocument/didChange.lua
index 82e6c096..83701662 100644
--- a/script/method/textDocument/didChange.lua
+++ b/script/method/textDocument/didChange.lua
@@ -1,12 +1,16 @@
+--- @param lsp LSP
+--- @param params table
+--- @return boolean
return function (lsp, params)
local doc = params.textDocument
local change = params.contentChanges
- if lsp.workspace then
- local path = lsp.workspace:relativePathByUri(doc.uri)
- if not path or not lsp.workspace:isLuaFile(path) then
+ local ws = lsp:findWorkspaceFor(doc.uri)
+ if ws then
+ local path = ws:relativePathByUri(doc.uri)
+ if not path or not ws:isLuaFile(path) then
return
end
- if not lsp:isOpen(doc.uri) and lsp.workspace.gitignore(path:string()) then
+ if not lsp:isOpen(doc.uri) and ws.gitignore(path:string()) then
return
end
end
diff --git a/script/method/textDocument/didClose.lua b/script/method/textDocument/didClose.lua
index 589b212f..3cfd98e8 100644
--- a/script/method/textDocument/didClose.lua
+++ b/script/method/textDocument/didClose.lua
@@ -1,3 +1,6 @@
+--- @param lsp LSP
+--- @param params table
+--- @return boolean
return function (lsp, params)
local doc = params.textDocument
lsp:close(doc.uri)
diff --git a/script/method/textDocument/didOpen.lua b/script/method/textDocument/didOpen.lua
index e2a67fd2..d9b0de53 100644
--- a/script/method/textDocument/didOpen.lua
+++ b/script/method/textDocument/didOpen.lua
@@ -1,3 +1,6 @@
+--- @param lsp LSP
+--- @param params table
+--- @return boolean
return function (lsp, params)
local doc = params.textDocument
lsp:open(doc.uri, doc.version, doc.text)
diff --git a/script/method/textDocument/documentHighlight.lua b/script/method/textDocument/documentHighlight.lua
index 377ffcdf..2a6768f2 100644
--- a/script/method/textDocument/documentHighlight.lua
+++ b/script/method/textDocument/documentHighlight.lua
@@ -1,5 +1,8 @@
local core = require 'core'
+--- @param lsp LSP
+--- @param params table
+--- @return table
return function (lsp, params)
local uri = params.textDocument.uri
local vm, lines = lsp:loadVM(uri)
diff --git a/script/method/textDocument/documentSymbol.lua b/script/method/textDocument/documentSymbol.lua
index a4b0c3b7..a84afb7a 100644
--- a/script/method/textDocument/documentSymbol.lua
+++ b/script/method/textDocument/documentSymbol.lua
@@ -32,6 +32,9 @@ local function convertRange(lines, symbol)
end
end
+--- @param lsp LSP
+--- @param params table
+--- @return function
return function (lsp, params)
local uri = params.textDocument.uri
diff --git a/script/method/textDocument/foldingRange.lua b/script/method/textDocument/foldingRange.lua
index 0320b422..6395c908 100644
--- a/script/method/textDocument/foldingRange.lua
+++ b/script/method/textDocument/foldingRange.lua
@@ -16,6 +16,9 @@ local function convertRange(lines, range)
return result
end
+--- @param lsp LSP
+--- @param params table
+--- @return function
return function (lsp, params)
local uri = params.textDocument.uri
if timerCache[uri] then
diff --git a/script/method/textDocument/hover.lua b/script/method/textDocument/hover.lua
index f8dba27c..2e909dc1 100644
--- a/script/method/textDocument/hover.lua
+++ b/script/method/textDocument/hover.lua
@@ -1,5 +1,8 @@
local core = require 'core'
+--- @param lsp LSP
+--- @param params table
+--- @return table
return function (lsp, params)
local uri = params.textDocument.uri
local vm, lines = lsp:loadVM(uri)
diff --git a/script/method/textDocument/implementation.lua b/script/method/textDocument/implementation.lua
index 14e2f24c..94991fd4 100644
--- a/script/method/textDocument/implementation.lua
+++ b/script/method/textDocument/implementation.lua
@@ -77,6 +77,9 @@ end
local LastTask
+--- @param lsp LSP
+--- @param params table
+--- @return function
return function (lsp, params)
if LastTask then
LastTask:remove()
diff --git a/script/method/textDocument/onTypeFormatting.lua b/script/method/textDocument/onTypeFormatting.lua
index fc9cbdc9..8485ab49 100644
--- a/script/method/textDocument/onTypeFormatting.lua
+++ b/script/method/textDocument/onTypeFormatting.lua
@@ -1,3 +1,6 @@
+--- @param lsp LSP
+--- @param params table
+--- @return any
return function (lsp, params)
local uri = params.textDocument.uri
local vm, lines = lsp:loadVM(uri)
diff --git a/script/method/textDocument/publishDiagnostics.lua b/script/method/textDocument/publishDiagnostics.lua
index c767e934..0a2900fa 100644
--- a/script/method/textDocument/publishDiagnostics.lua
+++ b/script/method/textDocument/publishDiagnostics.lua
@@ -140,6 +140,9 @@ local function buildError(err, lines, uri)
return diagnostic
end
+--- @param lsp LSP
+--- @param params table
+--- @return table
return function (lsp, params)
local vm = params.vm
local lines = params.lines
diff --git a/script/method/textDocument/references.lua b/script/method/textDocument/references.lua
index 0a198323..6421145e 100644
--- a/script/method/textDocument/references.lua
+++ b/script/method/textDocument/references.lua
@@ -54,6 +54,9 @@ local function findReferences(lsp, uri, position)
return locations, isGlobal
end
+--- @param lsp LSP
+--- @param params table
+--- @return function
return function (lsp, params)
local uri = params.textDocument.uri
local declarat = params.context.includeDeclaration
diff --git a/script/method/textDocument/rename.lua b/script/method/textDocument/rename.lua
index 6da9c721..b637141d 100644
--- a/script/method/textDocument/rename.lua
+++ b/script/method/textDocument/rename.lua
@@ -1,5 +1,8 @@
local core = require 'core'
+--- @param lsp LSP
+--- @param params table
+--- @return table
return function (lsp, params)
local uri = params.textDocument.uri
local newName = params.newName
diff --git a/script/method/textDocument/semanticTokens.lua b/script/method/textDocument/semanticTokens.lua
index 03f0163a..bc6d2bcb 100644
--- a/script/method/textDocument/semanticTokens.lua
+++ b/script/method/textDocument/semanticTokens.lua
@@ -169,6 +169,9 @@ local function testTokens(vm, lines)
return tokens
end
+--- @param lsp LSP
+--- @param params table
+--- @return function
return function (lsp, params)
local uri = params.textDocument.uri
diff --git a/script/method/textDocument/signatureHelp.lua b/script/method/textDocument/signatureHelp.lua
index 01d6289d..e7e695ca 100644
--- a/script/method/textDocument/signatureHelp.lua
+++ b/script/method/textDocument/signatureHelp.lua
@@ -1,5 +1,8 @@
local core = require 'core'
+--- @param lsp LSP
+--- @param params table
+--- @return table
return function (lsp, params)
local uri = params.textDocument.uri
local vm, lines = lsp:loadVM(uri)
diff --git a/script/method/workspace/didChangeConfiguration.lua b/script/method/workspace/didChangeConfiguration.lua
index ecaa9182..eca61ebc 100644
--- a/script/method/workspace/didChangeConfiguration.lua
+++ b/script/method/workspace/didChangeConfiguration.lua
@@ -1,27 +1,30 @@
local rpc = require 'rpc'
+--- @param lsp LSP
return function (lsp)
- local uri = lsp.workspace and lsp.workspace.uri
- -- 请求配置
- rpc:request('workspace/configuration', {
- items = {
- {
- scopeUri = uri,
- section = 'Lua',
+ for _, ws in ipairs(lsp.workspaces) do
+ local uri = ws.uri
+ -- 请求配置
+ rpc:request('workspace/configuration', {
+ items = {
+ {
+ scopeUri = uri,
+ section = 'Lua',
+ },
+ {
+ scopeUri = uri,
+ section = 'files.associations',
+ },
+ {
+ scopeUri = uri,
+ section = 'files.exclude',
+ }
},
- {
- scopeUri = uri,
- section = 'files.associations',
- },
- {
- scopeUri = uri,
- section = 'files.exclude',
- }
- },
- }, function (configs)
- lsp:onUpdateConfig(configs[1], {
- associations = configs[2],
- exclude = configs[3],
- })
- end)
+ }, function (configs)
+ lsp:onUpdateConfig(configs[1], {
+ associations = configs[2],
+ exclude = configs[3],
+ })
+ end)
+ end
end
diff --git a/script/method/workspace/didChangeWatchedFiles.lua b/script/method/workspace/didChangeWatchedFiles.lua
index 3ce68924..3d8fc599 100644
--- a/script/method/workspace/didChangeWatchedFiles.lua
+++ b/script/method/workspace/didChangeWatchedFiles.lua
@@ -7,38 +7,45 @@ local FileChangeType = {
Deleted = 3,
}
+--- @param lsp LSP
+--- @param params table
return function (lsp, params)
- if not lsp.workspace then
- return
- end
- local needReset
+ local needReset = {}
+ local needRescan
for _, change in ipairs(params.changes) do
+ local ws = lsp:findWorkspaceFor(change.uri)
+ if not ws then
+ goto CONTINUE
+ end
local path = uric.decode(change.uri)
if not path then
goto CONTINUE
end
if change.type == FileChangeType.Created then
- lsp.workspace:addFile(path)
+ ws:addFile(path)
if lsp:getVM(change.uri) then
- needReset = true
+ needReset[ws] = true
end
elseif change.type == FileChangeType.Deleted then
- lsp.workspace:removeFile(path)
+ ws:removeFile(path)
if lsp:getVM(change.uri) then
- needReset = true
+ needReset[ws] = true
end
end
-- 排除类文件发生更改需要重新扫描
local filename = path:filename():string()
- if lsp.workspace:fileNameEq(filename, '.gitignore')
- or lsp.workspace:fileNameEq(filename, '.gitmodules')
+ if ws:fileNameEq(filename, '.gitignore')
+ or ws:fileNameEq(filename, '.gitmodules')
then
- lsp:reScanFiles()
+ needRescan = true
end
::CONTINUE::
end
+ if needRescan then
+ lsp:reScanFiles()
+ end
-- 缓存过的文件发生变化后,重新计算
- if needReset then
- lsp.workspace:reset()
+ for ws, _ in pairs(needReset) do
+ ws:reset()
end
end
diff --git a/script/method/workspace/didChangeWorkspaceFolders.lua b/script/method/workspace/didChangeWorkspaceFolders.lua
new file mode 100644
index 00000000..25c06f4b
--- /dev/null
+++ b/script/method/workspace/didChangeWorkspaceFolders.lua
@@ -0,0 +1,43 @@
+local rpc = require 'rpc'
+
+--- @param lsp LSP
+--- @param params table
+return function (lsp, params)
+ local event = params.event
+
+ for _, removed in ipairs(event.removed) do
+ lsp:removeWorkspace(removed.name, removed.uri)
+ end
+
+ for _, added in ipairs(event.added) do
+ lsp:addWorkspace(added.name, added.uri)
+ end
+
+ local ws = lsp.workspaces[1]
+ if ws then
+ -- 请求工作目录
+ local uri = ws.uri
+ -- 请求配置
+ rpc:request('workspace/configuration', {
+ items = {
+ {
+ scopeUri = uri,
+ section = 'Lua',
+ },
+ {
+ scopeUri = uri,
+ section = 'files.associations',
+ },
+ {
+ scopeUri = uri,
+ section = 'files.exclude',
+ }
+ },
+ }, function (configs)
+ lsp:onUpdateConfig(configs[1], {
+ associations = configs[2],
+ exclude = configs[3],
+ })
+ end)
+ end
+end
diff --git a/script/method/workspace/executeCommand.lua b/script/method/workspace/executeCommand.lua
index cfa4023e..d5abb453 100644
--- a/script/method/workspace/executeCommand.lua
+++ b/script/method/workspace/executeCommand.lua
@@ -37,6 +37,8 @@ local function posToRange(lines, start, finish)
}
end
+--- @param lsp LSP
+--- @param data table
function command.config(lsp, data)
local def = config.config
for _, k in ipairs(data.key) do
@@ -53,8 +55,12 @@ function command.config(lsp, data)
local vscodePath
local mode
- if lsp.workspace then
- vscodePath = lsp.workspace.root / '.vscode'
+ local ws
+ if data.uri then
+ ws = lsp:findWorkspaceFor(data.uri)
+ end
+ if ws then
+ vscodePath = ws.root / '.vscode'
mode = 'workspace'
else
if platform.OS == 'Windows' then
@@ -115,6 +121,8 @@ function command.config(lsp, data)
end
end
+--- @param lsp LSP
+--- @param data table
function command.removeSpace(lsp, data)
local uri = data.uri
local vm, lines = lsp:getVM(uri)
@@ -178,6 +186,8 @@ local literalMap = {
['table'] = true,
}
+--- @param lsp LSP
+--- @param data table
function command.solve(lsp, data)
local uri = data.uri
local vm, lines = lsp:getVM(uri)
@@ -248,6 +258,8 @@ function command.solve(lsp, data)
})
end
+--- @param lsp LSP
+--- @param params table
return function (lsp, params)
local name = params.command
if not command[name] then
diff --git a/script/service.lua b/script/service.lua
index 21e8939c..0114f19a 100644
--- a/script/service.lua
+++ b/script/service.lua
@@ -21,6 +21,7 @@ local files = require 'files'
local uric = require 'uri'
local capability = require 'capability'
local plugin = require 'plugin'
+local workspace = require 'workspace'
local ErrorCodes = {
-- Defined by JSON RPC
@@ -174,34 +175,83 @@ function mt:isDeadText(uri)
return self._files:isDead(uri)
end
+---@param name string
+---@param uri uri
+function mt:addWorkspace(name, uri)
+ log.info("Add workspace", name, uri)
+ for _, ws in ipairs(self.workspaces) do
+ if ws.name == name and ws.uri == uri then
+ return
+ end
+ end
+ local ws = workspace(self, name)
+ ws:init(uri)
+ table.insert(self.workspaces, ws)
+ return ws
+end
+
+---@param name string
+---@param uri uri
+function mt:removeWorkspace(name, uri)
+ log.info("Remove workspace", name, uri)
+ local index
+ for i, ws in ipairs(self.workspaces) do
+ if ws.name == name and ws.uri == uri then
+ index = i
+ break
+ end
+ end
+ if index then
+ table.remove(self.workspaces, index)
+ end
+end
+
+---@param uri uri
+---@return Workspace
+function mt:findWorkspaceFor(uri)
+ local path = uric.decode(uri)
+ if not path then
+ return nil
+ end
+ for _, ws in ipairs(self.workspaces) do
+ if not ws:relativePathByUri(uri):string():match("^%.%.") then
+ return ws
+ end
+ end
+ log.info("No workspace for", uri)
+ return nil
+end
+
---@param uri uri
---@return boolean
function mt:isLua(uri)
- if not self.workspace then
- return true
+ local ws = self:findWorkspaceFor(uri)
+ if not ws then
+ return false
end
- local path = self.workspace:absolutePathByUri(uri)
+ local path = ws:absolutePathByUri(uri)
if not path then
return false
end
- if self.workspace:isLuaFile(path) then
+ if ws:isLuaFile(path) then
return true
end
return false
end
function mt:isIgnored(uri)
- if not self.workspace then
+ local ws = self:findWorkspaceFor(uri)
+ if not ws then
return true
end
- if not self.workspace.gitignore then
+ if not ws.gitignore then
return true
end
- local path = self.workspace:relativePathByUri(uri)
+ local path = ws:relativePathByUri(uri)
if not path then
return true
end
- if self.workspace.gitignore(path:string()) then
+ if ws.gitignore(path:string()) then
return true
end
return false
@@ -261,11 +311,16 @@ function mt:checkReadFile(uri, path, text)
return true
end
+---@param ws Workspace
---@param uri uri
---@param path path
---@param buf string
---@param compiled table
-function mt:readText(uri, path, buf, compiled)
+function mt:readText(ws, uri, path, buf, compiled)
+ if self:findWorkspaceFor(uri) ~= ws then
+ log.debug('Read failed due to different workspace:', uri, debug.traceback())
+ return
+ end
if self._files:get(uri) then
log.debug('Read failed due to duplicate:', uri)
return
@@ -287,18 +342,22 @@ function mt:readText(uri, path, buf, compiled)
self:needCompile(uri, compiled)
end
+---@param ws Workspace
---@param uri uri
---@param path path
---@param buf string
---@param compiled table
-function mt:readLibrary(uri, path, buf, compiled)
+function mt:readLibrary(ws, uri, path, buf, compiled)
+ if self:findWorkspaceFor(uri) ~= ws then
+ return
+ end
if not self:isLua(uri) then
return
end
if not self:checkReadFile(uri, path, buf) then
return
end
- self._files:save(uri, buf, 0)
+ self._files:save(uri, buf, 0, ws)
self._files:setLibrary(uri)
self:needCompile(uri, compiled)
self:clearDiagnostics(uri)
@@ -663,8 +722,10 @@ function mt:checkWorkSpaceComplete()
return
end
self._hasCheckedWorkSpaceComplete = true
- if self.workspace:isComplete() then
- return
+ for _, ws in ipairs(self.workspaces) do
+ if ws:isComplete() then
+ return
+ end
end
self._needShowComplete = true
rpc:notify('window/showMessage', {
@@ -747,12 +808,11 @@ function mt:restartDueToMemoryLeak()
end
function mt:reScanFiles()
- if not self.workspace then
- return
- end
log.debug('reScanFiles')
self:clearAllFiles()
- self.workspace:scanFiles()
+ for _, ws in ipairs(self.workspaces) do
+ ws:scanFiles()
+ end
end
function mt:onUpdateConfig(updated, other)
@@ -781,7 +841,9 @@ function mt:onUpdateConfig(updated, other)
capability.semantic.disable()
end
if not table.equal(oldConfig.plugin, newConfig.plugin) then
- plugin.load(self.workspace)
+ for _, ws in ipairs(self.workspaces) do
+ plugin.load(ws)
+ end
end
if not table.equal(oldConfig.workspace, newConfig.workspace)
or not table.equal(oldConfig.plugin, newConfig.plugin)
@@ -1015,6 +1077,7 @@ function mt:listen()
end
end
+--- @return LSP
return function ()
local session = setmetatable({
_needCompile = {},
@@ -1026,5 +1089,7 @@ return function ()
session.global = core.global(session)
session.chain = chainMgr()
session.emmy = emmyMgr()
+ ---@type Workspace[]
+ session.workspaces = {}
return session
end
diff --git a/script/vm/vm.lua b/script/vm/vm.lua
index 36ad78c9..d0caa8a9 100644
--- a/script/vm/vm.lua
+++ b/script/vm/vm.lua
@@ -168,7 +168,11 @@ function mt:callSetMetaTable(func, values, source)
end
function mt:tryRequireOne(str, strValue, mode)
- if not self.lsp or not self.lsp.workspace then
+ if not self.lsp then
+ return nil
+ end
+ local ws = self.lsp:findWorkspaceFor(self:getUri())
+ if not ws then
return nil
end
local strSource = strValue:getSource()
@@ -180,11 +184,11 @@ function mt:tryRequireOne(str, strValue, mode)
self:instantSource(strSource)
local uri
if mode == 'require' then
- uri = self.lsp.workspace:searchPath(self:getUri(), str)
+ uri = ws:searchPath(self:getUri(), str)
elseif mode == 'loadfile' then
- uri = self.lsp.workspace:loadPath(self:getUri(), str)
+ uri = ws:loadPath(self:getUri(), str)
elseif mode == 'dofile' then
- uri = self.lsp.workspace:loadPath(self:getUri(), str)
+ uri = ws:loadPath(self:getUri(), str)
end
if not uri then
return nil
diff --git a/script/workspace.lua b/script/workspace.lua
index f9b243ad..8d869d9a 100644
--- a/script/workspace.lua
+++ b/script/workspace.lua
@@ -42,6 +42,7 @@ local function similarity(a, b)
return #ta
end
+--- @class Workspace
local mt = {}
mt.__index = mt
@@ -60,9 +61,9 @@ function mt:listenLoadFile()
local uri = uric.encode(path)
self.files[name] = uri
if mode == 'workspace' then
- self.lsp:readText(uri, path, buf, self._currentScanCompiled)
+ self.lsp:readText(self, uri, path, buf, self._currentScanCompiled)
elseif mode == 'library' then
- self.lsp:readLibrary(uri, path, buf, self._currentScanCompiled)
+ self.lsp:readLibrary(self, uri, path, buf, self._currentScanCompiled)
else
error('Unknown mode:' .. tostring(mode))
end
@@ -221,7 +222,7 @@ function mt:addFile(path)
local name = getFileName(path)
local uri = uric.encode(path)
self.files[name] = uri
- self.lsp:readText(uri, path)
+ self.lsp:readText(self, uri, path)
end
function mt:removeFile(path)
@@ -368,6 +369,8 @@ function mt:convertPathAsRequire(filename, start)
return list
end
+--- @param baseUri uri
+--- @param input string
function mt:matchPath(baseUri, input)
local first = input:match '^[^%.]+'
if not first then
@@ -502,6 +505,9 @@ function mt:absolutePathByUri(uri)
return fs.absolute(path)
end
+--- @param lsp LSP
+--- @param name string
+--- @return Workspace
return function (lsp, name)
local workspace = setmetatable({
lsp = lsp,
diff --git a/test/crossfile/completion.lua b/test/crossfile/completion.lua
index ab017716..14744430 100644
--- a/test/crossfile/completion.lua
+++ b/test/crossfile/completion.lua
@@ -64,9 +64,7 @@ end
function TEST(data)
local lsp = service()
- local ws = workspace(lsp, 'test')
- lsp.workspace = ws
- ws.root = ROOT
+ local ws = lsp:addWorkspace('test', uric.encode(ROOT))
local mainUri
local mainBuf
diff --git a/test/crossfile/definition.lua b/test/crossfile/definition.lua
index 02209609..c59e5999 100644
--- a/test/crossfile/definition.lua
+++ b/test/crossfile/definition.lua
@@ -44,8 +44,7 @@ end
function TEST(datas)
local lsp = service()
- local ws = workspace(lsp, 'test')
- lsp.workspace = ws
+ local ws = lsp:addWorkspace('test', uric.encode(ROOT))
local compiled = {}
local targetList = {}
diff --git a/test/crossfile/document_symbol.lua b/test/crossfile/document_symbol.lua
index 23bd6af3..50a7ff9e 100644
--- a/test/crossfile/document_symbol.lua
+++ b/test/crossfile/document_symbol.lua
@@ -65,8 +65,7 @@ rawset(_G, 'TEST', true)
function TEST(data)
local lsp = service()
- local ws = workspace(lsp, 'test')
- lsp.workspace = ws
+ local ws = lsp:addWorkspace('test', uric.encode(ROOT))
local targetUri = uric.encode(ROOT / fs.path(data[1].path))
local sourceUri = uric.encode(ROOT / fs.path(data[2].path))
diff --git a/test/crossfile/hover.lua b/test/crossfile/hover.lua
index f2560673..1472f1b6 100644
--- a/test/crossfile/hover.lua
+++ b/test/crossfile/hover.lua
@@ -56,9 +56,7 @@ end
function TEST(data)
local lsp = service()
- local ws = workspace(lsp, 'test')
- lsp.workspace = ws
- ws.root = ROOT
+ local ws = lsp:addWorkspace('test', uric.encode(ROOT))
local targetScript = data[1].content
local targetUri = uric.encode(ROOT / fs.path(data[1].path))
diff --git a/test/crossfile/references.lua b/test/crossfile/references.lua
index 87577770..0c594354 100644
--- a/test/crossfile/references.lua
+++ b/test/crossfile/references.lua
@@ -72,9 +72,7 @@ end
function TEST(data)
local lsp = service()
- local ws = workspace(lsp, 'test')
- lsp.workspace = ws
- ws.root = ROOT
+ local ws = lsp:addWorkspace('test', uric.encode(ROOT))
local mainUri
local pos