summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2018-12-20 11:02:48 +0800
committer最萌小汐 <sumneko@hotmail.com>2018-12-20 11:02:48 +0800
commite9ec6c5d7812fb29cda834b2726ad972bd3f0d49 (patch)
treee42578e8a4adbb5cb23b2137224a0e785cf097ff /server
parent26c9ee2de021c6a08d1472f187ada881c46d9cc3 (diff)
downloadlua-language-server-e9ec6c5d7812fb29cda834b2726ad972bd3f0d49.zip
工作目录与文件变化
Diffstat (limited to 'server')
-rw-r--r--server/src/method/init.lua2
-rw-r--r--server/src/method/initialized.lua13
-rw-r--r--server/src/method/workspace/didChangeWatchedFiles.lua21
-rw-r--r--server/src/method/workspace/didChangeWorkspaceFolders.lua16
-rw-r--r--server/src/rpc.lua27
-rw-r--r--server/src/service.lua7
-rw-r--r--server/src/workspace.lua78
7 files changed, 153 insertions, 11 deletions
diff --git a/server/src/method/init.lua b/server/src/method/init.lua
index 2aaa2b24..22c58289 100644
--- a/server/src/method/init.lua
+++ b/server/src/method/init.lua
@@ -18,5 +18,7 @@ init 'textDocument/implementation'
init 'textDocument/publishDiagnostics'
init 'textDocument/rename'
init 'textDocument/references'
+init 'workspace/didChangeWatchedFiles'
+init 'workspace/didChangeWorkspaceFolders'
return method
diff --git a/server/src/method/initialized.lua b/server/src/method/initialized.lua
index a7e70d66..cb2e6c65 100644
--- a/server/src/method/initialized.lua
+++ b/server/src/method/initialized.lua
@@ -2,11 +2,18 @@ local rpc = require 'rpc'
local workspace = require 'workspace'
return function (lsp)
- lsp.workspace = workspace()
+ rpc:request('workspace/workspaceFolders', nil, function (folders)
+ if folders then
+ local folder = folders[1]
+ if folder then
+ lsp.workspace = workspace(folder.name, folder.uri)
+ end
+ end
+ end)
-- 必须动态注册的事件:
rpc:request('client/registerCapability', {
registrations = {
- -- 监事文件变化
+ -- 监视文件变化
{
id = '0',
method = 'workspace/didChangeWatchedFiles',
@@ -14,7 +21,7 @@ return function (lsp)
watchers = {
{
globPattern = '**/*.lua',
- kind = 1 | 2 | 4, -- Create | Delete
+ kind = 1 | 2 | 4, -- Create | Change | Delete
},
},
},
diff --git a/server/src/method/workspace/didChangeWatchedFiles.lua b/server/src/method/workspace/didChangeWatchedFiles.lua
new file mode 100644
index 00000000..3e1808a8
--- /dev/null
+++ b/server/src/method/workspace/didChangeWatchedFiles.lua
@@ -0,0 +1,21 @@
+local FileChangeType = {
+ Created = 1,
+ Changed = 2,
+ Deleted = 3,
+}
+
+return function (lsp, params)
+ if not lsp.workspace then
+ return
+ end
+ for _, change in ipairs(params.changes) do
+ if change.type == FileChangeType.Created then
+ lsp.workspace:addFile(change.uri)
+ elseif change.type == FileChangeType.Deleted then
+ lsp.workspace:removeFile(change.uri)
+ -- 删除文件后,清除该文件的诊断
+ lsp:clearDiagnostics(change.uri)
+ end
+ end
+ -- 发生任何文件变化后,重新计算当前的打开文件
+end
diff --git a/server/src/method/workspace/didChangeWorkspaceFolders.lua b/server/src/method/workspace/didChangeWorkspaceFolders.lua
new file mode 100644
index 00000000..12fe915d
--- /dev/null
+++ b/server/src/method/workspace/didChangeWorkspaceFolders.lua
@@ -0,0 +1,16 @@
+local rpc = require 'rpc'
+
+return function ()
+ -- 暂不支持多个工作目录,因此当工作目录切换时,暴力结束服务,让前端重启服务
+ rpc:requestWait('window/showMessageRequest', {
+ type = 3,
+ message = '[Lua] dose not support multi workspace now, I may need to restart to support the new workspace ...',
+ actions = {
+ {
+ title = 'Restart'
+ }
+ }
+ }, function ()
+ os.exit(true)
+ end)
+end
diff --git a/server/src/rpc.lua b/server/src/rpc.lua
index 99136a0a..ad98e7d5 100644
--- a/server/src/rpc.lua
+++ b/server/src/rpc.lua
@@ -33,6 +33,22 @@ local function request(self, method, params, callback)
io.write(buf)
end
+local function requestWait(self, method, params, callback)
+ ID = ID + 1
+ local pack = {
+ jsonrpc = '2.0',
+ id = ID,
+ method = method,
+ params = params,
+ }
+ local content = json.encode(pack)
+ local buf = ('Content-Length: %d\r\n\r\n%s'):format(#content, content)
+ BUF[ID] = {
+ callback = callback,
+ }
+ io.write(buf)
+end
+
local function response(self, id, data)
data.jsonrpc = '2.0'
data.id = id
@@ -49,7 +65,7 @@ local function recieve(self, proto)
return
end
BUF[id] = nil
- if os.clock() > data.timeout then
+ if data.timeout and os.clock() > data.timeout then
log.warn('Recieve timeout: ', table.dump(proto.error))
return
end
@@ -61,8 +77,9 @@ local function recieve(self, proto)
end
return {
- notify = notify,
- request = request,
- response = response,
- recieve = recieve,
+ notify = notify,
+ request = request,
+ requestWait = requestWait,
+ response = response,
+ recieve = recieve,
}
diff --git a/server/src/service.lua b/server/src/service.lua
index f7c81317..d6a0daf0 100644
--- a/server/src/service.lua
+++ b/server/src/service.lua
@@ -113,6 +113,13 @@ function mt:_doDiagnostic()
end
end
+function mt:clearDiagnostics(uri)
+ rpc:notify('textDocument/publishDiagnostics', {
+ uri = uri,
+ diagnostics = {},
+ })
+end
+
function mt:_buildTextCache()
if not next(self._needCompile) then
return
diff --git a/server/src/workspace.lua b/server/src/workspace.lua
index f167719c..104a15c7 100644
--- a/server/src/workspace.lua
+++ b/server/src/workspace.lua
@@ -1,6 +1,78 @@
+local fs = require 'bee.filesystem'
+
+local function uriDecode(uri)
+ if uri:sub(1, 8) ~= 'file:///' then
+ log.error('uri decode failed: ', uri)
+ return nil
+ end
+ local names = {}
+ for name in uri:sub(9):gmatch '[^%/]+' do
+ names[#names+1] = name:gsub('%%([0-9a-fA-F][0-9a-fA-F])', function (hex)
+ return string.char(tonumber(hex, 16))
+ end)
+ end
+ if #names == 0 then
+ log.error('uri decode failed: ', uri)
+ return nil
+ end
+ local path = fs.path(names[1])
+ for i = 2, #names do
+ path = path / names[i]
+ end
+ return fs.absolute(path)
+end
+
+local function uriEncode(path)
+ local names = {}
+ local cur = fs.absolute(path)
+ while true do
+ local name = cur:filename():string():gsub([=[[^%w%-%_%.%~]]=], function (char)
+ return '%' .. string.byte(char)
+ end)
+ table.insert(names, 1, name)
+ if cur == cur:parent_path() then
+ break
+ end
+ cur = cur:parent_path()
+ end
+ return 'file:///' .. table.concat(names, '/')
+end
+
local mt = {}
-mt.__index = {}
+mt.__index = mt
+
+function mt:init(rootUri)
+ self.root = uriDecode(rootUri)
+ if not self.root then
+ return
+ end
+ log.info('Workspace inited, root: ', self.root)
+ local count = 0
+ for path in io.scan(self.root) do
+ if path:extension():string() == '.lua' then
+ local uri = uriEncode(path)
+ self.files[uri] = true
+ count = count + 1
+ end
+ end
+ log.info(('Found [%d] files'):format(count))
+end
+
+function mt:addFile(uri)
+ if uri:sub(-4) == '.lua' then
+ self.files[path] = true
+ end
+end
+
+function mt:removeFile(uri)
+ self.files[uri] = nil
+end
-return function ()
-
+return function (name, uri)
+ local workspace = setmetatable({
+ name = name,
+ files = {},
+ }, mt)
+ workspace:init(uri)
+ return workspace
end