summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/libs/@lua/basic.lni34
-rw-r--r--server/src/core/hover/hover.lua4
-rw-r--r--server/src/emmy/arrayType.lua36
-rw-r--r--server/src/emmy/manager.lua29
-rw-r--r--server/src/vm/emmy.lua14
-rw-r--r--server/src/vm/ipairs.lua43
-rw-r--r--server/src/vm/library.lua7
-rw-r--r--server/src/vm/local.lua5
-rw-r--r--server/src/vm/value.lua16
-rw-r--r--server/src/vm/vm.lua9
-rw-r--r--server/test/hover/init.lua49
11 files changed, 215 insertions, 31 deletions
diff --git a/server/libs/@lua/basic.lni b/server/libs/@lua/basic.lni
index a90a029e..61db69c9 100644
--- a/server/libs/@lua/basic.lni
+++ b/server/libs/@lua/basic.lni
@@ -127,32 +127,26 @@ name = 'object'
name = 'metatable'
type = 'table'
+[@ipairs]
+special = '@ipairs'
+[[.args]]
+type = 'table'
+``````````
+name = 'i'
+type = 'integer'
+[[.returns]]
+name = 'i'
+type = 'integer'
+``````````
+type = 'object'
+
[ipairs]
+special = 'ipairs'
[[.args]]
name = 't'
type = 'table'
[[.returns]]
name = 'iterator'
-type = 'function'
-args = {
- 1 = {
- name = 'table',
- type = 'table',
- },
- 2 = {
- name = 'i',
- type = 'integer',
- }
-}
-returns = {
- 1 = {
- name = 'i',
- type = 'integer',
- },
- 2 = {
- name = 'object',
- },
-}
``````````
name = 't'
type = 'table'
diff --git a/server/src/core/hover/hover.lua b/server/src/core/hover/hover.lua
index 550129a4..12d6fbe5 100644
--- a/server/src/core/hover/hover.lua
+++ b/server/src/core/hover/hover.lua
@@ -100,6 +100,10 @@ local function unpackTable(value)
lines[#lines+1] = ('%s: %s'):format(key, child:getType())
end
end)
+ local emmy = value:getEmmy()
+ if emmy and emmy.type == 'emmy.arrayType' then
+ lines[#lines+1] = ('[*integer]: %s'):format(emmy:getName())
+ end
if #lines == 0 then
return '{}'
end
diff --git a/server/src/emmy/arrayType.lua b/server/src/emmy/arrayType.lua
new file mode 100644
index 00000000..3c6a7b7b
--- /dev/null
+++ b/server/src/emmy/arrayType.lua
@@ -0,0 +1,36 @@
+local listMgr = require 'vm.list'
+
+---@class EmmyArrayType
+local mt = {}
+mt.__index = mt
+mt.type = 'emmy.arrayType'
+
+function mt:getType()
+ return 'table'
+end
+
+function mt:getName()
+ return self.name
+end
+
+function mt:getSource()
+ return listMgr.get(self.source)
+end
+
+function mt:setValue(value)
+ self.value = value
+ self:getSource():get('emmy.typeUnit'):setValue(value)
+end
+
+function mt:getValue()
+ return self.value
+end
+
+return function (manager, source)
+ local self = setmetatable({
+ name = source[1],
+ source = source.id,
+ _manager = manager,
+ }, mt)
+ return self
+end
diff --git a/server/src/emmy/manager.lua b/server/src/emmy/manager.lua
index ce766988..45fc1c3d 100644
--- a/server/src/emmy/manager.lua
+++ b/server/src/emmy/manager.lua
@@ -1,12 +1,13 @@
-local listMgr = require 'vm.list'
-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 newReturn = require 'emmy.return'
-local newField = require 'emmy.field'
-local newGeneric = require 'emmy.generic'
+local listMgr = require 'vm.list'
+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 newReturn = require 'emmy.return'
+local newField = require 'emmy.field'
+local newGeneric = require 'emmy.generic'
+local newArrayType = require 'emmy.arrayType'
local mt = {}
mt.__index = mt
@@ -99,6 +100,16 @@ function mt:addType(source)
return typeObj
end
+function mt:addArrayType(source)
+ local typeObj = newArrayType(self, source)
+ local typeUnit = newTypeUnit(self, source)
+ local list = self:getClass(source[1])
+ typeUnit:setParent(typeObj)
+ list[source.id] = typeUnit
+ source:set('emmy.typeUnit', typeUnit)
+ return typeObj
+end
+
function mt:addAlias(source, typeObj)
local aliasName = source[1][1]
local aliasObj = newAlias(self, source)
diff --git a/server/src/vm/emmy.lua b/server/src/vm/emmy.lua
index 1dd67d7d..cf6d7026 100644
--- a/server/src/vm/emmy.lua
+++ b/server/src/vm/emmy.lua
@@ -27,6 +27,7 @@ function mt:doEmmy(action)
self:doEmmyVararg(action)
elseif tp == 'emmyLanguage' then
elseif tp == 'emmyArrayType' then
+ self:doEmmyArrayType(action)
elseif tp == 'emmyTableType' then
elseif tp == 'emmyFunctionType' then
elseif tp == 'emmySee' then
@@ -223,6 +224,19 @@ function mt:doEmmyVararg(action)
end
end
+function mt:doEmmyArrayType(action)
+ ---@type emmyMgr
+ local emmyMgr = self.emmyMgr
+ self:instantSource(action)
+ action:set('emmy class', action[1])
+ local type = emmyMgr:addArrayType(action)
+ self._emmy = type
+ if self.lsp then
+ self.lsp.global:markGet(self:getUri())
+ end
+ return type
+end
+
function mt:doEmmyIncomplete(action)
self:instantSource(action)
end
diff --git a/server/src/vm/ipairs.lua b/server/src/vm/ipairs.lua
new file mode 100644
index 00000000..e27b8584
--- /dev/null
+++ b/server/src/vm/ipairs.lua
@@ -0,0 +1,43 @@
+local mt = require 'vm.manager'
+
+---@param func function
+function mt:callIpairs(func, values, source)
+ local tbl = values[1]
+ func:setReturn(2, tbl)
+end
+
+---@param func function
+function mt:callAtIpairs(func, values, source)
+ local tbl = values[1]
+ if tbl then
+ local emmy = tbl:getEmmy()
+ if emmy then
+ if emmy.type == 'emmy.arrayType' then
+ local value = self:createValue(emmy:getName(), source)
+ func:setReturn(2, value)
+ end
+ end
+ end
+end
+
+---@param func function
+function mt:callPairs(func, values, source)
+ local tbl = values[1]
+ func:setReturn(2, tbl)
+end
+
+---@param func function
+function mt:callNext(func, values, source)
+ local tbl = values[1]
+ if tbl then
+ local emmy = tbl:getEmmy()
+ if emmy then
+ if emmy.type == 'emmy.arrayType' then
+ local key = self:createValue('integer', self:getDefaultSource())
+ local value = self:createValue(emmy:getName(), source)
+ func:setReturn(1, key)
+ func:setReturn(2, value)
+ end
+ end
+ end
+end
diff --git a/server/src/vm/library.lua b/server/src/vm/library.lua
index e1bd335e..258118a7 100644
--- a/server/src/vm/library.lua
+++ b/server/src/vm/library.lua
@@ -43,6 +43,9 @@ function buildLibValue(lib)
if lib.special == 'pairs' then
func:setReturn(1, Special['next'])
end
+ if lib.special == 'ipairs' then
+ func:setReturn(1, Special['@ipairs'])
+ end
end
elseif tp == 'string' then
value = valueMgr.create('string', sourceMgr.dummy())
@@ -71,6 +74,10 @@ function buildLibValue(lib)
if lib.special == 'next' then
Special['next'] = value
end
+ if lib.special == '@ipairs' then
+ Special['@ipairs'] = value
+ return nil
+ end
return value
end
diff --git a/server/src/vm/local.lua b/server/src/vm/local.lua
index 3591eab9..ad7d80e8 100644
--- a/server/src/vm/local.lua
+++ b/server/src/vm/local.lua
@@ -140,7 +140,10 @@ function mt:setEmmy(emmy)
if not emmy then
return
end
- if emmy.type ~= 'emmy.class' and emmy.type ~= 'emmy.type' then
+ if emmy.type ~= 'emmy.class'
+ and emmy.type ~= 'emmy.type'
+ and emmy.type ~= 'emmy.arrayType'
+ then
return
end
if self.value then
diff --git a/server/src/vm/value.lua b/server/src/vm/value.lua
index efbe50c4..d974cec0 100644
--- a/server/src/vm/value.lua
+++ b/server/src/vm/value.lua
@@ -184,7 +184,17 @@ function mt:getChild(index, source)
parent = method
end
if not value and source then
- value = create('any', source)
+ local emmy = self:getEmmy()
+ if emmy then
+ if emmy.type == 'emmy.arrayType' then
+ if type(index) == 'number' then
+ value = create(emmy:getName(), source)
+ end
+ end
+ end
+ if not value then
+ value = create('any', source)
+ end
self:setChild(index, value)
value.uri = self.uri
end
@@ -575,6 +585,10 @@ function mt:setEmmy(emmy)
self:mergeValue(class:getValue())
end
end)
+ elseif emmy.type == 'emmy.arrayType' then
+ ---@type EmmyArrayType
+ local EmmyArrayType = emmy
+ EmmyArrayType:setValue(self)
else
return
end
diff --git a/server/src/vm/vm.lua b/server/src/vm/vm.lua
index d057c1cd..fab500e5 100644
--- a/server/src/vm/vm.lua
+++ b/server/src/vm/vm.lua
@@ -14,6 +14,7 @@ local mt = require 'vm.manager'
require 'vm.module'
require 'vm.raw'
require 'vm.pcall'
+require 'vm.ipairs'
require 'vm.emmy'
-- TODO source测试
@@ -296,6 +297,14 @@ function mt:callLibrary(func, values, source, lib)
self:callPcall(func, values, source)
elseif lib.special == 'xpcall' then
self:callXpcall(func, values, source)
+ elseif lib.special == 'ipairs' then
+ self:callIpairs(func, values, source)
+ elseif lib.special == '@ipairs' then
+ self:callAtIpairs(func, values, source)
+ elseif lib.special == 'pairs' then
+ self:callPairs(func, values, source)
+ elseif lib.special == 'next' then
+ self:callNext(func, values, source)
end
else
-- 如果lib的参数中有function,则立即执行function
diff --git a/server/test/hover/init.lua b/server/test/hover/init.lua
index 5e46bf26..485b68a7 100644
--- a/server/test/hover/init.lua
+++ b/server/test/hover/init.lua
@@ -642,3 +642,52 @@ end
[[
local x: *Class {}
]]
+
+TEST [[
+---@type string[]
+local <?x?>
+]]
+[[
+local x: {
+ [*integer]: string,
+}
+]]
+
+TEST [[
+---@type string[]
+local t
+local <?x?> = t[1]
+]]
+[[
+local x: string
+]]
+
+TEST [[
+---@type string[]
+local t
+for _, <?x?> in ipairs(t) do
+end
+]]
+[[
+local x: string
+]]
+
+TEST [[
+---@type string[]
+local t
+for _, <?x?> in pairs(t) do
+end
+]]
+[[
+local x: string
+]]
+
+TEST [[
+---@type string[]
+local t
+for <?k?>, v in pairs(t) do
+end
+]]
+[[
+local k: integer
+]]