diff options
-rw-r--r-- | script/core/definition.lua | 2 | ||||
-rw-r--r-- | script/vm/compiler.lua | 81 | ||||
-rw-r--r-- | script/vm/getDef.lua | 20 | ||||
-rw-r--r-- | script/vm/global-manager.lua | 2 | ||||
-rw-r--r-- | script/vm/global.lua | 5 | ||||
-rw-r--r-- | test/definition/bug.lua | 8 | ||||
-rw-r--r-- | test/definition/function.lua | 2 |
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?>() ]] |