summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--script/core/definition.lua2
-rw-r--r--script/vm/compiler.lua81
-rw-r--r--script/vm/getDef.lua20
-rw-r--r--script/vm/global-manager.lua2
-rw-r--r--script/vm/global.lua5
-rw-r--r--test/definition/bug.lua8
-rw-r--r--test/definition/function.lua2
7 files changed, 96 insertions, 24 deletions
diff --git a/script/core/definition.lua b/script/core/definition.lua
index 3323cb84..b089bdab 100644
--- a/script/core/definition.lua
+++ b/script/core/definition.lua
@@ -152,7 +152,7 @@ return function (uri, offset)
goto CONTINUE
end
else
- if guide.isLiteral(src) then
+ if guide.isLiteral(src) and src.type ~= 'function' then
goto CONTINUE
end
end
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua
index dba97932..3d17cef4 100644
--- a/script/vm/compiler.lua
+++ b/script/vm/compiler.lua
@@ -57,7 +57,7 @@ local searchFieldMap = util.switch()
if field.type == 'tablefield'
or field.type == 'tableindex' then
if guide.getKeyName(field) == key then
- pushResult(m.compileNode(field))
+ pushResult(field)
end
end
end
@@ -65,9 +65,14 @@ local searchFieldMap = util.switch()
: case 'global'
---@param node vm.node.global
: call(function (node, key, pushResult)
- local global = globalMgr.getGlobal('variable', node.name, key)
- if global then
- pushResult(global)
+ if node.cate == 'variable' then
+ local global = globalMgr.getGlobal('variable', node.name, key)
+ if global then
+ pushResult(global)
+ end
+ end
+ if node.cate == 'type' then
+ m.getClassFields(node, key, pushResult)
end
end)
: case 'local'
@@ -75,12 +80,57 @@ local searchFieldMap = util.switch()
local sources = localID.getSources(node, key)
if sources then
for _, src in ipairs(sources) do
- pushResult(m.compileNode(src))
+ pushResult(src)
end
end
end)
: getMap()
+
+function m.getClassFields(node, key, pushResult)
+ local mark = {}
+ local function searchClass(class)
+ local name = class.name
+ if mark[name] then
+ return
+ end
+ mark[name] = true
+ for _, set in ipairs(class:getSets()) do
+ if set.type == 'doc.class' then
+ -- check ---@field
+ local hasFounded
+ for _, field in ipairs(set.fields) do
+ if guide.getKeyName(field) == key then
+ hasFounded = true
+ pushResult(field)
+ end
+ end
+ -- check local field and global field
+ if set.bindSources then
+ for _, src in ipairs(set.bindSources) do
+ if searchFieldMap[src.type] then
+ searchFieldMap[src.type](src, key, function (src)
+ hasFounded = true
+ pushResult(src)
+ end)
+ end
+ end
+ end
+ -- look into extends(if field not found)
+ if not hasFounded and set.extends then
+ for _, extend in ipairs(set.extends) do
+ local extendType = globalMgr.getGlobal('type', extend[1])
+ if extendType then
+ searchClass(extendType)
+ end
+ end
+ end
+ end
+ end
+ end
+ searchClass(node)
+end
+
local function getReturnOfFunction(func, index)
if not func._returns then
func._returns = util.defaultTable(function ()
@@ -101,8 +151,8 @@ local function getReturnOfSetMetaTable(source, args)
m.setNode(source, m.compileNode(tbl))
end
if mt then
- m.compileByParentNode(mt, '__index', function (node)
- m.setNode(source, node)
+ m.compileByParentNode(mt, '__index', function (src)
+ m.setNode(source, m.compileNode(src))
end)
end
return source._node
@@ -136,7 +186,7 @@ end
---@param source vm.node
---@param key any
----@param pushResult fun(node:vm.node)
+---@param pushResult fun(source: parser.object)
function m.compileByParentNode(source, key, pushResult)
local parentNode = m.compileNode(source)
if not parentNode then
@@ -244,8 +294,8 @@ local compilerMap = util.switch()
: case 'getindex'
: call(function (source)
compileByLocalID(source)
- m.compileByParentNode(source.node, guide.getKeyName(source), function (node)
- m.setNode(source, node)
+ m.compileByParentNode(source.node, guide.getKeyName(source), function (src)
+ m.setNode(source, m.compileNode(src))
end)
end)
: case 'tablefield'
@@ -291,6 +341,10 @@ local compilerMap = util.switch()
type:addGet(uri, source)
m.setNode(source, type)
end)
+ : case 'doc.field'
+ : call(function (source)
+ m.setNode(source, m.compileNode(source.extends))
+ end)
: getMap()
---@param source parser.object
@@ -303,6 +357,10 @@ end
---@param source parser.object
local function compileByGlobal(source)
+ if source.type == 'global' then
+ m.setNode(source, source)
+ return
+ end
if source._globalNode then
m.setNode(source, source._globalNode)
for _, set in ipairs(source._globalNode:getSets()) do
@@ -310,6 +368,7 @@ local function compileByGlobal(source)
m.setNode(source, m.compileNode(set.value))
end
end
+ return
end
end
@@ -320,8 +379,8 @@ function m.compileNode(source)
return source._node
end
source._node = false
- compileByNode(source)
compileByGlobal(source)
+ compileByNode(source)
localMgr.subscribeLocal(source, source._node)
diff --git a/script/vm/getDef.lua b/script/vm/getDef.lua
index b6897bea..8b3e610d 100644
--- a/script/vm/getDef.lua
+++ b/script/vm/getDef.lua
@@ -85,13 +85,23 @@ local searchFieldMap = util.switch()
end
end)
: case 'global'
+ ---@param node vm.node
+ ---@param key string
: call(function (node, key, pushResult)
- local newGlobal = globalMgr.getGlobal('variable', node.name, key)
- if not newGlobal then
- return
+ if node.cate == 'variable' then
+ local newGlobal = globalMgr.getGlobal('variable', node.name, key)
+ if newGlobal then
+ for _, set in ipairs(newGlobal:getSets()) do
+ pushResult(set)
+ end
+ end
end
- for _, set in ipairs(newGlobal:getSets()) do
- pushResult(set)
+ if node.cate == 'type' then
+ compiler.getClassFields(node, key, function (field)
+ if field.type == 'doc.field' then
+ pushResult(field.field)
+ end
+ end)
end
end)
: case 'local'
diff --git a/script/vm/global-manager.lua b/script/vm/global-manager.lua
index 438d3d72..bda7b744 100644
--- a/script/vm/global-manager.lua
+++ b/script/vm/global-manager.lua
@@ -162,7 +162,7 @@ function m.declareGlobal(cate, name, uri)
local key = cate .. '|' .. name
m.globalSubs[uri][key] = true
if not m.globals[key] then
- m.globals[key] = globalBuilder(name)
+ m.globals[key] = globalBuilder(name, cate)
end
return m.globals[key]
end
diff --git a/script/vm/global.lua b/script/vm/global.lua
index d5974e63..2f17bdc2 100644
--- a/script/vm/global.lua
+++ b/script/vm/global.lua
@@ -8,6 +8,7 @@ local util = require 'utility'
---@field links table<uri, vm.node.global.link>
---@field setsCache parser.object[]
---@field getsCache parser.object[]
+---@field cate vm.global.cate
local mt = {}
mt.__index = mt
mt.type = 'global'
@@ -70,10 +71,12 @@ function mt:isAlive()
return next(self.links) ~= nil
end
+---@param cate vm.global.cate
---@return vm.node.global
-return function (name)
+return function (name, cate)
return setmetatable({
name = name,
+ cate = cate,
links = util.defaultTable(function ()
return {
sets = {},
diff --git a/test/definition/bug.lua b/test/definition/bug.lua
index ef7295d1..58c2ed59 100644
--- a/test/definition/bug.lua
+++ b/test/definition/bug.lua
@@ -262,7 +262,7 @@ TEST [[
---@type B
local t
-local <!<?v?>!> = t.x
+t.<?x?>
]]
TEST [[
@@ -274,7 +274,7 @@ TEST [[
---@type B
local t
-local <!<?v?>!> = t.x
+t.<?x?>
]]
TEST [[
@@ -286,7 +286,7 @@ function A:x() end
---@class B: A
local B
-function B:<!x!>() end
+<!function B:x() end!>
---@type B
local t
@@ -298,7 +298,7 @@ TEST [[
---@class A
local A
-function A:<!x!>() end
+<!function A:x() end!>
---@class B: A
local B
diff --git a/test/definition/function.lua b/test/definition/function.lua
index f5d32e78..95dd1b57 100644
--- a/test/definition/function.lua
+++ b/test/definition/function.lua
@@ -24,6 +24,6 @@ end
]]
TEST [[
-local <!f!> = function () end
+local <!f!> = <!function () end!>
<?f?>()
]]