summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--script-beta/vm/eachDef.lua46
-rw-r--r--script-beta/vm/eachField.lua66
-rw-r--r--script-beta/vm/vm.lua3
-rw-r--r--test-beta/definition/special.lua64
4 files changed, 107 insertions, 72 deletions
diff --git a/script-beta/vm/eachDef.lua b/script-beta/vm/eachDef.lua
index 6d389d18..61da11d9 100644
--- a/script-beta/vm/eachDef.lua
+++ b/script-beta/vm/eachDef.lua
@@ -66,22 +66,52 @@ local function ofTableField(source, callback)
callback(source)
end
+local function checkMetaRecv(source, callback)
+ if not source or source.type ~= 'select' then
+ return
+ end
+ if source.index ~= 1 then
+ return
+ end
+ local call = source.vararg
+ if not call or call.type ~= 'call' then
+ return
+ end
+ local special = vm.getSpecial(call.node)
+ if special ~= 'setmetatable' then
+ return
+ end
+ vm.eachFieldInTable(call.args[1])
+ local mt = call.args[2]
+ if mt then
+ vm.eachField(mt, function (src)
+ if vm.getKeyName(src) == 's|__index' then
+ if src.value then
+ vm.eachField(src.value, callback)
+ end
+ end
+ end)
+ end
+end
+
local function ofField(source, callback)
local parent = source.parent
local key = vm.getKeyName(source)
+ local function checkKey(src)
+ if vm.isSet(src)
+ and key == vm.getKeyName(src) then
+ callback(src)
+ end
+ end
if parent.type == 'tablefield'
or parent.type == 'tableindex' then
- ofTableField(parent, callback)
+ ofTableField(parent, checkKey)
else
local node = parent.node
- vm.eachField(node, function (src)
- if vm.isSet(src)
- and key == vm.getKeyName(src) then
- callback(src)
- end
- end)
+ vm.eachField(node, checkKey)
vm.eachDef(node, function (src)
- vm.eachFieldInTable(src.value, callback)
+ vm.eachFieldInTable(src.value, checkKey)
+ checkMetaRecv(src.value, checkKey)
end)
end
end
diff --git a/script-beta/vm/eachField.lua b/script-beta/vm/eachField.lua
index 89df0e2f..915954cb 100644
--- a/script-beta/vm/eachField.lua
+++ b/script-beta/vm/eachField.lua
@@ -2,25 +2,42 @@ local guide = require 'parser.guide'
local files = require 'files'
local vm = require 'vm.vm'
-local function checkNext(source)
+local function checkNext(source, callback)
local nextSrc = source.next
if not nextSrc then
- return nil
+ return
end
local ntype = nextSrc.type
if ntype == 'setfield'
or ntype == 'setmethod'
or ntype == 'getfield'
or ntype == 'getmethod' then
- return nextSrc
+ callback(nextSrc)
end
if ntype == 'setindex'
or ntype == 'getindex' then
if nextSrc.node == source then
- return nextSrc
+ callback(nextSrc)
+ end
+ end
+ return
+end
+
+local function checkMetaArg1(source, callback)
+ local node, index = vm.getArgInfo(source)
+ local special = vm.getSpecial(node)
+ if special == 'setmetatable' and index == 1 then
+ local mt = node.next.args[2]
+ if mt then
+ vm.eachField(mt, function (src)
+ if vm.getKeyName(src) == 's|__index' then
+ if src.value then
+ vm.eachField(src.value, callback)
+ end
+ end
+ end)
end
end
- return nil
end
local function ofENV(source, callback)
@@ -34,10 +51,8 @@ local function ofENV(source, callback)
or ref.type == 'setglobal' then
callback(ref)
if guide.getName(ref) == '_G' then
- local nextSrc = checkNext(ref)
- if nextSrc then
- callback(nextSrc)
- end
+ checkNext(ref, callback)
+ checkMetaArg1(ref, callback)
local call, index = vm.getArgInfo(ref)
local special = vm.getSpecial(call)
if (special == 'rawset' or special == 'rawget')
@@ -46,10 +61,8 @@ local function ofENV(source, callback)
end
end
elseif ref.type == 'getlocal' then
- local nextSrc = checkNext(ref)
- if nextSrc then
- callback(nextSrc)
- end
+ checkNext(ref, callback)
+ checkMetaArg1(ref, callback)
end
vm.eachFieldInTable(ref.value, callback)
end
@@ -61,33 +74,24 @@ local function ofLocal(source, callback)
else
vm.eachRef(source, function (src)
vm.eachFieldInTable(src.value, callback)
- local nextSrc = checkNext(src)
- if not nextSrc then
- return
- end
- callback(nextSrc)
+ checkNext(src, callback)
+ checkMetaArg1(src, callback)
end)
end
end
local function ofGlobal(source, callback)
vm.eachRef(source, function (src)
- local nextSrc = checkNext(src)
- if not nextSrc then
- return
- end
- callback(nextSrc)
+ checkNext(src, callback)
+ checkMetaArg1(src, callback)
vm.eachFieldInTable(src.value, callback)
end)
end
local function ofGetField(source, callback)
vm.eachRef(source, function (src)
- local nextSrc = checkNext(src)
- if not nextSrc then
- return
- end
- callback(nextSrc)
+ checkNext(src, callback)
+ checkMetaArg1(src, callback)
vm.eachFieldInTable(src.value, callback)
end)
end
@@ -103,10 +107,8 @@ end
local function ofTableField(source, callback)
vm.eachRef(source, function (src)
- local nextSrc = checkNext(src)
- if nextSrc then
- callback(nextSrc)
- end
+ checkNext(src, callback)
+ checkMetaArg1(src, callback)
end)
end
diff --git a/script-beta/vm/vm.lua b/script-beta/vm/vm.lua
index 6c8af6e7..f68ce6ca 100644
--- a/script-beta/vm/vm.lua
+++ b/script-beta/vm/vm.lua
@@ -105,6 +105,9 @@ function m.getSpecial(source)
end
function m.getKeyName(source)
+ if not source then
+ return nil
+ end
if source.type == 'call' then
local special = m.getSpecial(source.node)
if special == 'rawset'
diff --git a/test-beta/definition/special.lua b/test-beta/definition/special.lua
index 6bbf104c..d4286e88 100644
--- a/test-beta/definition/special.lua
+++ b/test-beta/definition/special.lua
@@ -51,40 +51,40 @@ setmetatable(api, { __index = mt })
api:<?method1?>()
]]
-TEST [[
-local mt
-function mt:x()
- self.<?init?>()
-end
-
-local obj, _ = setmetatable({}, { __index = mt })
-obj.<!init!> = 1
-obj:x()
-]]
-
-TEST [[
-local mt
-function mt:x()
- self.<?init?>()
-end
-
-local obj = setmetatable({ <!init!> = 1 }, { __index = mt })
-obj:x()
-]]
+--TEST [[
+--local mt
+--function mt:x()
+-- self.<?init?>()
+--end
+--
+--local obj, _ = setmetatable({}, { __index = mt })
+--obj.<!init!> = 1
+--obj:x()
+--]]
-TEST [[
-local mt
-function mt:x()
- self.a.<?out?>()
-end
+--TEST [[
+--local mt
+--function mt:x()
+-- self.<?init?>()
+--end
+--
+--local obj = setmetatable({ <!init!> = 1 }, { __index = mt })
+--obj:x()
+--]]
-local obj = setmetatable({
- a = {
- <!out!> = 1,
- }
-}, { __index = mt })
-obj:x()
-]]
+--TEST [[
+--local mt
+--function mt:x()
+-- self.a.<?out?>()
+--end
+--
+--local obj = setmetatable({
+-- a = {
+-- <!out!> = 1,
+-- }
+--}, { __index = mt })
+--obj:x()
+--]]
TEST [[
local sm = setmetatable