summaryrefslogtreecommitdiff
path: root/server-beta
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2019-09-21 17:13:10 +0800
committer最萌小汐 <sumneko@hotmail.com>2019-09-21 17:14:21 +0800
commit6e0641e480cc80afea6016a75ebb6c757c411867 (patch)
tree9705d618a8c44a35a2ac5035bc6f7dfa67093106 /server-beta
parent9ce1899a64c0fbb285e5e0183f5107ede08d89d1 (diff)
downloadlua-language-server-6e0641e480cc80afea6016a75ebb6c757c411867.zip
获取文件语法树
Diffstat (limited to 'server-beta')
-rw-r--r--server-beta/src/files.lua66
-rw-r--r--server-beta/src/proto/init.lua4
-rw-r--r--server-beta/src/pub/pub.lua109
3 files changed, 150 insertions, 29 deletions
diff --git a/server-beta/src/files.lua b/server-beta/src/files.lua
index eaf92ba6..6cd59799 100644
--- a/server-beta/src/files.lua
+++ b/server-beta/src/files.lua
@@ -1,10 +1,11 @@
local platform = require 'bee.platform'
+local pub = require 'pub'
+local task = require 'task'
local m = {}
m.openMap = {}
-m.textMap = {}
-m.astMap = {}
+m.fileMap = {}
--- 打开文件
function m.open(uri)
@@ -27,15 +28,68 @@ function m.setText(uri, text)
if platform.OS == 'Windows' then
uri = uri:lower()
end
- m.textMap[uri] = text
+ if not m.fileMap[uri] then
+ m.fileMap[uri] = {}
+ end
+ local file = m.fileMap[uri]
+ file.text = text
+ if file.compiling then
+ pub.removeTask(file.compiling)
+ end
+ file.compiling = pub.asyncTask('compile', text, function (ast)
+ file.ast = ast
+ file.compiling = nil
+ local onCompiledList = file.onCompiledList
+ if onCompiledList then
+ file.onCompiledList = nil
+ for _, callback in ipairs(onCompiledList) do
+ callback()
+ end
+ end
+ end)
+end
+
+--- 监听编译完成
+function m.onCompiled(uri, callback)
+ if platform.OS == 'Windows' then
+ uri = uri:lower()
+ end
+ local file = m.fileMap[uri]
+ if not file then
+ return
+ end
+ if not file.onCompiledList then
+ file.onCompiledList = {}
+ end
+ file.onCompiledList[#file.onCompiledList+1] = callback
+end
+
+--- 获取文件文本
+function m.getText(uri)
+ if platform.OS == 'Windows' then
+ uri = uri:lower()
+ end
+ local file = m.fileMap[uri]
+ if not file then
+ return nil
+ end
+ return file.text
end
---- 设置文件语法树
-function m.setAst(uri, ast)
+--- 获取文件语法树(同步)
+function m.getAst(uri)
if platform.OS == 'Windows' then
uri = uri:lower()
end
- m.astMap[uri] = ast
+ local file = m.fileMap[uri]
+ if not file.compiling then
+ return file.ast
+ end
+ pub.jumpQueue(file.compiling)
+ task.wait(function (waker)
+ m.onCompiled(file, waker)
+ end)
+ return file.ast
end
return m
diff --git a/server-beta/src/proto/init.lua b/server-beta/src/proto/init.lua
index 26fd5df8..56cb4930 100644
--- a/server-beta/src/proto/init.lua
+++ b/server-beta/src/proto/init.lua
@@ -41,8 +41,6 @@ proto.on('textDocument/didOpen', function (params)
local text = doc.text
files.open(uri)
files.setText(uri, text)
- local ast = pub.task('compile', text)
- files.setAst(uri, ast)
end)
proto.on('textDocument/didClose', function (params)
@@ -57,8 +55,6 @@ proto.on('textDocument/didChange', function (params)
local uri = doc.uri
local text = change[1].text
files.setText(uri, text)
- local ast = pub.task('compile', text)
- files.setAst(uri, ast)
end)
return proto
diff --git a/server-beta/src/pub/pub.lua b/server-beta/src/pub/pub.lua
index 692d7837..68c25ba7 100644
--- a/server-beta/src/pub/pub.lua
+++ b/server-beta/src/pub/pub.lua
@@ -4,6 +4,7 @@ local task = require 'task'
local errLog = thread.channel 'errlog'
local type = type
+local counter = utility.counter()
local braveTemplate = [[
package.path = %q
@@ -21,7 +22,7 @@ local m = {}
m.type = 'pub'
m.braves = {}
m.ability = {}
-m.taskList = {}
+m.taskQueue = {}
--- 注册酒馆的功能
function m.on(name, callback)
@@ -46,7 +47,6 @@ function m.recruitBraves(num)
id
)),
taskList = {},
- counter = utility.counter(),
currentTask = nil,
memory = 0,
}
@@ -55,28 +55,43 @@ end
--- 勇者是否有空
function m.isIdle(brave)
- return next(brave.taskList) == nil
+ return next(brave.taskMap) == nil
end
--- 给勇者推送任务
-function m.pushTask(brave, name, params)
- local taskID = brave.counter()
- brave.taskpad:push(name, taskID, params)
+function m.pushTask(brave, info)
+ if info.removed then
+ return
+ end
+ brave.taskpad:push(info.name, info.id, info.params)
return task.wait(function (waker)
- brave.taskList[taskID] = waker
+ info.callback = waker
+ brave.taskMap[info.id] = info
end)
end
+--- 给勇者推送任务(异步)
+function m.pushAsyncTask(brave, info)
+ if info.removed then
+ return
+ end
+ brave.taskpad:push(info.name, info.id, info.params)
+ brave.taskMap[info.id] = info
+end
+
--- 从勇者处接收任务反馈
function m.popTask(brave, id, result)
- local waker = brave.taskList[id]
- if not waker then
+ local info = brave.taskMap[id]
+ if not info then
log.warn(('Brave pushed unknown task result: # %d => [%d]'):format(brave.id, id))
return
end
- brave.taskList[id] = nil
+ brave.taskMap[id] = nil
m.checkWaitingTask(brave)
- waker(result)
+ if not info.removed then
+ info.removed = true
+ info.callback(result)
+ end
end
--- 从勇者处接收报告
@@ -89,33 +104,89 @@ function m.popReport(brave, name, params)
abil(params, brave)
end
---- 发布任务
+--- 发布任务(同步)
---@parma name string
+---@param params any
function m.task(name, params)
+ local info = {
+ id = counter(),
+ name = name,
+ params = params,
+ }
for _, brave in ipairs(m.braves) do
if m.isIdle(brave) then
- return m.pushTask(brave, name, params)
+ return m.pushTask(brave, info)
end
end
-- 如果所有勇者都在战斗,那么把任务缓存到队列里
-- 当有勇者提交任务反馈后,尝试把按顺序将堆积任务
-- 交给该勇者
- m.taskList[#m.taskList+1] = function (brave)
- return m.pushTask(brave, name, params)
+ m.taskQueue[#m.taskQueue+1] = info
+end
+
+--- 发布异步任务,如果任务进入了队列,会返回执行器
+---|通过 jumpQueue 可以插队
+---@parma name string
+---@param params any
+---@param callback function
+function m.asyncTask(name, params, callback)
+ local info = {
+ id = counter(),
+ name = name,
+ params = params,
+ callback = callback or function () end,
+ }
+ for _, brave in ipairs(m.braves) do
+ if m.isIdle(brave) then
+ m.pushAsyncTask(brave, info)
+ return nil
+ end
+ end
+ -- 如果所有勇者都在战斗,那么把任务缓存到队列里
+ -- 当有勇者提交任务反馈后,尝试把按顺序将堆积任务
+ -- 交给该勇者
+ m.taskQueue[#m.taskQueue+1] = info
+ return info
+end
+
+--- 插队
+function m.jumpQueue(info)
+ for i = 2, #m.taskQueue do
+ if m.taskQueue[i] == info then
+ m.taskQueue[i] = nil
+ table.move(m.taskQueue, 1, i - 1, 2)
+ m.taskQueue[1] = info
+ return
+ end
+ end
+end
+
+--- 移除任务
+function m.remove(info)
+ info.removed = true
+ for i = 1, #m.taskQueue do
+ if m.taskQueue[i] == info then
+ table.remove(m.taskQueue[i], i)
+ return
+ end
end
end
--- 检查堆积任务
function m.checkWaitingTask(brave)
- if #m.taskList == 0 then
+ if #m.taskQueue == 0 then
return
end
-- 如果勇者还有其他活要忙,那么让他继续忙去吧
- if next(brave.taskList) then
+ if next(brave.taskMap) then
return
end
- local waiting = table.remove(m.taskList, 1)
- waiting(brave)
+ local info = table.remove(m.taskQueue, 1)
+ if info.callback then
+ m.pushAsyncTask(brave, info)
+ else
+ m.pushTask(brave, info)
+ end
end
--- 接收反馈