diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2019-03-01 17:57:08 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2019-03-01 17:57:08 +0800 |
commit | f6570295633065a319e695211c05cddc71c1c4a6 (patch) | |
tree | a9f36cc8cf3d2e2a52bf46cbdbf932c567b44a21 /server | |
parent | 1113d28c032be9ef216e23f35c10ed751296601f (diff) | |
download | lua-language-server-f6570295633065a319e695211c05cddc71c1c4a6.zip |
未定义全局变量
Diffstat (limited to 'server')
-rw-r--r-- | server/src/core/diagnostics.lua | 149 | ||||
-rw-r--r-- | server/src/vm/local.lua | 9 | ||||
-rw-r--r-- | server/src/vm/source.lua | 22 | ||||
-rw-r--r-- | server/src/vm/vm.lua | 34 | ||||
-rw-r--r-- | server/test/diagnostics/init.lua | 11 |
5 files changed, 136 insertions, 89 deletions
diff --git a/server/src/core/diagnostics.lua b/server/src/core/diagnostics.lua index 068ad37b..e2c7c5ec 100644 --- a/server/src/core/diagnostics.lua +++ b/server/src/core/diagnostics.lua @@ -12,67 +12,65 @@ local mt = {} mt.__index = mt function mt:searchUnusedLocals(callback) - local results = self.results - for _, var in ipairs(results.locals) do - if var.key == '_' - or var.key == '_ENV' - or var.key == '' - then - goto NEXT_VAR + self.vm:eachSource(function (source) + local loc = source:bindLocal() + if not loc then + return end - if var.hide then - goto NEXT_VAR + local name = loc:getName() + if name == '_' or name == '_ENV' or name == '' then + return end - local ok = self.vm:eachInfo(var, function (info) + if source:action() ~= 'local' then + return + end + if loc:getFlag 'hide' then + return + end + local used = loc:eachInfo(function (info) if info.type == 'get' then return true end - if info.type == 'local' then - if info.source.start == 0 then - return true - end - end end) - if ok then - goto NEXT_VAR + if not used then + callback(source.start, source.finish, name) end - callback(var.source.start, var.source.finish, var.key) - ::NEXT_VAR:: - end + end) end function mt:searchUndefinedGlobal(callback) - local globalValue = self.vm.lsp.globalValue - globalValue:eachField(function (index, field) - if field.value.lib then - goto NEXT_VAR + self.vm:eachSource(function (source) + if not source:getFlag 'global' then + return end - if not field.uris[self.vm.uri] then - goto NEXT_VAR + local value = source:bindValue() + if not value then + return end - if type(index) ~= 'string' then - goto NEXT_VAR + if source:action() ~= 'get' then + return end - if config.config.diagnostics.globals[index] then - goto NEXT_VAR + if value:getLib() then + return end - if index == '' then - goto NEXT_VAR + local name = source:getName() + if name == '' then + return + end + if type(name) ~= 'string' then + return + end + if config.config.diagnostics.globals[name] then + return end - local ok = field.value:eachInfo(function (info) + local defined = value:eachInfo(function (info) if info.type == 'set' then return true end end) - if ok then - goto NEXT_VAR + if not defined then + callback(source.start, source.finish, name) end - self.vm:eachInfo(field, function (info) - if info.type == 'get' then - callback(info.source.start, info.source.finish, tostring(index)) - end - end) - ::NEXT_VAR:: end) end @@ -229,7 +227,7 @@ function mt:doDiagnostics(func, code, callback) if config.config.diagnostics.disable[code] then return end - self[func](self, function (start, finish, ...) + func(self, function (start, finish, ...) local data = callback(...) data.code = code data.start = start @@ -244,61 +242,60 @@ end return function (vm, lines, uri) local session = setmetatable({ vm = vm, - results = vm.results, lines = lines, uri = uri, datas = {}, }, mt) -- 未使用的局部变量 - session:doDiagnostics('searchUnusedLocals', 'unused-local', function (key) + session:doDiagnostics(session.searchUnusedLocals, 'unused-local', function (key) return { level = DiagnosticSeverity.Information, message = lang.script('DIAG_UNUSED_LOCAL', key), } end) -- 读取未定义全局变量 - session:doDiagnostics('searchUndefinedGlobal', 'undefined-global', function (key) + session:doDiagnostics(session.searchUndefinedGlobal, 'undefined-global', function (key) return { level = DiagnosticSeverity.Warning, message = lang.script('DIAG_UNDEFINED_GLOBAL', key), } end) -- 未使用的Label - session:doDiagnostics('searchUnusedLabel', 'unused-label', function (key) - return { - level =DiagnosticSeverity.Hint, - message = lang.script('DIAG_UNUSED_LABEL', key) - } - end) + --session:doDiagnostics(session.searchUnusedLabel, 'unused-label', function --(key) + -- return { + -- level =DiagnosticSeverity.Hint, + -- message = lang.script('DIAG_UNUSED_LABEL', key) + -- } + --end) -- 只有空格与制表符的行,以及后置空格 - session:doDiagnostics('searchSpaces', 'trailing-space', function (message) - return { - level = DiagnosticSeverity.Hint, - message = message, - } - end) + --session:doDiagnostics(session.searchSpaces, 'trailing-space', function --(message) + -- return { + -- level = DiagnosticSeverity.Hint, + -- message = message, + -- } + --end) -- 重定义局部变量 - session:doDiagnostics('searchRedefinition', 'redefined-local', function (key, related) - return { - level = DiagnosticSeverity.Information, - message = lang.script('DIAG_REDEFINED_LOCAL', key), - related = related, - } - end) + --session:doDiagnostics(session.searchRedefinition, 'redefined-local', --function (key, related) + -- return { + -- level = DiagnosticSeverity.Information, + -- message = lang.script('DIAG_REDEFINED_LOCAL', key), + -- related = related, + -- } + --end) -- 以括号开始的一行(可能被误解析为了上一行的call) - session:doDiagnostics('searchNewLineCall', 'newline-call', function () - return { - level = DiagnosticSeverity.Information, - message = lang.script.DIAG_PREVIOUS_CALL, - } - end) + --session:doDiagnostics(session.searchNewLineCall, 'newline-call', function () + -- return { + -- level = DiagnosticSeverity.Information, + -- message = lang.script.DIAG_PREVIOUS_CALL, + -- } + --end) -- 调用函数时的参数数量是否超过函数的接收数量 - session:doDiagnostics('searchRedundantParameters', 'remainder-parameters', function (max, passed) - return { - level = DiagnosticSeverity.Information, - message = lang.script('DIAG_OVER_MAX_ARGS', max, passed), - } - end) + --session:doDiagnostics(session.searchRedundantParameters, --'remainder-parameters', function (max, passed) + -- return { + -- level = DiagnosticSeverity.Information, + -- message = lang.script('DIAG_OVER_MAX_ARGS', max, passed), + -- } + --end) return session.datas end diff --git a/server/src/vm/local.lua b/server/src/vm/local.lua index f1c33ecf..75f41db2 100644 --- a/server/src/vm/local.lua +++ b/server/src/vm/local.lua @@ -31,7 +31,10 @@ end function mt:eachInfo(callback) for _, info in ipairs(self) do - callback(info) + local res = callback(info) + if res ~= nil then + return res + end end end @@ -49,6 +52,10 @@ function mt:getFlag(name) return self._flag[name] end +function mt:getName() + return self.name +end + return function (name, source, value) if not value then error('Local must has a value') diff --git a/server/src/vm/source.lua b/server/src/vm/source.lua index 5406298b..6685b95f 100644 --- a/server/src/vm/source.lua +++ b/server/src/vm/source.lua @@ -2,9 +2,11 @@ local mt = {} mt.__index = mt mt._hasInstant = true -function mt:bindLocal(loc) +function mt:bindLocal(loc, action) if loc then self._bindLocal = loc + self._action = action + loc:addInfo(action, self) else return self._bindLocal end @@ -50,6 +52,24 @@ function mt:getUri() return self._uri end +function mt:setFlag(name, v) + if not self._flag then + self._flag = {} + end + self._flag[name] = v +end + +function mt:getFlag(name) + if not self._flag then + return nil + end + return self._flag[name] +end + +function mt:getName() + return self[1] +end + return function (source) if source._hasInstant then return false diff --git a/server/src/vm/vm.lua b/server/src/vm/vm.lua index 1a892100..64419d72 100644 --- a/server/src/vm/vm.lua +++ b/server/src/vm/vm.lua @@ -350,12 +350,18 @@ function mt:getName(name, source) end local loc = self:loadLocal(name) if loc then - source:bindLocal(loc) + source:bindLocal(loc, 'get') return loc:getValue() end + local global = source:bindValue() + if global then + return global + end + source:setFlag('global', true) local ENV = self:loadLocal('_ENV') local ENVValue = ENV:getValue() - local global = ENVValue:getChild(name) or ENVValue:setChild(name, createValue('any', source)) + global = ENVValue:getChild(name) or ENVValue:setChild(name, createValue('any', source)) + source:bindValue(global, 'get') return global end @@ -363,10 +369,16 @@ function mt:setName(name, source, value) self:instantSource(source) local loc = self:loadLocal(name) if loc then - source:bindLocal(loc) + source:bindLocal(loc, 'set') loc:setValue(value) return end + local global = source:bindValue() + if global then + return global + end + source:setFlag('global', true) + source:bindValue(global, 'set') local ENV = self:loadLocal('_ENV') local ENVValue = ENV:getValue() ENVValue:setChild(name, value) @@ -1031,13 +1043,13 @@ function mt:instantSource(source) end end -function mt:bindLocal(source, loc) +function mt:bindLocal(source, loc, action) if not source then return end self:instantSource(source) if loc then - source:bindLocal(loc) + source:bindLocal(loc, action) else return source:bindLocal() end @@ -1065,7 +1077,7 @@ function mt:createLocal(key, source, value) loc = createLocal(key, source, value) self:saveLocal(key, loc) - self:bindLocal(source, loc) + self:bindLocal(source, loc, 'local') return loc end @@ -1081,6 +1093,13 @@ function mt:createEnvironment(ast) self.env = env end +function mt:eachSource(callback) + local sources = self.sources + for i = 1, #sources do + callback(sources[i]) + end +end + local function compile(ast, lsp, uri) local vm = setmetatable({ funcs = {}, @@ -1099,9 +1118,6 @@ local function compile(ast, lsp, uri) -- 检查所有没有调用过的函数,调用一遍 vm:callLeftFuncions() - vm.scope = nil - vm.chunk = nil - return vm end diff --git a/server/test/diagnostics/init.lua b/server/test/diagnostics/init.lua index 9ab41aed..e8d483ed 100644 --- a/server/test/diagnostics/init.lua +++ b/server/test/diagnostics/init.lua @@ -1,4 +1,5 @@ local core = require 'core' +local buildVM = require 'vm' local parser = require 'parser' local service = require 'service' @@ -43,7 +44,7 @@ function TEST(script) local ast = parser:ast(new_script) assert(ast) local lines = parser:lines(new_script) - local vm = core.vm(ast, lsp) + local vm = buildVM(ast, lsp) assert(vm) local datas = core.diagnostics(vm, lines, 'test') local results = {} @@ -71,7 +72,7 @@ print(<!X!>) print(<!Log!>) print(_VERSION) print(<!y!>) -print(z) +print(<!z!>) z = 1 ]] @@ -154,6 +155,12 @@ end ]] TEST [[ +local mt = {} +function mt:f() +end +]] + +TEST [[ local function f(<!self!>) end f() |