diff options
Diffstat (limited to 'server/src')
-rw-r--r-- | server/src/matcher/diagnostics.lua | 49 | ||||
-rw-r--r-- | server/src/matcher/init.lua | 1 | ||||
-rw-r--r-- | server/src/service.lua | 88 |
3 files changed, 119 insertions, 19 deletions
diff --git a/server/src/matcher/diagnostics.lua b/server/src/matcher/diagnostics.lua new file mode 100644 index 00000000..9cd4f6ee --- /dev/null +++ b/server/src/matcher/diagnostics.lua @@ -0,0 +1,49 @@ +local DiagnosticSeverity = { + Error = 1, + Warning = 2, + Information = 3, + Hint = 4, +} + +--[[ +/** + * Represents a related message and source code location for a diagnostic. This should be + * used to point to code locations that cause or related to a diagnostics, e.g when duplicating + * a symbol in a scope. + */ +export interface DiagnosticRelatedInformation { + /** + * The location of this related diagnostic information. + */ + location: Location; + + /** + * The message of this related diagnostic information. + */ + message: string; +} +]]-- + +return function (ast, results) + local diagnostics = {} + + diagnostics[1] = { + range = { + start = { + line = 0, + character = 0, + }, + ['end'] = { + line = 0, + character = 10, + }, + }, + severity = DiagnosticSeverity.Warning, + code = 'I am code', + source = 'I am source', + message = 'I am message', + relatedInformation = nil, + } + + return diagnostics +end diff --git a/server/src/matcher/init.lua b/server/src/matcher/init.lua index 99149582..cacef3e5 100644 --- a/server/src/matcher/init.lua +++ b/server/src/matcher/init.lua @@ -4,6 +4,7 @@ local api = { references = require 'matcher.references', rename = require 'matcher.rename', hover = require 'matcher.hover', + diagnostics = require 'matcher.diagnostics', compile = require 'matcher.compile', } diff --git a/server/src/service.lua b/server/src/service.lua index e6515fa5..12ae140b 100644 --- a/server/src/service.lua +++ b/server/src/service.lua @@ -34,21 +34,27 @@ function mt:_callMethod(name, params) local f = method[name] if f then local clock = os.clock() - local suc, res, res2 = pcall(f, self, params) + local suc, res = xpcall(f, log.error, self, params) local passed = os.clock() - clock if passed > 0.01 then log.debug(('Task [%s] takes [%.3f]sec.'):format(name, passed)) end if suc then - return res, res2 + return res else - return nil, 'Runtime error: ' .. res + return nil, { + code = ErrorCodes.InternalError, + message = res, + } end end if optional then - return false + return nil else - return nil, 'Undefined method: ' .. name + return nil, { + code = ErrorCodes.MethodNotFound, + message = 'MethodNotFound', + } end end @@ -64,18 +70,50 @@ function mt:_doProto(proto) local method = proto.method local params = proto.params local response, err = self:_callMethod(method, params) + if not id then + return + end local proto = json.table() proto.id = id - proto.result = response + if err then + proto.error = err + else + proto.result = response + end self:_send(proto) end +function mt:_doDiagnostic() + if not next(self._needDiagnostics) then + return + end + local copy = {} + for uri, data in pairs(self._needDiagnostics) do + copy[uri] = data + self._needDiagnostics[uri] = nil + end + for uri, data in pairs(copy) do + local ast = data.ast + local results = data.results + local suc, res = xpcall(matcher.diagnostics, log.error, ast, results) + if suc then + self:_send { + method = 'textDocument/publishDiagnostics', + params = { + uri = uri, + diagnostics = res, + }, + } + end + end +end + function mt:_buildTextCache() - if not next(self._need_compile) then + if not next(self._needCompile) then return end local list = {} - for uri in pairs(self._need_compile) do + for uri in pairs(self._needCompile) do list[#list+1] = uri end @@ -123,13 +161,13 @@ function mt:saveText(uri, version, text) end obj.version = version obj.text = text - self._need_compile[uri] = true + self._needCompile[uri] = true else self._file[uri] = { version = version, text = text, } - self._need_compile[uri] = true + self._needCompile[uri] = true end end @@ -147,30 +185,41 @@ function mt:compileText(uri) if not obj then return nil end - if not self._need_compile[uri] then + if not self._needCompile[uri] then return nil end - self._need_compile[uri] = nil - local ast = parser:ast(obj.text) + self._needCompile[uri] = nil + local ast = parser:ast(obj.text) obj.results = matcher.compile(ast) - obj.lines = parser:lines(obj.text) + if not obj.results then + return obj + end + obj.lines = parser:lines(obj.text) + + self._needDiagnostics[uri] = { + ast = ast, + results = obj.results, + } + return obj end function mt:removeText(uri) self._file[uri] = nil - self._need_compile[uri] = nil + self._needCompile[uri] = nil end function mt:on_tick() local proto = thread.proto() if proto then - self._idle_clock = os.clock() + self._idleClock = os.clock() self:_doProto(proto) return end - if os.clock() - self._idle_clock >= 1 then + if os.clock() - self._idleClock >= 0.2 then + self._idleClock = os.clock() self:_buildTextCache() + self:_doDiagnostic() end end @@ -192,8 +241,9 @@ end return function () local session = setmetatable({ _file = {}, - _need_compile = {}, - _idle_clock = os.clock(), + _needCompile = {}, + _needDiagnostics = {}, + _idleClock = os.clock(), }, mt) return session end |