summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2018-11-29 18:05:32 +0800
committer最萌小汐 <sumneko@hotmail.com>2018-11-29 18:05:32 +0800
commit550f5d0072f1e2ad112fe2b6cded8df6c92f9328 (patch)
tree87b0f285ebeeb125b6ca9aee3b8e657f54826a20
parentfd8737e3129c766752f81a69484bb073be7f72a0 (diff)
downloadlua-language-server-550f5d0072f1e2ad112fe2b6cded8df6c92f9328.zip
异步读取与建立缓存
-rw-r--r--server/src/lsp.lua77
-rw-r--r--server/src/method/textDocument/definition.lua4
-rw-r--r--server/src/service.lua27
3 files changed, 95 insertions, 13 deletions
diff --git a/server/src/lsp.lua b/server/src/lsp.lua
index 1ac2c6c0..3f804ab4 100644
--- a/server/src/lsp.lua
+++ b/server/src/lsp.lua
@@ -44,13 +44,29 @@ function mt:_send(data)
f(buf)
end
-function mt:_readAsContent(header)
+function mt:_readProtoHead()
+ local header = self:read 'l'
+ if not header then
+ return
+ end
+ if header:sub(1, #'Content-Length') == 'Content-Length' then
+ return header
+ elseif header:sub(1, #'Content-Type') == 'Content-Type' then
+ else
+ log.error('错误的协议头:', header)
+ end
+end
+
+function mt:_readProtoContent(header)
local len = tonumber(header:match('%d+'))
if not len then
log.error('错误的协议头:', header)
return
end
local buf = self:read(len+2)
+ if not buf then
+ return
+ end
local suc, res = pcall(json.decode, buf)
if not suc then
log.error('错误的协议:', buf)
@@ -79,8 +95,38 @@ function mt:_readAsContent(header)
if not response then
log.error(err or ('没有回应:' .. method))
end
- -- 运行时不清理垃圾,在回复前端之后清理垃圾
- collectgarbage()
+ return true
+end
+
+function mt:_buildTextCache()
+ if not next(self._need_compile) then
+ return
+ end
+ local list = {}
+ for uri in pairs(self._need_compile) do
+ list[#list+1] = uri
+ end
+
+ local size = 0
+ local clock = os.clock()
+ for _, uri in ipairs(list) do
+ local obj = self:compileText(uri)
+ if obj then
+ size = size + #obj.text
+ end
+ end
+ local passed = os.clock() - clock
+ log.debug(('\n\z
+ 语法树缓存完成\n\z
+ 耗时:[%.3f]秒\n\z
+ 数量:[%d]\n\z
+ 总大小:[%.3f]kb\n\z
+ 速度:[%.3f]kb/s'):format(
+ passed,
+ #list,
+ size / 1000,
+ size / passed / 1000
+ ))
end
function mt:setInput(input)
@@ -139,6 +185,7 @@ function mt:compileText(uri)
end
obj.ast = ast
obj.lines = parser:lines(obj.text)
+ return obj
end
function mt:removeText(uri)
@@ -150,15 +197,23 @@ function mt:setMethod(method)
end
function mt:runStep()
- local header = self:read 'l'
- if not header then
+ if not self._header then
+ -- 如果没有协议头,则尝试读一条协议头
+ self._header = self:_readProtoHead()
+ end
+ if self._header then
+ -- 如果有协议头,则读取协议内容
+ local suc = self:_readProtoContent(self._header)
+ if suc then
+ -- 协议内容读取成功后重置
+ self._header = nil
+ self._idle_clock = 0
+ end
return
end
- if header:sub(1, #'Content-Length') == 'Content-Length' then
- self:_readAsContent(header)
- elseif header:sub(1, #'Content-Type') == 'Content-Type' then
- else
- log.error('错误的协议头:', header)
+ self._idle_clock = self._idle_clock + 1
+ if self._idle_clock == 1000 then
+ self:_buildTextCache()
end
end
@@ -171,5 +226,7 @@ return function ()
return setmetatable({
_file = {},
_need_compile = {},
+ _header = nil,
+ _idle_clock = 0,
}, mt)
end
diff --git a/server/src/method/textDocument/definition.lua b/server/src/method/textDocument/definition.lua
index f5fb6472..0cffee4a 100644
--- a/server/src/method/textDocument/definition.lua
+++ b/server/src/method/textDocument/definition.lua
@@ -2,12 +2,12 @@ local parser = require 'parser'
local matcher = require 'matcher'
return function (lsp, params)
+ local start_clock = os.clock()
local uri = params.textDocument.uri
local ast, lines = lsp:loadText(uri)
if not ast then
return nil, '找不到文件:' .. uri
end
- local start_clock = os.clock()
-- lua是从1开始的,因此都要+1
local position = lines:position(params.position.line + 1, params.position.character + 1)
local suc, start, finish = matcher.definition(ast, position, 'utf8')
@@ -39,7 +39,7 @@ return function (lsp, params)
}
local passed_clock = os.clock() - start_clock
if passed_clock >= 0.01 then
- log.warn(('[转到定义]耗时[%.3f]秒,文件大小[%s]字节'):format(passed_clock, #text))
+ log.warn(('[转到定义]耗时[%.3f]秒,文件大小[%s]字节'):format(passed_clock, #lines.buf))
end
return response
diff --git a/server/src/service.lua b/server/src/service.lua
index 9e11d82f..0763a774 100644
--- a/server/src/service.lua
+++ b/server/src/service.lua
@@ -22,8 +22,33 @@ local function listen(self, input, output)
io.output():setvbuf 'no'
local session = lsp()
+ local cache = ''
session:setInput(function (mode)
- return io.read(mode)
+ local num = subprocess.peek(io.input())
+ if num > 0 then
+ cache = cache .. io.read(num)
+ end
+ if type(mode) == 'number' then
+ if #cache < mode then
+ return nil
+ end
+ local res = cache:sub(1, mode)
+ cache = cache:sub(mode + 1)
+ return res
+ elseif mode == 'l' then
+ local pos = cache:find '[\r\n]'
+ if not pos then
+ return nil
+ end
+ local res = cache:sub(1, pos - 1)
+ if cache:sub(pos, pos + 1) == '\r\n' then
+ cache = cache:sub(pos + 2)
+ else
+ cache = cache:sub(pos + 1)
+ end
+ return res
+ end
+ return nil
end)
session:setOutput(function (buf)
io.write(buf)