diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/debugger.lua | 1 | ||||
-rw-r--r-- | server/main.lua | 2 | ||||
-rw-r--r-- | server/src/config.lua | 2 | ||||
-rw-r--r-- | server/src/plugin.lua | 80 | ||||
-rw-r--r-- | server/src/rpc.lua | 6 | ||||
-rw-r--r-- | server/src/sandbox.lua | 76 | ||||
-rw-r--r-- | server/src/service.lua | 5 |
7 files changed, 132 insertions, 40 deletions
diff --git a/server/debugger.lua b/server/debugger.lua index 5315953a..79b2931d 100644 --- a/server/debugger.lua +++ b/server/debugger.lua @@ -44,6 +44,7 @@ local function tryDebugger() local addr = "127.0.0.1:" .. port local dbg = loadfile(entry)('windows', root) dbg:start(addr) + dbg:wait() log.debug('Debugger startup, listen port:', port) log.debug('Debugger args:', addr, root, path, cpath) end diff --git a/server/main.lua b/server/main.lua index 00a3b0fd..99143461 100644 --- a/server/main.lua +++ b/server/main.lua @@ -15,7 +15,7 @@ log.info('Lua Lsp startup, root: ', ROOT) log.debug('ROOT:', ROOT:string()) ac = {} ---xpcall(dofile, log.debug, rootPath .. 'debugger.lua') +xpcall(dofile, log.debug, rootPath .. '/debugger.lua') require 'utility' local service = require 'service' local session = service() diff --git a/server/src/config.lua b/server/src/config.lua index 774af499..7fb7970e 100644 --- a/server/src/config.lua +++ b/server/src/config.lua @@ -125,7 +125,7 @@ local ConfigTemplate = { }, plugin = { enable = {false, Boolean}, - path = {'${workspaceRoot}/.vscode/lua/', String}, + path = {'.vscode/lua-plugin/*.lua', String}, }, } diff --git a/server/src/plugin.lua b/server/src/plugin.lua new file mode 100644 index 00000000..303c2dda --- /dev/null +++ b/server/src/plugin.lua @@ -0,0 +1,80 @@ +local fs = require 'bee.filesystem' +local rpc = require 'rpc' +local config = require 'config' +local glob = require 'glob' +local platform = require 'bee.platform' +local sandbox = require 'sandbox' + +local Plugins + +local function showError(msg) + local traceback = log.error(msg) + rpc:notify('window/showMessage', { + type = 3, + message = traceback, + }) + return traceback +end + +local function showWarn(msg) + log.warn(msg) + rpc:notify('window/showMessage', { + type = 3, + message = msg, + }) + return msg +end + +local function scan(path, callback) + if fs.is_directory(path) then + for p in path:list_directory() do + scan(p, callback) + end + else + callback(path) + end +end + +local function loadPluginFrom(path, root) + log.info('Load plugin from:', path:string()) + local env = setmetatable({}, { __index = _G }) + sandbox(path:filename():string(), root:string(), io.open, package.loaded, env) + Plugins[#Plugins+1] = env +end + +local function load(workspace) + Plugins = {} + if not config.config.plugin.enable then + return + end + local suc, path = xpcall(fs.path, showWarn, config.config.plugin.path) + if not suc then + return + end + + local pluginPath + if workspace then + pluginPath = fs.absolute(workspace.root / path) + else + pluginPath = fs.absolute(path) + end + if not fs.is_directory(pluginPath) then + pluginPath = pluginPath:parent_path() + end + + local pattern = {config.config.plugin.path} + local options = { + ignoreCase = platform.OS == 'Windows' + } + local parser = glob.glob(pattern, options) + + scan(pluginPath:parent_path(), function (filePath) + if parser(filePath:string()) then + loadPluginFrom(filePath, pluginPath) + end + end) +end + +return { + load = load, +} diff --git a/server/src/rpc.lua b/server/src/rpc.lua index 91b30bf5..2456cbd3 100644 --- a/server/src/rpc.lua +++ b/server/src/rpc.lua @@ -67,8 +67,10 @@ local function recieve(self, proto) BUF[id] = nil if data.timeout and os.clock() > data.timeout then log.warn('Recieve timeout: ', table.dump(proto)) - local info = debug.getinfo(data.callback, 'S') - log.warn('Call back info: ', info.source, info.linedefined) + if data.callback then + local info = debug.getinfo(data.callback, 'S') + log.warn('Call back info: ', info.source, info.linedefined) + end return end if proto.error then diff --git a/server/src/sandbox.lua b/server/src/sandbox.lua index c09230fd..6b2f2a32 100644 --- a/server/src/sandbox.lua +++ b/server/src/sandbox.lua @@ -1,5 +1,5 @@ -local function standard(loaded) - local r = {} +local function standard(loaded, env) + local r = env or {} for _, s in ipairs { --'package', 'coroutine', @@ -45,9 +45,9 @@ local function standard(loaded) return r end -local function sandbox_env(loadlua, openfile, loaded) +local function sandbox_env(loadlua, openfile, loaded, env) local _LOADED = loaded or {} - local _E = standard(_LOADED) + local _E = standard(_LOADED, env) local _PRELOAD = {} _E.io = { @@ -56,14 +56,14 @@ local function sandbox_env(loadlua, openfile, loaded) local function searchpath(name, path) local err = '' - name = string.gsub(name, '%.', '/') - for c in string.gmatch(path, '[^;]+') do + name = string.gsub(name, '%.', '/') + for c in string.gmatch(path, '[^;]+') do local filename = string.gsub(c, '%?', name) local f = openfile(filename) if f then f:close() - return filename - end + return filename + end err = err .. ("\n\tno file '%s'"):format(filename) end return nil, err @@ -76,25 +76,25 @@ local function sandbox_env(loadlua, openfile, loaded) end return _PRELOAD[name] end - + local function searcher_lua(name) assert(type(_E.package.path) == "string", "'package.path' must be a string") - local filename, err = searchpath(name, _E.package.path) - if not filename then - return err - end - local f, err = loadlua(filename) - if not f then - error(("error loading module '%s' from file '%s':\n\t%s"):format(name, filename, err)) - end - return f, filename + local filename, err = searchpath(name, _E.package.path) + if not filename then + return err + end + local f, err = loadlua(filename) + if not f then + error(("error loading module '%s' from file '%s':\n\t%s"):format(name, filename, err)) + end + return f, filename end local function require_load(name) local msg = '' local _SEARCHERS = _E.package.searchers assert(type(_SEARCHERS) == "table", "'package.searchers' must be a table") - for _, searcher in ipairs(_SEARCHERS) do + for _, searcher in ipairs(_SEARCHERS) do local f, extra = searcher(name) if type(f) == 'function' then return f, extra @@ -107,20 +107,22 @@ local function sandbox_env(loadlua, openfile, loaded) _E.require = function(name) assert(type(name) == "string", ("bad argument #1 to 'require' (string expected, got %s)"):format(type(name))) - local p = _LOADED[name] - if p ~= nil then - return p - end - local init, extra = require_load(name) - debug.setupvalue(init, 1, _E) - local res = init(name, extra) - if res ~= nil then - _LOADED[name] = res - end - if _LOADED[name] == nil then - _LOADED[name] = true - end - return _LOADED[name] + local p = _LOADED[name] + if p ~= nil then + return p + end + local init, extra = require_load(name) + if debug.getupvalue(init, 1) == '_ENV' then + debug.setupvalue(init, 1, _E) + end + local res = init(name, extra) + if res ~= nil then + _LOADED[name] = res + end + if _LOADED[name] == nil then + _LOADED[name] = true + end + return _LOADED[name] end _E.package = { config = [[ @@ -139,7 +141,7 @@ local function sandbox_env(loadlua, openfile, loaded) return _E end -return function(name, root, io_open, loaded) +return function(name, root, io_open, loaded, env) if not root:sub(-1):find '[/\\]' then root = root .. '/' end @@ -158,6 +160,8 @@ return function(name, root, io_open, loaded) if not init then return end - debug.setupvalue(init, 1, sandbox_env(loadlua, openfile, loaded)) - return init() + if debug.getupvalue(init, 1) == '_ENV' then + debug.setupvalue(init, 1, sandbox_env(loadlua, openfile, loaded, env)) + end + return init() end diff --git a/server/src/service.lua b/server/src/service.lua index fd814ff3..0b668b6d 100644 --- a/server/src/service.lua +++ b/server/src/service.lua @@ -20,6 +20,7 @@ local task = require 'task' local files = require 'files' local uric = require 'uri' local capability = require 'capability' +local plugin = require 'plugin' local ErrorCodes = { -- Defined by JSON RPC @@ -763,7 +764,11 @@ function mt:onUpdateConfig(updated, other) else capability.completion.disable() end + if not table.equal(oldConfig.plugin, newConfig.plugin) then + plugin.load(self.workspace) + end if not table.equal(oldConfig.workspace, newConfig.workspace) + or not table.equal(oldConfig.plugin, newConfig.plugin) or not table.equal(oldOther.associations, newOther.associations) or not table.equal(oldOther.exclude, newOther.exclude) then |