dotfiles from arch
This commit is contained in:
@@ -0,0 +1,727 @@
|
||||
local await = require 'await'
|
||||
local proto = require 'proto.proto'
|
||||
local define = require 'proto.define'
|
||||
local lang = require 'language'
|
||||
local files = require 'files'
|
||||
local config = require 'config'
|
||||
local core = require 'core.diagnostics'
|
||||
local util = require 'utility'
|
||||
local ws = require 'workspace'
|
||||
local progress = require "progress"
|
||||
local client = require 'client'
|
||||
local converter = require 'proto.converter'
|
||||
local loading = require 'workspace.loading'
|
||||
local scope = require 'workspace.scope'
|
||||
local time = require 'bee.time'
|
||||
local ltable = require 'linked-table'
|
||||
local furi = require 'file-uri'
|
||||
local json = require 'json'
|
||||
local fw = require 'filewatch'
|
||||
local vm = require 'vm.vm'
|
||||
|
||||
---@class diagnosticProvider
|
||||
local m = {}
|
||||
m.cache = {}
|
||||
m.sleepRest = 0.0
|
||||
m.scopeDiagCount = 0
|
||||
m.pauseCount = 0
|
||||
|
||||
local function concat(t, sep)
|
||||
if type(t) ~= 'table' then
|
||||
return t
|
||||
end
|
||||
return table.concat(t, sep)
|
||||
end
|
||||
|
||||
local function buildSyntaxError(uri, err)
|
||||
local state = files.getState(uri)
|
||||
local text = files.getText(uri)
|
||||
if not text or not state then
|
||||
return
|
||||
end
|
||||
local message = lang.script('PARSER_' .. err.type, err.info)
|
||||
|
||||
if err.version then
|
||||
local version = err.info and err.info.version or config.get(uri, 'Lua.runtime.version')
|
||||
message = message .. ('(%s)'):format(lang.script('DIAG_NEED_VERSION'
|
||||
, concat(err.version, '/')
|
||||
, version
|
||||
))
|
||||
end
|
||||
|
||||
local related = err.info and err.info.related
|
||||
local relatedInformation
|
||||
if related then
|
||||
relatedInformation = {}
|
||||
for _, rel in ipairs(related) do
|
||||
local rmessage
|
||||
if rel.message then
|
||||
rmessage = lang.script('PARSER_' .. rel.message)
|
||||
else
|
||||
rmessage = text:sub(rel.start, rel.finish)
|
||||
end
|
||||
local relUri = rel.uri or uri
|
||||
local relState = files.getState(relUri)
|
||||
if relState then
|
||||
relatedInformation[#relatedInformation+1] = {
|
||||
message = rmessage,
|
||||
location = converter.location(relUri, converter.packRange(relState, rel.start, rel.finish)),
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
code = err.type:lower():gsub('_', '-'),
|
||||
range = converter.packRange(state, err.start, err.finish),
|
||||
severity = define.DiagnosticSeverity[err.level],
|
||||
source = lang.script.DIAG_SYNTAX_CHECK,
|
||||
message = message,
|
||||
data = 'syntax',
|
||||
|
||||
relatedInformation = relatedInformation,
|
||||
}
|
||||
end
|
||||
|
||||
local function buildDiagnostic(uri, diag)
|
||||
local state = files.getState(uri)
|
||||
if not state then
|
||||
return
|
||||
end
|
||||
|
||||
local relatedInformation
|
||||
if diag.related then
|
||||
relatedInformation = {}
|
||||
for _, rel in ipairs(diag.related) do
|
||||
local rtext = files.getText(rel.uri)
|
||||
if not rtext then
|
||||
goto CONTINUE
|
||||
end
|
||||
local relState = files.getState(rel.uri)
|
||||
if not relState then
|
||||
goto CONTINUE
|
||||
end
|
||||
relatedInformation[#relatedInformation+1] = {
|
||||
message = rel.message or rtext:sub(rel.start, rel.finish),
|
||||
location = converter.location(rel.uri, converter.packRange(relState, rel.start, rel.finish))
|
||||
}
|
||||
::CONTINUE::
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
range = converter.packRange(state, diag.start, diag.finish),
|
||||
source = lang.script.DIAG_DIAGNOSTICS,
|
||||
severity = diag.level,
|
||||
message = diag.message,
|
||||
code = diag.code,
|
||||
tags = diag.tags,
|
||||
data = diag.data,
|
||||
|
||||
relatedInformation = relatedInformation,
|
||||
}
|
||||
end
|
||||
|
||||
local function mergeDiags(a, b, c)
|
||||
if not a and not b and not c then
|
||||
return nil
|
||||
end
|
||||
local t = {}
|
||||
|
||||
local function merge(diags)
|
||||
if not diags then
|
||||
return
|
||||
end
|
||||
for i = 1, #diags do
|
||||
local diag = diags[i]
|
||||
local severity = diag.severity
|
||||
if severity == define.DiagnosticSeverity.Hint
|
||||
or severity == define.DiagnosticSeverity.Information then
|
||||
if #t > 10000 then
|
||||
goto CONTINUE
|
||||
end
|
||||
end
|
||||
t[#t+1] = diag
|
||||
::CONTINUE::
|
||||
end
|
||||
end
|
||||
|
||||
merge(a)
|
||||
merge(b)
|
||||
merge(c)
|
||||
|
||||
if #t == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
-- enable `push`, disable `clear`
|
||||
function m.clear(uri, force)
|
||||
await.close('diag:' .. uri)
|
||||
if m.cache[uri] == nil and not force then
|
||||
return
|
||||
end
|
||||
m.cache[uri] = nil
|
||||
proto.notify('textDocument/publishDiagnostics', {
|
||||
uri = uri,
|
||||
diagnostics = {},
|
||||
})
|
||||
log.info('clearDiagnostics', uri)
|
||||
end
|
||||
|
||||
function m.clearCacheExcept(uris)
|
||||
local excepts = {}
|
||||
for _, uri in ipairs(uris) do
|
||||
excepts[uri] = true
|
||||
end
|
||||
for uri in pairs(m.cache) do
|
||||
if not excepts[uri] then
|
||||
m.cache[uri] = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param uri? uri
|
||||
---@param force? boolean
|
||||
function m.clearAll(uri, force)
|
||||
local scp
|
||||
if uri then
|
||||
scp = scope.getScope(uri)
|
||||
end
|
||||
if force then
|
||||
for luri in files.eachFile() do
|
||||
if not scp or scope.getScope(luri) == scp then
|
||||
m.clear(luri, force)
|
||||
end
|
||||
end
|
||||
else
|
||||
for luri in pairs(m.cache) do
|
||||
if not scp or scope.getScope(luri) == scp then
|
||||
m.clear(luri)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function m.syntaxErrors(uri, ast)
|
||||
if #ast.errs == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
local results = {}
|
||||
|
||||
pcall(function ()
|
||||
local disables = util.arrayToHash(config.get(uri, 'Lua.diagnostics.disable'))
|
||||
for _, err in ipairs(ast.errs) do
|
||||
local id = err.type:lower():gsub('_', '-')
|
||||
if not disables[id]
|
||||
and not vm.isDiagDisabledAt(uri, err.start, id, true) then
|
||||
results[#results+1] = buildSyntaxError(uri, err)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
return results
|
||||
end
|
||||
|
||||
local function copyDiagsWithoutSyntax(diags)
|
||||
if not diags then
|
||||
return nil
|
||||
end
|
||||
local copyed = {}
|
||||
for _, diag in ipairs(diags) do
|
||||
if diag.data ~= 'syntax' then
|
||||
copyed[#copyed+1] = diag
|
||||
end
|
||||
end
|
||||
return copyed
|
||||
end
|
||||
|
||||
---@async
|
||||
---@param uri uri
|
||||
---@return boolean
|
||||
local function isValid(uri)
|
||||
if not config.get(uri, 'Lua.diagnostics.enable') then
|
||||
return false
|
||||
end
|
||||
if not ws.isReady(uri) then
|
||||
return false
|
||||
end
|
||||
if files.isLibrary(uri, true) then
|
||||
local status = config.get(uri, 'Lua.diagnostics.libraryFiles')
|
||||
if status == 'Disable' then
|
||||
return false
|
||||
elseif status == 'Opened' then
|
||||
if not files.isOpen(uri) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
if ws.isIgnored(uri) then
|
||||
local status = config.get(uri, 'Lua.diagnostics.ignoredFiles')
|
||||
if status == 'Disable' then
|
||||
return false
|
||||
elseif status == 'Opened' then
|
||||
if not files.isOpen(uri) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
local scheme = furi.split(uri)
|
||||
local disableScheme = config.get(uri, 'Lua.diagnostics.disableScheme')
|
||||
if util.arrayHas(disableScheme, scheme) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
---@async
|
||||
function m.doDiagnostic(uri, isScopeDiag, ignoreFileState)
|
||||
if not isValid(uri) then
|
||||
return
|
||||
end
|
||||
|
||||
await.delay()
|
||||
|
||||
local state = files.getState(uri)
|
||||
if not state then
|
||||
m.clear(uri)
|
||||
return
|
||||
end
|
||||
|
||||
local version = files.getVersion(uri)
|
||||
|
||||
local prog <close> = progress.create(uri, lang.script.WINDOW_DIAGNOSING, 0.5)
|
||||
prog:setMessage(ws.getRelativePath(uri))
|
||||
|
||||
--log.debug('Diagnostic file:', uri)
|
||||
|
||||
local syntax = m.syntaxErrors(uri, state)
|
||||
|
||||
local diags = {}
|
||||
local lastDiag = copyDiagsWithoutSyntax(m.cache[uri])
|
||||
local function pushResult()
|
||||
tracy.ZoneBeginN 'mergeSyntaxAndDiags'
|
||||
local _ <close> = tracy.ZoneEnd
|
||||
local full = mergeDiags(syntax, lastDiag, diags)
|
||||
--log.debug(('Pushed [%d] results'):format(full and #full or 0))
|
||||
if not full then
|
||||
m.clear(uri)
|
||||
return
|
||||
end
|
||||
|
||||
if util.equal(m.cache[uri], full) then
|
||||
return
|
||||
end
|
||||
m.cache[uri] = full
|
||||
|
||||
if not files.exists(uri) then
|
||||
m.clear(uri)
|
||||
return
|
||||
end
|
||||
|
||||
proto.notify('textDocument/publishDiagnostics', {
|
||||
uri = uri,
|
||||
version = version,
|
||||
diagnostics = full,
|
||||
})
|
||||
log.debug('publishDiagnostics', uri, #full)
|
||||
end
|
||||
|
||||
pushResult()
|
||||
|
||||
local lastPushClock = time.time()
|
||||
---@async
|
||||
xpcall(core, log.error, uri, isScopeDiag, function (result)
|
||||
diags[#diags+1] = buildDiagnostic(uri, result)
|
||||
|
||||
if not isScopeDiag and time.time() - lastPushClock >= 500 then
|
||||
lastPushClock = time.time()
|
||||
pushResult()
|
||||
end
|
||||
end, function (checkedName)
|
||||
if not lastDiag then
|
||||
return
|
||||
end
|
||||
for i, diag in ipairs(lastDiag) do
|
||||
if diag.code == checkedName then
|
||||
lastDiag[i] = lastDiag[#lastDiag]
|
||||
lastDiag[#lastDiag] = nil
|
||||
end
|
||||
end
|
||||
end, ignoreFileState)
|
||||
|
||||
lastDiag = nil
|
||||
pushResult()
|
||||
end
|
||||
|
||||
---@param uri uri
|
||||
function m.resendDiagnostic(uri)
|
||||
local full = m.cache[uri]
|
||||
if not full then
|
||||
return
|
||||
end
|
||||
|
||||
if not files.exists(uri) then
|
||||
m.clear(uri)
|
||||
return
|
||||
end
|
||||
|
||||
local version = files.getVersion(uri)
|
||||
|
||||
proto.notify('textDocument/publishDiagnostics', {
|
||||
uri = uri,
|
||||
version = version,
|
||||
diagnostics = full,
|
||||
})
|
||||
log.debug('publishDiagnostics', uri, #full)
|
||||
end
|
||||
|
||||
---@async
|
||||
---@return table|nil result
|
||||
---@return boolean? unchanged
|
||||
function m.pullDiagnostic(uri, isScopeDiag)
|
||||
if not isValid(uri) then
|
||||
return nil, util.equal(m.cache[uri], nil)
|
||||
end
|
||||
|
||||
await.delay()
|
||||
|
||||
local state = files.getState(uri)
|
||||
if not state then
|
||||
return nil, util.equal(m.cache[uri], nil)
|
||||
end
|
||||
|
||||
local prog <close> = progress.create(uri, lang.script.WINDOW_DIAGNOSING, 0.5)
|
||||
prog:setMessage(ws.getRelativePath(uri))
|
||||
|
||||
local syntax = m.syntaxErrors(uri, state)
|
||||
local diags = {}
|
||||
|
||||
xpcall(core, log.error, uri, isScopeDiag, function (result)
|
||||
diags[#diags+1] = buildDiagnostic(uri, result)
|
||||
end)
|
||||
|
||||
local full = mergeDiags(syntax, diags)
|
||||
|
||||
if util.equal(m.cache[uri], full) then
|
||||
return full, true
|
||||
end
|
||||
|
||||
m.cache[uri] = full
|
||||
|
||||
return full
|
||||
end
|
||||
|
||||
---@param uri uri
|
||||
function m.stopScopeDiag(uri)
|
||||
local scp = scope.getScope(uri)
|
||||
local scopeID = 'diagnosticsScope:' .. scp:getName()
|
||||
await.close(scopeID)
|
||||
end
|
||||
|
||||
---@param event string
|
||||
---@param uri uri
|
||||
function m.refreshScopeDiag(event, uri)
|
||||
if not ws.isReady(uri) then
|
||||
return
|
||||
end
|
||||
|
||||
local eventConfig = config.get(uri, 'Lua.diagnostics.workspaceEvent')
|
||||
|
||||
if eventConfig ~= event then
|
||||
return
|
||||
end
|
||||
|
||||
---@async
|
||||
await.call(function ()
|
||||
local delay = config.get(uri, 'Lua.diagnostics.workspaceDelay') / 1000
|
||||
if delay < 0 then
|
||||
return
|
||||
end
|
||||
await.sleep(math.max(delay, 0.2))
|
||||
m.diagnosticsScope(uri)
|
||||
end)
|
||||
end
|
||||
|
||||
---@param uri uri
|
||||
function m.refresh(uri)
|
||||
if not ws.isReady(uri) then
|
||||
return
|
||||
end
|
||||
|
||||
await.close('diag:' .. uri)
|
||||
---@async
|
||||
await.call(function ()
|
||||
await.setID('diag:' .. uri)
|
||||
repeat
|
||||
await.sleep(0.1)
|
||||
until not m.isPaused()
|
||||
xpcall(m.doDiagnostic, log.error, uri)
|
||||
end)
|
||||
end
|
||||
|
||||
---@async
|
||||
local function askForDisable(uri)
|
||||
if m.dontAskedForDisable then
|
||||
return
|
||||
end
|
||||
local delay = 30
|
||||
local delayTitle = lang.script('WINDOW_DELAY_WS_DIAGNOSTIC', delay)
|
||||
local item = proto.awaitRequest('window/showMessageRequest', {
|
||||
type = define.MessageType.Info,
|
||||
message = lang.script.WINDOW_SETTING_WS_DIAGNOSTIC,
|
||||
actions = {
|
||||
{
|
||||
title = lang.script.WINDOW_DONT_SHOW_AGAIN,
|
||||
},
|
||||
{
|
||||
title = delayTitle,
|
||||
},
|
||||
{
|
||||
title = lang.script.WINDOW_DISABLE_DIAGNOSTIC,
|
||||
},
|
||||
}
|
||||
})
|
||||
if not item then
|
||||
return
|
||||
end
|
||||
if item.title == lang.script.WINDOW_DONT_SHOW_AGAIN then
|
||||
m.dontAskedForDisable = true
|
||||
elseif item.title == delayTitle then
|
||||
client.setConfig {
|
||||
{
|
||||
key = 'Lua.diagnostics.workspaceDelay',
|
||||
action = 'set',
|
||||
value = delay * 1000,
|
||||
uri = uri,
|
||||
}
|
||||
}
|
||||
elseif item.title == lang.script.WINDOW_DISABLE_DIAGNOSTIC then
|
||||
client.setConfig {
|
||||
{
|
||||
key = 'Lua.diagnostics.workspaceDelay',
|
||||
action = 'set',
|
||||
value = -1,
|
||||
uri = uri,
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local function clearMemory(finished)
|
||||
if m.scopeDiagCount > 0 then
|
||||
return
|
||||
end
|
||||
vm.clearNodeCache()
|
||||
if finished then
|
||||
collectgarbage()
|
||||
collectgarbage()
|
||||
end
|
||||
end
|
||||
|
||||
---@async
|
||||
function m.awaitDiagnosticsScope(suri, callback)
|
||||
local scp = scope.getScope(suri)
|
||||
if scp.type == 'fallback' then
|
||||
return
|
||||
end
|
||||
while loading.count() > 0 do
|
||||
await.sleep(1.0)
|
||||
end
|
||||
local finished
|
||||
m.scopeDiagCount = m.scopeDiagCount + 1
|
||||
local scopeDiag <close> = util.defer(function ()
|
||||
m.scopeDiagCount = m.scopeDiagCount - 1
|
||||
clearMemory(finished)
|
||||
end)
|
||||
local clock = os.clock()
|
||||
local bar <close> = progress.create(suri, lang.script.WORKSPACE_DIAGNOSTIC, 1)
|
||||
local cancelled
|
||||
bar:onCancel(function ()
|
||||
log.info('Cancel workspace diagnostics')
|
||||
cancelled = true
|
||||
---@async
|
||||
await.call(function ()
|
||||
askForDisable(suri)
|
||||
end)
|
||||
end)
|
||||
local uris = files.getAllUris(suri)
|
||||
local sortedUris = ltable()
|
||||
for _, uri in ipairs(uris) do
|
||||
if files.isOpen(uri) then
|
||||
sortedUris:pushHead(uri)
|
||||
else
|
||||
sortedUris:pushTail(uri)
|
||||
end
|
||||
end
|
||||
log.info(('Diagnostics scope [%s], files count:[%d]'):format(scp:getName(), #uris))
|
||||
local i = 0
|
||||
for uri in sortedUris:pairs() do
|
||||
while loading.count() > 0 do
|
||||
await.sleep(1.0)
|
||||
end
|
||||
i = i + 1
|
||||
bar:setMessage(('%d/%d'):format(i, #uris))
|
||||
bar:setPercentage(i / #uris * 100)
|
||||
callback(uri)
|
||||
await.delay()
|
||||
if cancelled then
|
||||
log.info('Break workspace diagnostics')
|
||||
break
|
||||
end
|
||||
end
|
||||
bar:remove()
|
||||
log.info(('Diagnostics scope [%s] finished, takes [%.3f] sec.'):format(scp:getName(), os.clock() - clock))
|
||||
finished = true
|
||||
end
|
||||
|
||||
function m.diagnosticsScope(uri, force, ignoreFileOpenState)
|
||||
if not ws.isReady(uri) then
|
||||
return
|
||||
end
|
||||
if not force and not config.get(uri, 'Lua.diagnostics.enable') then
|
||||
m.clearAll(uri)
|
||||
return
|
||||
end
|
||||
if not force and config.get(uri, 'Lua.diagnostics.workspaceDelay') < 0 then
|
||||
return
|
||||
end
|
||||
local scp = scope.getScope(uri)
|
||||
local id = 'diagnosticsScope:' .. scp:getName()
|
||||
await.close(id)
|
||||
await.call(function () ---@async
|
||||
await.sleep(0.0)
|
||||
m.awaitDiagnosticsScope(uri, function (fileUri)
|
||||
xpcall(m.doDiagnostic, log.error, fileUri, true, ignoreFileOpenState)
|
||||
end)
|
||||
end, id)
|
||||
end
|
||||
|
||||
---@async
|
||||
function m.pullDiagnosticScope(callback)
|
||||
local processing = 0
|
||||
|
||||
for _, scp in ipairs(scope.folders) do
|
||||
if ws.isReady(scp.uri)
|
||||
and config.get(scp.uri, 'Lua.diagnostics.enable') then
|
||||
local id = 'diagnosticsScope:' .. scp:getName()
|
||||
await.close(id)
|
||||
await.call(function () ---@async
|
||||
processing = processing + 1
|
||||
local _ <close> = util.defer(function ()
|
||||
processing = processing - 1
|
||||
end)
|
||||
|
||||
local delay = config.get(scp.uri, 'Lua.diagnostics.workspaceDelay') / 1000
|
||||
if delay < 0 then
|
||||
return
|
||||
end
|
||||
print(delay)
|
||||
await.sleep(math.max(delay, 0.2))
|
||||
print('start')
|
||||
|
||||
m.awaitDiagnosticsScope(scp.uri, function (fileUri)
|
||||
local suc, result, unchanged = xpcall(m.pullDiagnostic, log.error, fileUri, true)
|
||||
if suc then
|
||||
callback {
|
||||
uri = fileUri,
|
||||
result = result,
|
||||
unchanged = unchanged,
|
||||
version = files.getVersion(fileUri),
|
||||
}
|
||||
end
|
||||
end)
|
||||
end, id)
|
||||
end
|
||||
end
|
||||
|
||||
-- sleep for ever
|
||||
while true do
|
||||
await.sleep(1.0)
|
||||
end
|
||||
end
|
||||
|
||||
function m.refreshClient()
|
||||
if not client.isReady() then
|
||||
return
|
||||
end
|
||||
if not client.getAbility 'workspace.diagnostics.refreshSupport' then
|
||||
return
|
||||
end
|
||||
log.debug('Refresh client diagnostics')
|
||||
proto.request('workspace/diagnostic/refresh', json.null)
|
||||
end
|
||||
|
||||
---@return boolean
|
||||
function m.isPaused()
|
||||
return m.pauseCount > 0
|
||||
end
|
||||
|
||||
function m.pause()
|
||||
m.pauseCount = m.pauseCount + 1
|
||||
end
|
||||
|
||||
function m.resume()
|
||||
m.pauseCount = m.pauseCount - 1
|
||||
end
|
||||
|
||||
ws.watch(function (ev, uri)
|
||||
if ev == 'reload' then
|
||||
m.diagnosticsScope(uri)
|
||||
m.refreshClient()
|
||||
end
|
||||
end)
|
||||
|
||||
files.watch(function (ev, uri) ---@async
|
||||
if ev == 'remove' then
|
||||
m.clear(uri)
|
||||
m.stopScopeDiag(uri)
|
||||
m.refresh(uri)
|
||||
m.refreshScopeDiag('OnSave', uri)
|
||||
elseif ev == 'create' then
|
||||
m.stopScopeDiag(uri)
|
||||
m.refresh(uri)
|
||||
m.refreshScopeDiag('OnSave', uri)
|
||||
elseif ev == 'update' then
|
||||
m.stopScopeDiag(uri)
|
||||
m.refresh(uri)
|
||||
m.refreshScopeDiag('OnChange', uri)
|
||||
elseif ev == 'open' then
|
||||
if ws.isReady(uri) then
|
||||
m.resendDiagnostic(uri)
|
||||
xpcall(m.doDiagnostic, log.error, uri)
|
||||
end
|
||||
elseif ev == 'close' then
|
||||
if files.isLibrary(uri, true)
|
||||
or ws.isIgnored(uri) then
|
||||
m.clear(uri)
|
||||
end
|
||||
elseif ev == 'save' then
|
||||
m.refreshScopeDiag('OnSave', uri)
|
||||
end
|
||||
end)
|
||||
|
||||
config.watch(function (uri, key, value, oldValue)
|
||||
if util.stringStartWith(key, 'Lua.diagnostics')
|
||||
or util.stringStartWith(key, 'Lua.spell')
|
||||
or util.stringStartWith(key, 'Lua.doc') then
|
||||
if value ~= oldValue then
|
||||
m.diagnosticsScope(uri)
|
||||
m.refreshClient()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
fw.event(function (_ev, path)
|
||||
if util.stringEndWith(path, '.editorconfig') then
|
||||
for _, scp in ipairs(ws.folders) do
|
||||
m.diagnosticsScope(scp.uri)
|
||||
m.refreshClient()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
return m
|
||||
Reference in New Issue
Block a user