diff options
Diffstat (limited to 'script/provider/provider.lua')
-rw-r--r-- | script/provider/provider.lua | 307 |
1 files changed, 248 insertions, 59 deletions
diff --git a/script/provider/provider.lua b/script/provider/provider.lua index 3d012757..018db0c3 100644 --- a/script/provider/provider.lua +++ b/script/provider/provider.lua @@ -21,6 +21,8 @@ local furi = require 'file-uri' local inspect = require 'inspect' local markdown = require 'provider.markdown' local guide = require 'parser.guide' +local fs = require 'bee.filesystem' +local jumpSource = require 'core.jump-source' ---@async local function updateConfig(uri) @@ -28,7 +30,7 @@ local function updateConfig(uri) local specified = cfgLoader.loadLocalConfig(uri, CONFIGPATH) if specified then log.info('Load config from specified', CONFIGPATH) - log.debug(inspect(specified)) + log.info(inspect(specified)) -- watch directory filewatch.watch(workspace.getAbsolutePath(uri, CONFIGPATH):gsub('[^/\\]+$', '')) config.update(scope.override, specified) @@ -38,14 +40,14 @@ local function updateConfig(uri) local clientConfig = cfgLoader.loadClientConfig(folder.uri) if clientConfig then log.info('Load config from client', folder.uri) - log.debug(inspect(clientConfig)) + log.info(inspect(clientConfig)) end local rc = cfgLoader.loadRCConfig(folder.uri, '.luarc.json') or cfgLoader.loadRCConfig(folder.uri, '.luarc.jsonc') if rc then log.info('Load config from .luarc.json/.luarc.jsonc', folder.uri) - log.debug(inspect(rc)) + log.info(inspect(rc)) end config.update(folder, clientConfig, rc) @@ -53,7 +55,7 @@ local function updateConfig(uri) local global = cfgLoader.loadClientConfig() log.info('Load config from client', 'fallback') - log.debug(inspect(global)) + log.info(inspect(global)) config.update(scope.fallback, global) end @@ -149,7 +151,6 @@ m.register 'initialized'{ }) end client.setReady() - library.init() workspace.init() return true end @@ -234,11 +235,35 @@ m.register 'workspace/didRenameFiles' { end } +m.register 'workspace/didChangeWorkspaceFolders' { + capability = { + workspace = { + workspaceFolders = { + supported = true, + changeNotifications = true, + }, + }, + }, + ---@async + function (params) + log.debug('workspace/didChangeWorkspaceFolders', inspect(params)) + for _, folder in ipairs(params.event.added) do + workspace.create(folder.uri) + updateConfig() + workspace.reload(scope.getScope(folder.uri)) + end + for _, folder in ipairs(params.event.removed) do + workspace.remove(folder.uri) + end + end +} + m.register 'textDocument/didOpen' { function (params) - local doc = params.textDocument - local scheme = furi.split(doc.uri) - if scheme ~= 'file' then + local doc = params.textDocument + local scheme = furi.split(doc.uri) + local supports = config.get(doc.uri, 'Lua.workspace.supportScheme') + if not util.arrayHas(supports, scheme) then return end local uri = files.getRealUri(doc.uri) @@ -264,15 +289,21 @@ m.register 'textDocument/didClose' { } m.register 'textDocument/didChange' { + ---@async function (params) - local doc = params.textDocument - local scheme = furi.split(doc.uri) - if scheme ~= 'file' then + local doc = params.textDocument + local scheme = furi.split(doc.uri) + local supports = config.get(doc.uri, 'Lua.workspace.supportScheme') + if not util.arrayHas(supports, scheme) then return end local changes = params.contentChanges local uri = files.getRealUri(doc.uri) - local text = files.getOriginText(uri) or '' + local text = files.getOriginText(uri) + if not text then + files.setText(uri, pub.awaitTask('loadFile', furi.decode(uri)), false) + return + end local rows = files.getCachedRows(uri) text, rows = tm(text, rows, changes) files.setText(uri, text, true, function (file) @@ -310,7 +341,7 @@ m.register 'textDocument/hover' { end local pos = converter.unpackPosition(uri, params.position) local hover, source = core.byUri(uri, pos) - if not hover then + if not hover or not source then return nil end return { @@ -346,18 +377,16 @@ m.register 'textDocument/definition' { for i, info in ipairs(result) do local targetUri = info.uri if targetUri then - if files.exists(targetUri) then - if client.getAbility 'textDocument.definition.linkSupport' then - response[i] = converter.locationLink(targetUri - , converter.packRange(targetUri, info.target.start, info.target.finish) - , converter.packRange(targetUri, info.target.start, info.target.finish) - , converter.packRange(uri, info.source.start, info.source.finish) - ) - else - response[i] = converter.location(targetUri - , converter.packRange(targetUri, info.target.start, info.target.finish) - ) - end + if client.getAbility 'textDocument.definition.linkSupport' then + response[i] = converter.locationLink(targetUri + , converter.packRange(targetUri, info.target.start, info.target.finish) + , converter.packRange(targetUri, info.target.start, info.target.finish) + , converter.packRange(uri, info.source.start, info.source.finish) + ) + else + response[i] = converter.location(targetUri + , converter.packRange(targetUri, info.target.start, info.target.finish) + ) end end end @@ -388,18 +417,16 @@ m.register 'textDocument/typeDefinition' { for i, info in ipairs(result) do local targetUri = info.uri if targetUri then - if files.exists(targetUri) then - if client.getAbility 'textDocument.typeDefinition.linkSupport' then - response[i] = converter.locationLink(targetUri - , converter.packRange(targetUri, info.target.start, info.target.finish) - , converter.packRange(targetUri, info.target.start, info.target.finish) - , converter.packRange(uri, info.source.start, info.source.finish) - ) - else - response[i] = converter.location(targetUri - , converter.packRange(targetUri, info.target.start, info.target.finish) - ) - end + if client.getAbility 'textDocument.typeDefinition.linkSupport' then + response[i] = converter.locationLink(targetUri + , converter.packRange(targetUri, info.target.start, info.target.finish) + , converter.packRange(targetUri, info.target.start, info.target.finish) + , converter.packRange(uri, info.source.start, info.source.finish) + ) + else + response[i] = converter.location(targetUri + , converter.packRange(targetUri, info.target.start, info.target.finish) + ) end end end @@ -902,29 +929,35 @@ local function toArray(map) return array end -m.register 'textDocument/semanticTokens/full' { - capability = { - semanticTokensProvider = { - legend = { - tokenTypes = toArray(define.TokenTypes), - tokenModifiers = toArray(define.TokenModifiers), - }, - full = true, - }, - }, - ---@async - function (params) - log.debug('textDocument/semanticTokens/full') - local uri = files.getRealUri(params.textDocument.uri) - workspace.awaitReady(uri) - local _ <close> = progress.create(uri, lang.script.WINDOW_PROCESSING_SEMANTIC_FULL, 0.5) - local core = require 'core.semantic-tokens' - local results = core(uri, 0, math.huge) - return { - data = results - } +client.event(function (ev) + if ev == 'init' then + if not client.isVSCode() then + m.register 'textDocument/semanticTokens/full' { + capability = { + semanticTokensProvider = { + legend = { + tokenTypes = toArray(define.TokenTypes), + tokenModifiers = toArray(define.TokenModifiers), + }, + full = true, + }, + }, + ---@async + function (params) + log.debug('textDocument/semanticTokens/full') + local uri = files.getRealUri(params.textDocument.uri) + workspace.awaitReady(uri) + local _ <close> = progress.create(uri, lang.script.WINDOW_PROCESSING_SEMANTIC_FULL, 0.5) + local core = require 'core.semantic-tokens' + local results = core(uri, 0, math.huge) + return { + data = results + } + end + } + end end -} +end) m.register 'textDocument/semanticTokens/range' { capability = { @@ -988,6 +1021,40 @@ m.register 'textDocument/foldingRange' { end } +m.register 'textDocument/documentColor' { + capability = { + colorProvider = true + }, + ---@async + function (params) + local color = require 'core.color' + local uri = files.getRealUri(params.textDocument.uri) + workspace.awaitReady(uri) + if not files.exists(uri) then + return nil + end + local colors = color.colors(uri) + if not colors then + return nil + end + local results = {} + for _, colorValue in ipairs(colors) do + results[#results+1] = { + range = converter.packRange(uri, colorValue.start, colorValue.finish), + color = colorValue.color + } + end + return results + end +} + +m.register 'textDocument/colorPresentation' { + function (params) + local color = (require 'core.color').colorToText(params.color) + return {{label = color}} + end +} + m.register 'window/workDoneProgress/cancel' { function (params) log.debug('close proto(cancel):', params.token) @@ -1001,6 +1068,7 @@ m.register '$/status/click' { local titleDiagnostic = lang.script.WINDOW_LUA_STATUS_DIAGNOSIS_TITLE local result = client.awaitRequestMessage('Info', lang.script.WINDOW_LUA_STATUS_DIAGNOSIS_MSG, { titleDiagnostic, + DEVELOP and 'Restart Server', }) if not result then return @@ -1010,6 +1078,10 @@ m.register '$/status/click' { for _, scp in ipairs(workspace.folders) do diagnostic.diagnosticsScope(scp.uri, true) end + elseif result == 'Restart Server' then + local diag = require 'provider.diagnostic' + diag.clearAll(true) + os.exit(0, true) end end } @@ -1210,6 +1282,123 @@ m.register 'inlayHint/resolve' { end } +m.register 'textDocument/diagnostic' { + preview = true, + capability = { + diagnosticProvider = { + identifier = 'identifier', + interFileDependencies = true, + workspaceDiagnostics = false, + } + }, + ---@async + function (params) + local uri = files.getRealUri(params.textDocument.uri) + workspace.awaitReady(uri) + local core = require 'provider.diagnostic' + -- TODO: do some trick + core.doDiagnostic(uri) + + return { + kind = 'unchanged', + resultId = uri, + } + + --if not params.previousResultId then + -- core.clearCache(uri) + --end + --local results, unchanged = core.pullDiagnostic(uri, false) + --if unchanged then + -- return { + -- kind = 'unchanged', + -- resultId = uri, + -- } + --else + -- return { + -- kind = 'full', + -- resultId = uri, + -- items = results or {}, + -- } + --end + end +} + +m.register 'workspace/diagnostic' { + --preview = true, + --capability = { + -- diagnosticProvider = { + -- workspaceDiagnostics = false, + -- } + --}, + ---@async + function (params) + local core = require 'provider.diagnostic' + local excepts = {} + for _, id in ipairs(params.previousResultIds) do + excepts[#excepts+1] = id.value + end + core.clearCacheExcept(excepts) + local function convertItem(result) + if result.unchanged then + return { + kind = 'unchanged', + resultId = result.uri, + uri = result.uri, + version = result.version, + } + else + return { + kind = 'full', + resultId = result.uri, + items = result.result or {}, + uri = result.uri, + version = result.version, + } + end + end + core.pullDiagnosticScope(function (result) + proto.notify('$/progress', { + token = params.partialResultToken, + value = { + items = { + convertItem(result) + } + } + }) + end) + return { items = {} } + end +} + +m.register '$/api/report' { + ---@async + function (params) + local buildMeta = require 'provider.build-meta' + local SDBMHash = require 'SDBMHash' + await.close 'api/report' + await.setID 'api/report' + local name = params.name or 'default' + local uri = workspace.getFirstScope().uri + local hash = uri and ('%08x'):format(SDBMHash():hash(uri)) + local encoding = config.get(nil, 'Lua.runtime.fileEncoding') + local nameBuf = {} + nameBuf[#nameBuf+1] = name + nameBuf[#nameBuf+1] = hash + nameBuf[#nameBuf+1] = encoding + local fileDir = METAPATH .. '/' .. table.concat(nameBuf, ' ') + fs.create_directories(fs.path(fileDir)) + buildMeta.build(fileDir, params) + client.setConfig { + { + key = 'Lua.workspace.library', + action = 'add', + value = fileDir, + uri = uri, + } + } + end +} + local function refreshStatusBar() local valid = config.get(nil, 'Lua.window.statusBar') for _, scp in ipairs(workspace.folders) do |