From c427477428c0c1d583f42c0e7784684b8f713a6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Mon, 28 Jan 2019 17:43:40 +0800 Subject: =?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=96=B0=E7=9A=84=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/src/async/async.lua | 6 +-- server/src/async/scanfiles.lua | 106 ++++++++++++----------------------------- server/src/core/library.lua | 20 +++++++- server/src/log.lua | 2 +- server/src/path_filter.lua | 68 ++++++++++++++++++++++++++ server/src/utility.lua | 42 ---------------- server/src/workspace.lua | 32 ++++++++----- 7 files changed, 141 insertions(+), 135 deletions(-) create mode 100644 server/src/path_filter.lua (limited to 'server') 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 -- cgit v1.2.3 From 21f4c487be07960ffeac86e6842c5e159333e71c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Mon, 28 Jan 2019 17:54:49 +0800 Subject: =?UTF-8?q?=E7=89=B9=E6=AE=8A=E5=A4=84=E7=90=86=E4=B8=80=E4=B8=8B?= =?UTF-8?q?=E5=90=8E=E7=BD=AE=E6=96=9C=E6=9D=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/src/async/scanfiles.lua | 37 ++++++++++++++++++++++--------------- server/src/path_filter.lua | 3 +++ 2 files changed, 25 insertions(+), 15 deletions(-) (limited to 'server') diff --git a/server/src/async/scanfiles.lua b/server/src/async/scanfiles.lua index a9c266b3..6783f97b 100644 --- a/server/src/async/scanfiles.lua +++ b/server/src/async/scanfiles.lua @@ -5,8 +5,14 @@ local fs = require 'bee.filesystem' local path_filter = require 'path_filter' local function scan(root, filter) - local len = #root - local result = {fs.path(root)} + local result = {} + local len = #root:string() + local name = root:string():sub(len+2):gsub('/', '\\') + if filter(name) then + OUT:push('log', '过滤文件:', root:string()) + else + result[#result+1] = root + end local i = 0 return function () i = i + 1 @@ -15,17 +21,12 @@ local function scan(root, filter) return nil end 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 + 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 @@ -33,8 +34,14 @@ local function scan(root, filter) end end -local filter = path_filter(args.ignored) -for path in scan(args.root, filter) do +local ignore = {} +for _, name in ipairs(args.ignored) do + if name:sub(1, 1) ~= '!' then + ignore[#ignore+1] = name + end +end +local filter = path_filter(ignore) +for path in scan(fs.path(args.root), filter) do if path:extension():string() == '.lua' then local buf = io.load(path) if buf then diff --git a/server/src/path_filter.lua b/server/src/path_filter.lua index 2a362677..fb39a6f8 100644 --- a/server/src/path_filter.lua +++ b/server/src/path_filter.lua @@ -25,6 +25,9 @@ local function compile_exp(exp) else exp = '**/' .. exp end + if exp:sub(-1) == '/' then + exp = exp:sub(1, -2) + end local function next(cur) local pos, fn = exp:find('[/\\]+', cur) if not pos then -- cgit v1.2.3 From f231ada25549502c60839a1b1de1edd1314541bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Mon, 28 Jan 2019 17:57:58 +0800 Subject: =?UTF-8?q?=E4=BF=AE=E6=AD=A3bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/src/path_filter.lua | 11 ++++++----- server/src/workspace.lua | 4 +--- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'server') diff --git a/server/src/path_filter.lua b/server/src/path_filter.lua index fb39a6f8..403c938c 100644 --- a/server/src/path_filter.lua +++ b/server/src/path_filter.lua @@ -1,6 +1,6 @@ local m = require 'lpeglabel' -local m_cut = m.S'/\\' +local m_cut = m.S'\\' local m_path = (1-m_cut)^1 local function match_any(p, pass) @@ -20,16 +20,17 @@ local function compile_format(fmt) end local function compile_exp(exp) - if exp:sub(1, 1) == '/' then + exp = exp:gsub('/', '\\') + if exp:sub(1, 1) == '\\' then exp = exp:sub(2) else - exp = '**/' .. exp + exp = '**\\' .. exp end - if exp:sub(-1) == '/' then + if exp:sub(-1) == '\\' then exp = exp:sub(1, -2) end local function next(cur) - local pos, fn = exp:find('[/\\]+', cur) + local pos, fn = exp:find('[\\]+', cur) if not pos then return compile_format(exp:sub(cur)) end diff --git a/server/src/workspace.lua b/server/src/workspace.lua index 034a057c..c02f2854 100644 --- a/server/src/workspace.lua +++ b/server/src/workspace.lua @@ -78,9 +78,7 @@ function mt:init(rootUri) log.info('Log path: ', logPath) log.init(ROOT, logPath) - local ignored = { - ['.git'] = true, - } + local ignored = {'.git'} for path in pairs(config.config.workspace.ignoreDir) do ignored[#ignored+1] = path end -- cgit v1.2.3