diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2018-12-20 11:02:48 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2018-12-20 11:02:48 +0800 |
commit | e9ec6c5d7812fb29cda834b2726ad972bd3f0d49 (patch) | |
tree | e42578e8a4adbb5cb23b2137224a0e785cf097ff /server | |
parent | 26c9ee2de021c6a08d1472f187ada881c46d9cc3 (diff) | |
download | lua-language-server-e9ec6c5d7812fb29cda834b2726ad972bd3f0d49.zip |
工作目录与文件变化
Diffstat (limited to 'server')
-rw-r--r-- | server/src/method/init.lua | 2 | ||||
-rw-r--r-- | server/src/method/initialized.lua | 13 | ||||
-rw-r--r-- | server/src/method/workspace/didChangeWatchedFiles.lua | 21 | ||||
-rw-r--r-- | server/src/method/workspace/didChangeWorkspaceFolders.lua | 16 | ||||
-rw-r--r-- | server/src/rpc.lua | 27 | ||||
-rw-r--r-- | server/src/service.lua | 7 | ||||
-rw-r--r-- | server/src/workspace.lua | 78 |
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 |