summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/debugger.lua1
-rw-r--r--server/main.lua2
-rw-r--r--server/src/config.lua2
-rw-r--r--server/src/plugin.lua80
-rw-r--r--server/src/rpc.lua6
-rw-r--r--server/src/sandbox.lua76
-rw-r--r--server/src/service.lua5
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