summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-02-18 17:38:08 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-02-18 17:38:08 +0800
commit5aff820786099d4f6abff93ae2ae6b60aa4d4432 (patch)
treeb5011cc721fbd41f77e29efba845273e4c24005f
parentcd40c6c9117dce31c3040271e79038e20376af6a (diff)
downloadlua-language-server-5aff820786099d4f6abff93ae2ae6b60aa4d4432.zip
update
-rw-r--r--script/vm/getDef.lua2
-rw-r--r--script/vm/node/compiler.lua81
-rw-r--r--script/vm/state.lua5
-rw-r--r--test/definition/table.lua9
4 files changed, 77 insertions, 20 deletions
diff --git a/script/vm/getDef.lua b/script/vm/getDef.lua
index a303f5f7..735a817e 100644
--- a/script/vm/getDef.lua
+++ b/script/vm/getDef.lua
@@ -89,7 +89,7 @@ local nodeMap;nodeMap = util.switch()
: case 'getfield'
: case 'setfield'
: call(function (source, pushResult)
- local node = compiler.compileNode(guide.getUri(source.node), source.node)
+ local node = compiler.compileNode(source.node)
if not node then
return
end
diff --git a/script/vm/node/compiler.lua b/script/vm/node/compiler.lua
index fefe4fb0..a9b77920 100644
--- a/script/vm/node/compiler.lua
+++ b/script/vm/node/compiler.lua
@@ -2,6 +2,7 @@ local guide = require 'parser.guide'
local util = require 'utility'
local state = require 'vm.state'
local union = require 'vm.node.union'
+local localID = require 'vm.local-id'
---@class parser.object
---@field _compiledNodes boolean
@@ -55,11 +56,11 @@ local function getReturnOfFunction(func, index)
}
end)
end
- return m.compileNode(guide.getUri(func), func._returns[index])
+ return m.compileNode(func._returns[index])
end
local function getReturn(func, index)
- local node = m.compileNode(guide.getUri(func), func)
+ local node = m.compileNode(func)
if not node then
return
end
@@ -77,63 +78,109 @@ local valueMap = util.switch()
: case 'number'
: case 'string'
: case 'function'
- : call(function (uri, source, value)
- state.declareLiteral(uri, value)
+ : call(function (source, value)
+ state.declareLiteral(value)
m.setNode(source, value)
end)
: case 'call'
- : call(function (uri, source, value)
+ : call(function (source, value)
m.setNode(source, getReturn(value.node, 1))
end)
: getMap()
-local function compileValue(uri, source, value)
+local function compileValue(source, value)
if not value then
return
end
local f = valueMap[value.type]
if f then
- f(uri, source, value)
+ f(source, value)
+ end
+end
+
+local function compileByLocalID(source)
+ local sources = localID.getSources(source)
+ if not sources then
+ return
+ end
+ for _, src in ipairs(sources) do
+ if src.value then
+ compileValue(source, src.value)
+ end
+ end
+end
+
+local searchFieldMap = util.switch()
+ : case 'table'
+ : call(function (node, key, pushResult)
+ for _, field in ipairs(node) do
+ if field.type == 'tablefield'
+ or field.type == 'tableindex' then
+ if guide.getKeyName(field) == key then
+ pushResult(field)
+ end
+ end
+ end
+ end)
+ : getMap()
+
+local function compileByParentNode(source)
+ local parentNode = m.compileNode(source.node)
+ if not parentNode then
+ return
+ end
+ local key = guide.getKeyName(source)
+ for node in m.eachNode(parentNode) do
+ local f = searchFieldMap[node.type]
+ if f then
+ f(node, key, function (field)
+ compileValue(source, field.value)
+ end)
+ end
end
end
local compilerMap = util.switch()
: case 'local'
- : call(function (uri, source)
- compileValue(uri, source, source.value)
+ : call(function (source)
+ compileValue(source, source.value)
if source.ref then
for _, ref in ipairs(source.ref) do
if ref.type == 'setlocal' then
- compileValue(uri, source, ref.value)
+ compileValue(source, ref.value)
end
end
end
end)
: case 'getlocal'
- : call(function (uri, source)
- m.setNode(source, m.compileNode(uri, source.node))
+ : call(function (source)
+ m.setNode(source, m.compileNode(source.node))
end)
: case 'setfield'
+ : call(function (source)
+ compileByLocalID(source)
+ end)
: case 'getfield'
- : call(function (uri, source)
+ : call(function (source)
+ compileByLocalID(source)
+ compileByParentNode(source)
end)
: case 'function.return'
- : call(function (uri, source)
+ : call(function (source)
end)
: getMap()
----@param uri uri
---@param source parser.object
---@return vm.node
-function m.compileNode(uri, source)
+function m.compileNode(source)
if source._node then
return source._node
end
source._node = false
local compiler = compilerMap[source.type]
if compiler then
- compiler(uri, source)
+ compiler(source)
end
state.subscribeLiteral(source, source._node)
return source._node
diff --git a/script/vm/state.lua b/script/vm/state.lua
index 83ce6084..b0689384 100644
--- a/script/vm/state.lua
+++ b/script/vm/state.lua
@@ -1,6 +1,7 @@
local util = require 'utility'
local files = require 'files'
local globalNode = require 'vm.global-node'
+local guide = require 'parser.guide'
---@class vm.state
local m = {}
@@ -13,13 +14,13 @@ end)
---@type table<parser.object, boolean>
m.allLiterals = {}
----@param uri uri
---@param source parser.object
-function m.declareLiteral(uri, source)
+function m.declareLiteral(source)
if m.allLiterals[source] then
return
end
m.allLiterals[source] = true
+ local uri = guide.getUri(source)
local literals = m.literals[uri]
literals[#literals+1] = source
end
diff --git a/test/definition/table.lua b/test/definition/table.lua
index 0fb76191..47cb13ea 100644
--- a/test/definition/table.lua
+++ b/test/definition/table.lua
@@ -151,6 +151,15 @@ print(x.y.<?z?>)
]]
TEST [[
+local x = {
+ y = {
+ <!z!> = 1
+ }
+}
+print(x.y.<?z?>)
+]]
+
+TEST [[
local function f()
local t = {}
t.field1 = {