diff options
author | sumneko <sumneko@hotmail.com> | 2019-04-18 16:32:36 +0800 |
---|---|---|
committer | sumneko <sumneko@hotmail.com> | 2019-04-18 16:32:36 +0800 |
commit | f077aa010aa2ae0a2cc6edbc345eaf4056b96e2b (patch) | |
tree | c45f7cf10a5fed43afc0a93eb9106961c67b931c | |
parent | cc8fc15d26a1dfd2f30485ba21f2f313141932d0 (diff) | |
download | lua-language-server-f077aa010aa2ae0a2cc6edbc345eaf4056b96e2b.zip |
class的一些诊断
-rw-r--r-- | server/src/core/diagnostics.lua | 117 | ||||
-rw-r--r-- | server/src/emmy/class.lua | 18 | ||||
-rw-r--r-- | server/src/emmy/manager.lua | 17 | ||||
-rw-r--r-- | server/src/method/textDocument/completion.lua | 2 | ||||
-rw-r--r-- | server/src/parser/ast.lua | 2 | ||||
-rw-r--r-- | server/src/vm/emmy.lua | 12 | ||||
-rw-r--r-- | server/test/diagnostics/init.lua | 23 |
7 files changed, 152 insertions, 39 deletions
diff --git a/server/src/core/diagnostics.lua b/server/src/core/diagnostics.lua index 73f8c8ce..33037d5f 100644 --- a/server/src/core/diagnostics.lua +++ b/server/src/core/diagnostics.lua @@ -374,26 +374,6 @@ function mt:searchRedundantValue(callback) end) end -function mt:doDiagnostics(func, code, callback) - if config.config.diagnostics.disable[code] then - return - end - func(self, function (start, finish, ...) - local data = callback(...) - data.code = code - data.start = start - data.finish = finish - self.datas[#self.datas+1] = data - end) - if coroutine.isyieldable() then - if self.vm:isRemoved() then - coroutine.yield('stop') - else - coroutine.yield() - end - end -end - function mt:searchUndefinedEnvChild(callback) self.vm:eachSource(function (source) if not source:get 'global' then @@ -421,6 +401,95 @@ function mt:searchUndefinedEnvChild(callback) end) end +function mt:checkEmmyClass(source, callback) + local class = source:get 'emmy.class' + if not class then + return + end + -- class重复定义 + local name = class:getName() + local related = {} + self.vm.emmyMgr:eachClass(name, function (class) + local src = class:getSource() + if src ~= source then + related[#related+1] = { + start = src.start, + finish = src.finish, + uri = src.uri, + } + end + end) + if #related > 0 then + callback(source.start, source.finish, lang.script.DIAG_DUPLICATE_CLASS ,related) + end + -- 继承不存在的class + local extends = class.extends + if not extends then + return + end + local parent = self.vm.emmyMgr:eachClass(extends, function (parent) + return parent + end) + if not parent then + callback(source[2].start, source[2].finish, lang.script.DIAG_UNDEFINED_CLASS) + return + end + + -- class循环继承 + local related = {} + local current = class + for _ = 1, 10 do + if parent:getName() == class:getName() then + callback(source.start, source.finish, lang.script.DIAG_CYCLIC_EXTENDS, related) + break + end + local extends = current.extends + if not extends then + break + end + related[#related+1] = { + start = current:getSource().start, + finish = current:getSource().finish, + uri = current:getSource().uri, + } + current = parent + parent = self.vm.emmyMgr:eachClass(extends, function (parent) + return parent + end) + if not parent then + break + end + end +end + +function mt:searchEmmyLua(callback) + self.vm:eachSource(function (source) + if source.type == 'emmyClass' then + self:checkEmmyClass(source, callback) + end + end) +end + +function mt:doDiagnostics(func, code, callback) + if config.config.diagnostics.disable[code] then + return + end + func(self, function (start, finish, ...) + local data = callback(...) + data.code = code + data.start = start + data.finish = finish + self.datas[#self.datas+1] = data + end) + if coroutine.isyieldable() then + if self.vm:isRemoved() then + coroutine.yield('stop') + else + coroutine.yield() + end + end +end + return function (vm, lines, uri) local session = setmetatable({ vm = vm, @@ -538,5 +607,13 @@ return function (vm, lines, uri) message = lang.script('DIAG_OVER_MAX_VALUES', max, passed), } end) + -- Emmy相关的检查 + session:doDiagnostics(session.searchEmmyLua, 'emmy-lua', function (message, related) + return { + level = DiagnosticSeverity.Warning, + message = message, + related = related, + } + end) return session.datas end diff --git a/server/src/emmy/class.lua b/server/src/emmy/class.lua index 33a01be2..f1101e91 100644 --- a/server/src/emmy/class.lua +++ b/server/src/emmy/class.lua @@ -1,3 +1,5 @@ +local listMgr = require 'vm.list' + local mt = {} mt.__index = mt mt.type = 'emmy.class' @@ -6,11 +8,19 @@ function mt:getType() return self.name end -return function (class, parent) +function mt:getName() + return self.name +end + +function mt:getSource() + return listMgr.get(self.source) +end + +return function (source) local self = setmetatable({ - name = class[1], - source = class.id, - parent = parent and parent.id, + name = source[1][1], + source = source.id, + extends = source[2] and source[2][1], }, mt) return self end diff --git a/server/src/emmy/manager.lua b/server/src/emmy/manager.lua index 8ca102ca..99b46420 100644 --- a/server/src/emmy/manager.lua +++ b/server/src/emmy/manager.lua @@ -32,13 +32,18 @@ function mt:eachClass(name, callback) if not list then return end - for _, class in pairs(list) do - callback(class) + for k, class in pairs(list) do + if k ~= 'version' then + local res = callback(class) + if res ~= nil then + return res + end + end end end -function mt:addClass(class, parent) - local className = class[1] +function mt:addClass(source) + local className = source[1][1] self:flushClass(className) local list = self._class[className] local version = listMgr.getVersion() @@ -48,8 +53,8 @@ function mt:addClass(class, parent) } self._class[className] = list end - list[class.id] = newClass(class, parent) - return list[class.id] + list[source.id] = newClass(source) + return list[source.id] end function mt:remove() diff --git a/server/src/method/textDocument/completion.lua b/server/src/method/textDocument/completion.lua index 2f638979..7f60708b 100644 --- a/server/src/method/textDocument/completion.lua +++ b/server/src/method/textDocument/completion.lua @@ -121,7 +121,7 @@ return function (lsp, params) local items = fastCompletion(lsp, params, lines) --local items = finishCompletion(lsp, params, lines) if not items then - return + return nil end for i, item in ipairs(items) do diff --git a/server/src/parser/ast.lua b/server/src/parser/ast.lua index 7ac3db06..3078631d 100644 --- a/server/src/parser/ast.lua +++ b/server/src/parser/ast.lua @@ -1115,6 +1115,8 @@ local Defs = { EmmyClass = function (class, extends) return { type = 'emmyClass', + start = class.start, + finish = (extends or class).finish, [1] = class, [2] = extends, } diff --git a/server/src/vm/emmy.lua b/server/src/vm/emmy.lua index 4ab42c93..b2f38693 100644 --- a/server/src/vm/emmy.lua +++ b/server/src/vm/emmy.lua @@ -2,14 +2,10 @@ local mt = require 'vm.manager' function mt:doEmmyClass(action) local emmyMgr = self.emmyMgr - local class = action[1] - local parent = action[2] - self:instantSource(class) - if parent then - self:instantSource(parent) - end - local emmyClass = emmyMgr:addClass(class, parent) - self.emmy = emmyClass + self:instantSource(action) + local class = emmyMgr:addClass(action) + self.emmy = class + action:set('emmy.class', class) end function mt:doEmmyIncomplete(action) diff --git a/server/test/diagnostics/init.lua b/server/test/diagnostics/init.lua index 557a2475..7bb25f00 100644 --- a/server/test/diagnostics/init.lua +++ b/server/test/diagnostics/init.lua @@ -332,3 +332,26 @@ local function x() print(loc) end ]] + +TEST [[ +---@class <!Class!> +---@class <!Class!> +]] + +TEST [[ +---@class A : <!B!> +]] + +TEST [[ +---@class <!A : B!> +---@class <!B : C!> +---@class <!C : D!> +---@class <!D : A!> +]] + +TEST [[ +---@class A : B +---@class B : C +---@class C : D +---@class D +]] |