summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/src/matcher/diagnostics.lua42
-rw-r--r--server/src/matcher/vm.lua19
-rw-r--r--server/test/diagnostics/init.lua116
-rw-r--r--server/test/main.lua1
4 files changed, 151 insertions, 27 deletions
diff --git a/server/src/matcher/diagnostics.lua b/server/src/matcher/diagnostics.lua
index 814beaa2..e896e4b5 100644
--- a/server/src/matcher/diagnostics.lua
+++ b/server/src/matcher/diagnostics.lua
@@ -1,10 +1,7 @@
local findLib = require 'matcher.find_lib'
local function searchUnusedLocals(results, callback)
- for _, var in ipairs(results.vars) do
- if var.type ~= 'local' then
- goto NEXT_VAR
- end
+ for _, var in ipairs(results.locals) do
if var.key == 'self'
or var.key == '_'
or var.key == '_ENV'
@@ -22,33 +19,27 @@ local function searchUnusedLocals(results, callback)
end
local function searchUndefinedGlobal(results, callback)
- for _, var in ipairs(results.vars) do
- if var.type ~= 'field' then
- goto NEXT_VAR
- end
- if var.parent.key ~= '_ENV'
- and var.parent.key ~= '_G'
- then
- goto NEXT_VAR
- end
- if var.key:lower() == 'log' then
- goto NEXT_VAR
- end
- if not var.key:find '%l' then
+ local env = results.locals[1]
+ for index, field in pairs(env.value.child) do
+ if field.value.lib then
goto NEXT_VAR
end
- local lib = findLib(var)
- if lib then
- goto NEXT_VAR
+ if type(index) == 'string' then
+ if index:lower() == 'log' then
+ goto NEXT_VAR
+ end
+ if not index:find '%l' then
+ goto NEXT_VAR
+ end
end
- for _, info in ipairs(var) do
+ for _, info in ipairs(field) do
if info.type == 'set' then
goto NEXT_VAR
end
end
- for _, info in ipairs(var) do
+ for _, info in ipairs(field) do
if info.type == 'get' then
- callback(info.source.start, info.source.finish, var.key)
+ callback(info.source.start, info.source.finish, tostring(index))
end
end
::NEXT_VAR::
@@ -92,10 +83,7 @@ local function serachSpaces(lines, callback)
end
local function searchRedefinition(results, uri, callback)
- for _, var in ipairs(results.vars) do
- if var.type ~= 'local' then
- goto NEXT_VAR
- end
+ for _, var in ipairs(results.locals) do
if var.key == '_'
or var.key == '_ENV'
then
diff --git a/server/src/matcher/vm.lua b/server/src/matcher/vm.lua
index 3264bd18..2339f769 100644
--- a/server/src/matcher/vm.lua
+++ b/server/src/matcher/vm.lua
@@ -12,6 +12,20 @@ function mt:createLocal(key, source, value)
key = key,
source = source or DefaultSource,
}
+
+ local shadow = self.scope.locals[key]
+ if shadow then
+ local group
+ if shadow.shadow then
+ group = shadow.shadow
+ else
+ group = { shadow }
+ shadow.shadow = group
+ end
+ group[#group+1] = loc
+ loc.shadow = group
+ end
+
self.scope.locals[key] = loc
self.results.locals[#self.results.locals+1] = loc
@@ -458,6 +472,10 @@ function mt:getSimple(simple, mode)
if i < #simple then
value = value[1] or self:createValue('nil')
end
+ self.results.calls[#self.results.calls+1] = {
+ call = obj,
+ lastobj = simple[i-1],
+ }
elseif obj.index then
local index = self:getIndex(obj)
field = self:getField(value, index, obj)
@@ -819,6 +837,7 @@ local function compile(ast)
fields = {},
labels = {},
funcs = {},
+ calls = {},
},
}, mt)
diff --git a/server/test/diagnostics/init.lua b/server/test/diagnostics/init.lua
new file mode 100644
index 00000000..fb188318
--- /dev/null
+++ b/server/test/diagnostics/init.lua
@@ -0,0 +1,116 @@
+local matcher = require 'matcher'
+local parser = require 'parser'
+
+rawset(_G, 'TEST', true)
+
+local function catch_target(script)
+ local list = {}
+ local cur = 1
+ local cut = 0
+ while true do
+ local start, finish = script:find('<!.-!>', cur)
+ if not start then
+ break
+ end
+ list[#list+1] = { start - cut, finish - 4 - cut }
+ cur = finish + 1
+ cut = cut + 4
+ end
+ local new_script = script:gsub('<!(.-)!>', '%1')
+ return new_script, list
+end
+
+local function founded(targets, results)
+ if #targets ~= #results then
+ return false
+ end
+ for _, target in ipairs(targets) do
+ for _, result in ipairs(results) do
+ if target[1] == result[1] and target[2] == result[2] then
+ goto NEXT
+ end
+ end
+ do return false end
+ ::NEXT::
+ end
+ return true
+end
+
+function TEST(script)
+ local new_script, target = catch_target(script)
+ local ast = parser:ast(new_script)
+ assert(ast)
+ local lines = parser:lines(new_script)
+ local vm = matcher.vm(ast)
+ assert(vm)
+ local datas = matcher.diagnostics(vm, lines, 'test')
+ local results = {}
+ for i, data in ipairs(datas) do
+ results[i] = { data.start, data.finish }
+ end
+
+ if results[1] then
+ if not founded(target, results) then
+ error(('%s\n%s'):format(table.dump(target), table.dump(results)))
+ end
+ else
+ assert(#target == 0)
+ end
+end
+
+TEST [[
+local <!x!>
+]]
+
+TEST [[
+print(<!x!>)
+print(log)
+print(X)
+print(Log)
+print(_VERSION)
+print(<!y!>)
+print(z)
+z = 1
+]]
+
+TEST [[
+::<!LABEL!>::
+]]
+
+TEST [[
+<! !>
+]]
+
+TEST [[
+x = 1<! !>
+]]
+
+TEST [[
+local <!x!>
+print(x)
+local <!x!>
+print(x)
+]]
+
+TEST [[
+local x
+print(x)
+local x
+print(x)
+local x
+print(x)
+]]
+
+TEST [[
+local _
+print(_)
+local _
+print(_)
+local _ENV
+print(_ENV)
+]]
+
+TEST [[
+print(_G)
+<!('string')!>:sub(1, 1)
+]]
diff --git a/server/test/main.lua b/server/test/main.lua
index 9e619b70..8e340157 100644
--- a/server/test/main.lua
+++ b/server/test/main.lua
@@ -26,6 +26,7 @@ local function main()
test 'vm'
--test 'type_inference'
test 'definition'
+ test 'diagnostics'
--test 'find_lib'
print('测试完成')