summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/src/async/async.lua6
-rw-r--r--server/src/async/scanfiles.lua106
-rw-r--r--server/src/core/library.lua20
-rw-r--r--server/src/log.lua2
-rw-r--r--server/src/path_filter.lua68
-rw-r--r--server/src/utility.lua42
-rw-r--r--server/src/workspace.lua32
7 files changed, 141 insertions, 135 deletions
diff --git a/server/src/async/async.lua b/server/src/async/async.lua
index 953cf5cf..b385aac8 100644
--- a/server/src/async/async.lua
+++ b/server/src/async/async.lua
@@ -72,12 +72,12 @@ end
local function callback(id, running)
if running.callback then
while true do
- local ok, result = running.task.response:pop()
- if not ok then
+ local results = table.pack(running.task.response:pop())
+ if not results[1] then
break
end
-- TODO 封装成对象
- local suc, destroy = xpcall(running.callback, log.error, result)
+ local suc, destroy = xpcall(running.callback, log.error, table.unpack(results, 2))
if not suc or destroy then
RunningList[id] = nil
IdlePool[#IdlePool+1] = running.task
diff --git a/server/src/async/scanfiles.lua b/server/src/async/scanfiles.lua
index c242dcfe..a9c266b3 100644
--- a/server/src/async/scanfiles.lua
+++ b/server/src/async/scanfiles.lua
@@ -2,92 +2,46 @@ local args = ...
require 'utility'
local fs = require 'bee.filesystem'
-local root = fs.absolute(fs.path(args.root))
-
-local function glob_compile(pattern)
- return ("^%s$"):format(pattern:gsub("[%^%$%(%)%%%.%[%]%+%-%?]", "%%%0"):gsub("%*", ".*"))
-end
-local function glob_match(pattern, target)
- return target:match(pattern) ~= nil
-end
-
-local function accept_path(t, path)
- if t[path:string()] then
- return
- end
- t[#t+1] = path:string()
- t[path:string()] = #t
-end
-local function expand_dir(t, pattern, dir)
- if not fs.exists(dir) then
- return
- end
- for file in dir:list_directory() do
- if fs.is_directory(file) then
- expand_dir(t, pattern, file)
- else
- if glob_match(pattern, file:filename():string():lower()) then
- accept_path(t, file)
- end
+local path_filter = require 'path_filter'
+
+local function scan(root, filter)
+ local len = #root
+ local result = {fs.path(root)}
+ local i = 0
+ return function ()
+ i = i + 1
+ local current = result[i]
+ if not current then
+ return nil
end
- end
-end
-local function expand_path(t, root, source)
- if source:sub(1, 1) == '/' then
- source = source:sub(2)
- end
- local path = root / source
- if source:find("*", 1, true) == nil then
- accept_path(t, path)
- return
- end
- local filename = path:filename():string():lower()
- local pattern = glob_compile(filename)
- expand_dir(t, pattern, path:parent_path())
-end
-local function get_sources(root, sources)
- local result = {}
- local ignore = {}
- for _, source in ipairs(sources) do
- if source:sub(1,1) ~= "!" then
- expand_path(result, root, source)
- else
- expand_path(ignore, root, source:sub(2))
- end
- end
- for _, path in ipairs(ignore) do
- local pos = result[path]
- if pos then
- result[pos] = result[#result]
- result[result[pos]] = pos
- result[path] = nil
- result[#result] = nil
+ if fs.is_directory(current) then
+ local name = current:string():sub(len+2):gsub('/', '\\')
+ if filter(name) then
+ OUT:push('log', '过滤目录:', current:string())
+ else
+ for path in current:list_directory() do
+ local name = path:string():sub(len+2):gsub('/', '\\')
+ if filter(name) then
+ OUT:push('log', '过滤文件:', path:string())
+ else
+ result[#result+1] = path
+ end
+ end
+ end
end
+ return current
end
- return result
end
-local function computePath()
- local ignore = { '.git' }
-
-
- for name in pairs(args.ignore) do
- ignore[#ignore+1] = name:lower()
- end
-
- return get_sources(root, ignore)
-end
-
-local ignored = computePath()
-
-for path in io.scan(root, ignored) do
+local filter = path_filter(args.ignored)
+for path in scan(args.root, filter) do
if path:extension():string() == '.lua' then
local buf = io.load(path)
if buf then
- OUT:push {
+ OUT:push('file', {
path = fs.absolute(path):string(),
buf = buf,
- }
+ })
end
end
end
diff --git a/server/src/core/library.lua b/server/src/core/library.lua
index b268b368..6bceadc4 100644
--- a/server/src/core/library.lua
+++ b/server/src/core/library.lua
@@ -144,6 +144,24 @@ local function fix(libs)
end
end
+local function scan(path)
+ local result = {path}
+ local i = 0
+ return function ()
+ i = i + 1
+ local current = result[i]
+ if not current then
+ return nil
+ end
+ if fs.is_directory(current) then
+ for path in current:list_directory() do
+ result[#result+1] = path
+ end
+ end
+ return current
+ end
+end
+
local function init()
local lang = require 'language'
local id = lang.id
@@ -152,7 +170,7 @@ local function init()
library = table.container(),
object = table.container(),
}
- for path in io.scan(ROOT / 'libs') do
+ for path in scan(ROOT / 'libs') do
local libs
local buf = io.load(path)
if buf then
diff --git a/server/src/log.lua b/server/src/log.lua
index eb34505a..c4fa9461 100644
--- a/server/src/log.lua
+++ b/server/src/log.lua
@@ -24,7 +24,7 @@ local function push_log(level, ...)
for i = 1, t.n do
t[i] = tostring(t[i])
end
- local str = table.concat(t, '\t')
+ local str = table.concat(t, '\t', 1, t.n)
if level == 'error' then
str = str .. '\n' .. debug.traceback(nil, 3)
end
diff --git a/server/src/path_filter.lua b/server/src/path_filter.lua
new file mode 100644
index 00000000..2a362677
--- /dev/null
+++ b/server/src/path_filter.lua
@@ -0,0 +1,68 @@
+local m = require 'lpeglabel'
+
+local m_cut = m.S'/\\'
+local m_path = (1-m_cut)^1
+
+local function match_any(p, pass)
+ return m.P{p + pass * m.V(1)}
+end
+
+local function compile_format(fmt)
+ local function next(cur)
+ local pos, fn = fmt:find('%*+', cur)
+ if not pos then
+ return m.P(fmt:sub(cur)) * -1
+ end
+ local word = m.P(fmt:sub(cur, pos-1))
+ return word * match_any(next(fn+1), 1)
+ end
+ return next(1)
+end
+
+local function compile_exp(exp)
+ if exp:sub(1, 1) == '/' then
+ exp = exp:sub(2)
+ else
+ exp = '**/' .. exp
+ end
+ local function next(cur)
+ local pos, fn = exp:find('[/\\]+', cur)
+ if not pos then
+ return compile_format(exp:sub(cur))
+ end
+ local fmt = exp:sub(cur, pos-1)
+ if fmt == '**' then
+ return match_any(next(fn+1), m_path * m_cut)
+ elseif fmt == '' then
+ return m_cut
+ else
+ if fn < #exp then
+ return m.P(fmt) * m_cut * next(fn+1)
+ else
+ return m.P(fmt) * m_cut
+ end
+ end
+ end
+ return next(1)
+end
+
+local function compile_exps(exp)
+ local matcher
+ for _, exp in ipairs(exp) do
+ exp = exp:lower()
+ if matcher then
+ matcher = matcher + compile_exp(exp)
+ else
+ matcher = compile_exp(exp)
+ end
+ end
+ return matcher
+end
+
+return function (exp)
+ local matcher = compile_exps(exp)
+ return function (path)
+ local filename = path:lower()
+ return not not matcher:match(filename)
+ end
+end
diff --git a/server/src/utility.lua b/server/src/utility.lua
index ee15bf38..b0d44a60 100644
--- a/server/src/utility.lua
+++ b/server/src/utility.lua
@@ -142,45 +142,3 @@ function io.save(file_path, content)
return false, e
end
end
-
-function io.scan(path, ignore)
- local result = {path}
- local i = 0
- local absolute
- if ignore then
- absolute = {}
- for _, name in ipairs(ignore) do
- local absoluteName = fs.path(name):string():lower()
- absolute[#absolute+1] = absoluteName
- end
- end
-
- local function isIgnored(path)
- if not absolute then
- return false
- end
- local target = path:string():lower()
- for _, name in ipairs(absolute) do
- if target == name then
- return true
- end
- end
- return false
- end
-
- return function ()
- i = i + 1
- local current = result[i]
- if not current then
- return nil
- end
- if fs.is_directory(current) then
- if not isIgnored(current) then
- for path in current:list_directory() do
- result[#result+1] = path
- end
- end
- end
- return current
- end
-end
diff --git a/server/src/workspace.lua b/server/src/workspace.lua
index 348208ca..034a057c 100644
--- a/server/src/workspace.lua
+++ b/server/src/workspace.lua
@@ -78,16 +78,18 @@ function mt:init(rootUri)
log.info('Log path: ', logPath)
log.init(ROOT, logPath)
- local ignored = {}
+ local ignored = {
+ ['.git'] = true,
+ }
for path in pairs(config.config.workspace.ignoreDir) do
- ignored[path] = true
+ ignored[#ignored+1] = path
end
if config.config.workspace.ignoreSubmodules then
local buf = io.load(self.root / '.gitmodules')
if buf then
for path in buf:gmatch('path = ([^\r\n]+)') do
log.debug('忽略子模块:', path)
- ignored[path] = true
+ ignored[#ignored+1] = path
end
end
end
@@ -95,25 +97,31 @@ function mt:init(rootUri)
local buf = io.load(self.root / '.gitignore')
if buf then
for line in buf:gmatch '[^\r\n]+' do
- ignored[line] = true
+ ignored[#ignored+1] = line
end
end
end
+ log.debug('忽略文件:\r\n' .. table.concat(ignored, '\r\n'))
+
async.run('scanfiles', {
root = self.root:string(),
- ignore = ignored,
- }, function (file)
- if file == 'ok' then
+ ignored = ignored,
+ }, function (mode, ...)
+ if mode == 'ok' then
self:reset()
self._complete = true
return true
+ elseif mode == 'log' then
+ log.debug(...)
+ elseif mode == 'file' then
+ local file = ...
+ local path = fs.path(file.path)
+ local name = path:string():lower()
+ local uri = self:uriEncode(path)
+ self.files[name] = uri
+ self.lsp:readText(uri, path, file.buf)
end
- local path = fs.path(file.path)
- local name = path:string():lower()
- local uri = self:uriEncode(path)
- self.files[name] = uri
- self.lsp:readText(uri, path, file.buf)
end)
end