diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2019-09-21 17:13:10 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2019-09-21 17:14:21 +0800 |
commit | 6e0641e480cc80afea6016a75ebb6c757c411867 (patch) | |
tree | 9705d618a8c44a35a2ac5035bc6f7dfa67093106 /server-beta | |
parent | 9ce1899a64c0fbb285e5e0183f5107ede08d89d1 (diff) | |
download | lua-language-server-6e0641e480cc80afea6016a75ebb6c757c411867.zip |
获取文件语法树
Diffstat (limited to 'server-beta')
-rw-r--r-- | server-beta/src/files.lua | 66 | ||||
-rw-r--r-- | server-beta/src/proto/init.lua | 4 | ||||
-rw-r--r-- | server-beta/src/pub/pub.lua | 109 |
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 --- 接收反馈 |