diff options
Diffstat (limited to 'script-beta/files.lua')
-rw-r--r-- | script-beta/files.lua | 438 |
1 files changed, 0 insertions, 438 deletions
diff --git a/script-beta/files.lua b/script-beta/files.lua deleted file mode 100644 index 4d34568d..00000000 --- a/script-beta/files.lua +++ /dev/null @@ -1,438 +0,0 @@ -local platform = require 'bee.platform' -local config = require 'config' -local glob = require 'glob' -local furi = require 'file-uri' -local parser = require 'parser' -local proto = require 'proto' -local lang = require 'language' -local await = require 'await' -local timer = require 'timer' - -local m = {} - -m.openMap = {} -m.libraryMap = {} -m.fileMap = {} -m.watchList = {} -m.notifyCache = {} -m.assocVersion = -1 -m.assocMatcher = nil -m.globalVersion = 0 -m.linesMap = setmetatable({}, { __mode = 'v' }) -m.astMap = setmetatable({}, { __mode = 'v' }) - ---- 打开文件 ----@param uri string -function m.open(uri) - local originUri = uri - if platform.OS == 'Windows' then - uri = uri:lower() - end - m.openMap[uri] = true - m.onWatch('open', originUri) -end - ---- 关闭文件 ----@param uri string -function m.close(uri) - local originUri = uri - if platform.OS == 'Windows' then - uri = uri:lower() - end - m.openMap[uri] = nil - m.onWatch('close', originUri) -end - ---- 是否打开 ----@param uri string ----@return boolean -function m.isOpen(uri) - if platform.OS == 'Windows' then - uri = uri:lower() - end - return m.openMap[uri] == true -end - ---- 标记为库文件 -function m.setLibraryPath(uri, libraryPath) - if platform.OS == 'Windows' then - uri = uri:lower() - end - m.libraryMap[uri] = libraryPath -end - ---- 是否是库文件 -function m.isLibrary(uri) - if platform.OS == 'Windows' then - uri = uri:lower() - end - return m.libraryMap[uri] ~= nil -end - ---- 获取库文件的根目录 -function m.getLibraryPath(uri) - if platform.OS == 'Windows' then - uri = uri:lower() - end - return m.libraryMap[uri] -end - -function m.flushAllLibrary() - m.libraryMap = {} -end - ---- 是否存在 ----@return boolean -function m.exists(uri) - if platform.OS == 'Windows' then - uri = uri:lower() - end - return m.fileMap[uri] ~= nil -end - -function m.asKey(uri) - if platform.OS == 'Windows' then - uri = uri:lower() - end - return uri -end - ---- 设置文件文本 ----@param uri string ----@param text string -function m.setText(uri, text) - if not text then - return - end - local originUri = uri - if platform.OS == 'Windows' then - uri = uri:lower() - end - local create - if not m.fileMap[uri] then - m.fileMap[uri] = { - uri = originUri, - version = 0, - } - create = true - end - local file = m.fileMap[uri] - if file.text == text then - return - end - file.text = text - m.linesMap[uri] = nil - m.astMap[uri] = nil - file.cache = {} - file.cacheActiveTime = math.huge - file.version = file.version + 1 - m.globalVersion = m.globalVersion + 1 - await.close('files.version') - if create then - m.onWatch('create', originUri) - end - m.onWatch('update', originUri) -end - ---- 获取文件版本 -function m.getVersion(uri) - if platform.OS == 'Windows' then - uri = uri:lower() - end - local file = m.fileMap[uri] - if not file then - return nil - end - return file.version -end - ---- 获取文件文本 ----@param uri string ----@return string text -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 - ---- 移除文件 ----@param uri string -function m.remove(uri) - local originUri = uri - if platform.OS == 'Windows' then - uri = uri:lower() - end - local file = m.fileMap[uri] - if not file then - return - end - m.fileMap[uri] = nil - - m.globalVersion = m.globalVersion + 1 - await.close('files.version') - m.onWatch('remove', originUri) -end - ---- 移除所有文件 -function m.removeAll() - m.globalVersion = m.globalVersion + 1 - await.close('files.version') - for uri in pairs(m.fileMap) do - if not m.libraryMap[uri] then - m.fileMap[uri] = nil - m.astMap[uri] = nil - m.linesMap[uri] = nil - m.onWatch('remove', uri) - end - end - --m.notifyCache = {} -end - ---- 移除所有关闭的文件 -function m.removeAllClosed() - m.globalVersion = m.globalVersion + 1 - await.close('files.version') - for uri in pairs(m.fileMap) do - if not m.openMap[uri] - and not m.libraryMap[uri] then - m.fileMap[uri] = nil - m.astMap[uri] = nil - m.linesMap[uri] = nil - m.onWatch('remove', uri) - end - end - --m.notifyCache = {} -end - ---- 遍历文件 -function m.eachFile() - return pairs(m.fileMap) -end - -function m.compileAst(uri, text) - if not m.isOpen(uri) and #text >= config.config.workspace.preloadFileSize * 1000 then - if not m.notifyCache['preloadFileSize'] then - m.notifyCache['preloadFileSize'] = {} - m.notifyCache['skipLargeFileCount'] = 0 - end - if not m.notifyCache['preloadFileSize'][uri] then - m.notifyCache['preloadFileSize'][uri] = true - m.notifyCache['skipLargeFileCount'] = m.notifyCache['skipLargeFileCount'] + 1 - if m.notifyCache['skipLargeFileCount'] <= 3 then - local ws = require 'workspace' - proto.notify('window/showMessage', { - type = 3, - message = lang.script('WORKSPACE_SKIP_LARGE_FILE' - , ws.getRelativePath(uri) - , config.config.workspace.preloadFileSize - , #text / 1000 - ), - }) - end - end - return nil - end - local clock = os.clock() - local state, err = parser:compile(text - , 'lua' - , config.config.runtime.version - , { - special = config.config.runtime.special, - } - ) - local passed = os.clock() - clock - if passed > 0.1 then - log.warn(('Compile [%s] takes [%.3f] sec, size [%.3f] kb.'):format(uri, passed, #text / 1000)) - end - if state then - state.uri = uri - state.ast.uri = uri - if config.config.luadoc.enable then - parser:luadoc(state) - end - return state - else - log.error(err) - return nil - end -end - ---- 获取文件语法树 ----@param uri string ----@return table ast -function m.getAst(uri) - if platform.OS == 'Windows' then - uri = uri:lower() - end - if uri ~= '' and not m.isLua(uri) then - return nil - end - local file = m.fileMap[uri] - if not file then - return nil - end - local ast = m.astMap[uri] - if not ast then - ast = m.compileAst(uri, file.text) - m.astMap[uri] = ast - end - file.cacheActiveTime = timer.clock() - return ast -end - ---- 获取文件行信息 ----@param uri string ----@return table lines -function m.getLines(uri) - if platform.OS == 'Windows' then - uri = uri:lower() - end - local file = m.fileMap[uri] - if not file then - return nil - end - local lines = m.linesMap[uri] - if not lines then - lines = parser:lines(file.text) - m.linesMap[uri] = lines - end - return lines -end - ---- 获取原始uri -function m.getOriginUri(uri) - if platform.OS == 'Windows' then - uri = uri:lower() - end - local file = m.fileMap[uri] - if not file then - return nil - end - return file.uri -end - -function m.getUri(uri) - if platform.OS == 'Windows' then - uri = uri:lower() - end - return uri -end - ---- 获取文件的自定义缓存信息(在文件内容更新后自动失效) -function m.getCache(uri) - if platform.OS == 'Windows' then - uri = uri:lower() - end - local file = m.fileMap[uri] - if not file then - return nil - end - file.cacheActiveTime = timer.clock() - return file.cache -end - ---- 判断文件名相等 -function m.eq(a, b) - if platform.OS == 'Windows' then - return a:lower() == b:lower() - else - return a == b - end -end - ---- 获取文件关联 -function m.getAssoc() - if m.assocVersion == config.version then - return m.assocMatcher - end - m.assocVersion = config.version - local patt = {} - for k, v in pairs(config.other.associations) do - if m.eq(v, 'lua') then - patt[#patt+1] = k - end - end - m.assocMatcher = glob.glob(patt) - if platform.OS == 'Windows' then - m.assocMatcher:setOption 'ignoreCase' - end - return m.assocMatcher -end - ---- 判断是否是Lua文件 ----@param uri string ----@return boolean -function m.isLua(uri) - local ext = uri:match '%.([^%.%/%\\]-)$' - if not ext then - return false - end - if m.eq(ext, 'lua') then - return true - end - local matcher = m.getAssoc() - local path = furi.decode(uri) - return matcher(path) -end - ---- 注册事件 -function m.watch(callback) - m.watchList[#m.watchList+1] = callback -end - -function m.onWatch(ev, ...) - for _, callback in ipairs(m.watchList) do - callback(ev, ...) - end -end - -function m.flushCache() - for uri, file in pairs(m.fileMap) do - file.cacheActiveTime = math.huge - m.linesMap[uri] = nil - m.astMap[uri] = nil - file.cache = {} - end -end - -function m.flushFileCache(uri) - if platform.OS == 'Windows' then - uri = uri:lower() - end - local file = m.fileMap[uri] - if not file then - return - end - file.cacheActiveTime = math.huge - m.linesMap[uri] = nil - m.astMap[uri] = nil - file.cache = {} -end - -local function init() - --TODO 可以清空文件缓存,之后看要不要启用吧 - --timer.loop(10, function () - -- local list = {} - -- for _, file in pairs(m.fileMap) do - -- if timer.clock() - file.cacheActiveTime > 10.0 then - -- file.cacheActiveTime = math.huge - -- file.ast = nil - -- file.cache = {} - -- list[#list+1] = file.uri - -- end - -- end - -- if #list > 0 then - -- log.info('Flush file caches:', #list, '\n', table.concat(list, '\n')) - -- collectgarbage() - -- end - --end) -end - -xpcall(init, log.error) - -return m |