summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/src/emmy/manager.lua10
-rw-r--r--server/src/emmy/param.lua31
-rw-r--r--server/src/parser/ast.lua2
-rw-r--r--server/src/vm/emmy.lua27
-rw-r--r--server/src/vm/function.lua26
-rw-r--r--server/src/vm/value.lua7
-rw-r--r--server/src/vm/vm.lua1
-rw-r--r--server/test/definition/emmy.lua5
-rw-r--r--server/test/hover/init.lua39
9 files changed, 146 insertions, 2 deletions
diff --git a/server/src/emmy/manager.lua b/server/src/emmy/manager.lua
index fe14173c..d8b3b656 100644
--- a/server/src/emmy/manager.lua
+++ b/server/src/emmy/manager.lua
@@ -3,6 +3,7 @@ local newClass = require 'emmy.class'
local newType = require 'emmy.type'
local newTypeUnit = require 'emmy.typeUnit'
local newAlias = require 'emmy.alias'
+local newParam = require 'emmy.param'
local mt = {}
mt.__index = mt
@@ -104,6 +105,15 @@ function mt:addAlias(source, typeObj)
return aliasObj
end
+function mt:addParam(source, typeObj)
+ local paramName = source[1][1]
+ local paramObj = newParam(self, source)
+ paramObj:bindType(typeObj)
+ local list = self:getClass(paramName)
+ list[source.id] = paramObj
+ return paramObj
+end
+
function mt:remove()
end
diff --git a/server/src/emmy/param.lua b/server/src/emmy/param.lua
new file mode 100644
index 00000000..9c18bfec
--- /dev/null
+++ b/server/src/emmy/param.lua
@@ -0,0 +1,31 @@
+local listMgr = require 'vm.list'
+
+---@class EmmyParam
+local mt = {}
+mt.__index = mt
+mt.type = 'emmy.param'
+
+function mt:getName()
+ return self.name
+end
+
+function mt:getSource()
+ return listMgr.get(self.source)
+end
+
+function mt:bindType(type)
+ if type then
+ self._bindType = type
+ else
+ return self._bindType
+ end
+end
+
+return function (manager, source)
+ local self = setmetatable({
+ name = source[1][1],
+ source = source.id,
+ _manager = manager,
+ }, mt)
+ return self
+end
diff --git a/server/src/parser/ast.lua b/server/src/parser/ast.lua
index 8c703491..7df7676d 100644
--- a/server/src/parser/ast.lua
+++ b/server/src/parser/ast.lua
@@ -629,7 +629,7 @@ local Defs = {
end
if isField then
table[#table+1] = arg
- if arg.finish then
+ if arg.type:sub(1, 4) ~= 'emmy' then
wantField = false
start = arg.finish + 1
end
diff --git a/server/src/vm/emmy.lua b/server/src/vm/emmy.lua
index a2a38553..5406aab1 100644
--- a/server/src/vm/emmy.lua
+++ b/server/src/vm/emmy.lua
@@ -2,6 +2,7 @@ local mt = require 'vm.manager'
function mt:clearEmmy()
self._emmy = nil
+ self._emmyParams = nil
end
function mt:doEmmy(action)
@@ -13,6 +14,7 @@ function mt:doEmmy(action)
elseif tp == 'emmyAlias' then
self:doEmmyAlias(action)
elseif tp == 'emmyParam' then
+ self:doEmmyParam(action)
elseif tp == 'emmyReturn' then
elseif tp == 'emmyField' then
elseif tp == 'emmyGeneric' then
@@ -33,6 +35,19 @@ function mt:getEmmy()
return emmy
end
+function mt:addEmmyParam(param)
+ if not self._emmyParams then
+ self._emmyParams = {}
+ end
+ self._emmyParams[#self._emmyParams+1] = param
+end
+
+function mt:getEmmyParams()
+ local params = self._emmyParams
+ self._emmyParams = nil
+ return params
+end
+
function mt:doEmmyClass(action)
---@type emmyMgr
local emmyMgr = self.emmyMgr
@@ -83,6 +98,18 @@ function mt:doEmmyAlias(action)
end
end
+function mt:doEmmyParam(action)
+ ---@type emmyMgr
+ local emmyMgr = self.emmyMgr
+ self:instantSource(action)
+ self:instantSource(action[1])
+ local type = self:doEmmyType(action[2])
+ local param = emmyMgr:addParam(action, type)
+ action:set('emmy.param', param)
+ self._emmy = nil
+ self:addEmmyParam(param)
+end
+
function mt:doEmmyIncomplete(action)
self:instantSource(action)
end
diff --git a/server/src/vm/function.lua b/server/src/vm/function.lua
index 7df9c3ea..dff5952d 100644
--- a/server/src/vm/function.lua
+++ b/server/src/vm/function.lua
@@ -275,13 +275,33 @@ function mt:setArgs(values)
end
end
+function mt:findEmmyParamByName(name)
+ local params = self._emmyParams
+ if not params then
+ return nil
+ end
+ for i = #params, 1, -1 do
+ local param = params[i]
+ if param:getName() == name then
+ return param
+ end
+ end
+ return nil
+end
+
function mt:createArg(vm, arg)
vm:instantSource(arg)
arg:set('arg', true)
if arg.type == 'name' then
- local loc = localMgr.create(arg[1], arg, valueMgr.create('nil', arg))
+ local emmyParam = self:findEmmyParamByName(arg[1])
+ local value = valueMgr.create('nil', arg)
+ if emmyParam then
+ value:setEmmy(emmyParam:bindType())
+ end
+ local loc = localMgr.create(arg[1], arg, value)
self:saveUpvalue(arg[1], loc)
self.args[#self.args+1] = loc
+
elseif arg.type == '...' then
self._dots = createMulti()
end
@@ -360,6 +380,10 @@ function mt:markGlobal()
end
end
+function mt:setEmmyParams(params)
+ self._emmyParams = params
+end
+
local function create(source)
if not source then
error('Function need source')
diff --git a/server/src/vm/value.lua b/server/src/vm/value.lua
index 8a0b0861..9f9b6b7c 100644
--- a/server/src/vm/value.lua
+++ b/server/src/vm/value.lua
@@ -289,6 +289,13 @@ function mt:mergeType(value)
if not value then
return
end
+ if self._emmy and not value._emmy then
+ value._emmy = self._emmy
+ return
+ elseif not self._emmy and value._emmy then
+ self._emmy = value._emmy
+ return
+ end
if value._type then
for tp, rate in pairs(value._type) do
self:setType(tp, rate)
diff --git a/server/src/vm/vm.lua b/server/src/vm/vm.lua
index a6d5f9ea..b37ff153 100644
--- a/server/src/vm/vm.lua
+++ b/server/src/vm/vm.lua
@@ -1063,6 +1063,7 @@ end
function mt:createFunction(source)
local value = self:createValue('function', source)
local func = functionMgr.create(source)
+ func:setEmmyParams(self:getEmmyParams())
value:setFunction(func)
value:setType('function', 1.0)
if source:getUri() == self.uri then
diff --git a/server/test/definition/emmy.lua b/server/test/definition/emmy.lua
index 93fbd2be..7b5110c7 100644
--- a/server/test/definition/emmy.lua
+++ b/server/test/definition/emmy.lua
@@ -66,3 +66,8 @@ TEST [[
---@alias <!B A!>
---@type <?B?>
]]
+
+TEST [[
+---@class <!Class!>
+---@param a <?Class?>
+]]
diff --git a/server/test/hover/init.lua b/server/test/hover/init.lua
index 79904e6c..aadac372 100644
--- a/server/test/hover/init.lua
+++ b/server/test/hover/init.lua
@@ -536,3 +536,42 @@ local x: *Class {
b: number = 1,
}
]]
+
+TEST [[
+---@class Class
+local mt = {}
+
+---@param t Class
+function f(<?t?>)
+end
+]]
+[[
+local t: *Class {}
+]]
+
+TEST [[
+---@class Class
+local mt = {}
+
+---@param t Class
+function f(t)
+ print(<?t?>)
+end
+]]
+[[
+local t: *Class {}
+]]
+
+TEST [[
+---@class Class
+local mt = {}
+
+---@param t Class
+function f(t)
+end
+
+f(<?s?>)
+]]
+[[
+global s: *Class {}
+]]