summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorsumneko <sumneko@hotmail.com>2019-04-30 17:16:13 +0800
committersumneko <sumneko@hotmail.com>2019-04-30 17:16:13 +0800
commite683d90bdb40ed07ad3f1b53ca94b0d299382c74 (patch)
treef6c7f1d8d7906ab6f962ce0660248f0ebf94ba75 /server
parentcf97b3bf418d73894bb7849b6c02e40c753425bb (diff)
downloadlua-language-server-e683d90bdb40ed07ad3f1b53ca94b0d299382c74.zip
emmyTableType
Diffstat (limited to 'server')
-rw-r--r--server/src/core/hover/hover.lua41
-rw-r--r--server/src/emmy/manager.lua6
-rw-r--r--server/src/emmy/tableType.lua40
-rw-r--r--server/src/parser/ast.lua13
-rw-r--r--server/src/parser/grammar.lua2
-rw-r--r--server/src/vm/emmy.lua15
-rw-r--r--server/src/vm/ipairs.lua7
-rw-r--r--server/src/vm/local.lua1
-rw-r--r--server/src/vm/value.lua10
-rw-r--r--server/test/hover/init.lua49
10 files changed, 159 insertions, 25 deletions
diff --git a/server/src/core/hover/hover.lua b/server/src/core/hover/hover.lua
index 12d6fbe5..c0f62f24 100644
--- a/server/src/core/hover/hover.lua
+++ b/server/src/core/hover/hover.lua
@@ -71,23 +71,28 @@ local function findClass(value)
end)
end
+local function formatKey(key)
+ local kType = type(key)
+ if kType == 'table' then
+ key = ('[*%s]'):format(key:getType())
+ elseif math.type(key) == 'integer' then
+ key = ('[%03d]'):format(key)
+ elseif kType == 'string' then
+ if key:find '^%d' or key:find '[^%w_]' then
+ key = ('[%q]'):format(key)
+ end
+ elseif key == '' then
+ key = '[*any]'
+ else
+ key = ('[%s]'):format(key)
+ end
+ return key
+end
+
local function unpackTable(value)
local lines = {}
value:eachChild(function (key, child)
- local kType = type(key)
- if kType == 'table' then
- key = ('[*%s]'):format(key:getType())
- elseif math.type(key) == 'integer' then
- key = ('[%03d]'):format(key)
- elseif kType == 'string' then
- if key:find '^%d' or key:find '[^%w_]' then
- key = ('[%q]'):format(key)
- end
- elseif key == '' then
- key = '[*any]'
- else
- key = ('[%s]'):format(key)
- end
+ key = formatKey(key)
local vType = type(child:getLiteral())
if vType == 'boolean'
@@ -101,8 +106,12 @@ local function unpackTable(value)
end
end)
local emmy = value:getEmmy()
- if emmy and emmy.type == 'emmy.arrayType' then
- lines[#lines+1] = ('[*integer]: %s'):format(emmy:getName())
+ if emmy then
+ if emmy.type == 'emmy.arrayType' then
+ lines[#lines+1] = ('[*integer]: %s'):format(emmy:getName())
+ elseif emmy.type == 'emmy.tableType' then
+ lines[#lines+1] = ('[*%s]: %s'):format(emmy:getKeyType():getType(), emmy:getValueType():getType())
+ end
end
if #lines == 0 then
return '{}'
diff --git a/server/src/emmy/manager.lua b/server/src/emmy/manager.lua
index 45fc1c3d..dad456a8 100644
--- a/server/src/emmy/manager.lua
+++ b/server/src/emmy/manager.lua
@@ -8,6 +8,7 @@ local newReturn = require 'emmy.return'
local newField = require 'emmy.field'
local newGeneric = require 'emmy.generic'
local newArrayType = require 'emmy.arrayType'
+local newTableType = require 'emmy.tableType'
local mt = {}
mt.__index = mt
@@ -110,6 +111,11 @@ function mt:addArrayType(source)
return typeObj
end
+function mt:addTableType(source, keyType, valueType)
+ local typeObj = newTableType(self, source, keyType, valueType)
+ return typeObj
+end
+
function mt:addAlias(source, typeObj)
local aliasName = source[1][1]
local aliasObj = newAlias(self, source)
diff --git a/server/src/emmy/tableType.lua b/server/src/emmy/tableType.lua
new file mode 100644
index 00000000..3882cd61
--- /dev/null
+++ b/server/src/emmy/tableType.lua
@@ -0,0 +1,40 @@
+local listMgr = require 'vm.list'
+
+---@class EmmyTableType
+local mt = {}
+mt.__index = mt
+mt.type = 'emmy.tableType'
+
+function mt:getType()
+ return 'table'
+end
+
+function mt:getKeyType()
+ return self.keyType
+end
+
+function mt:getValueType()
+ return self.valueType
+end
+
+function mt:getSource()
+ return listMgr.get(self.source)
+end
+
+function mt:setValue(value)
+ self.value = value
+end
+
+function mt:getValue()
+ return self.value
+end
+
+return function (manager, source, keyType, valueType)
+ local self = setmetatable({
+ source = source.id,
+ keyType = keyType,
+ valueType = valueType,
+ _manager = manager,
+ }, mt)
+ return self
+end
diff --git a/server/src/parser/ast.lua b/server/src/parser/ast.lua
index 72c441ca..bf8f5dab 100644
--- a/server/src/parser/ast.lua
+++ b/server/src/parser/ast.lua
@@ -1168,11 +1168,14 @@ local Defs = {
typeName.type = 'emmyArrayType'
return typeName
end,
- EmmyTableType = function (typeName, keyType, valueType)
- typeName.type = 'emmyTableType'
- typeName[2] = keyType
- typeName[3] = valueType
- return typeName
+ EmmyTableType = function (start, keyType, valueType, finish)
+ return {
+ type = 'emmyTableType',
+ start = start,
+ finish = finish - 1,
+ [1] = keyType,
+ [2] = valueType,
+ }
end,
EmmyFunctionType = function (...)
local result = {
diff --git a/server/src/parser/grammar.lua b/server/src/parser/grammar.lua
index 2cbc6d34..28e3eb28 100644
--- a/server/src/parser/grammar.lua
+++ b/server/src/parser/grammar.lua
@@ -577,7 +577,7 @@ EmmyLanguage <- MustEmmyName
EmmyArrayType <- (MustEmmyName '[]')
-> EmmyArrayType
-EmmyTableType <- (MustEmmyName '<' %s* EmmyType %s* ',' %s* EmmyType %s* '>')
+EmmyTableType <- ({} 'table' Cut '<' %s* EmmyType %s* ',' %s* EmmyType %s* '>' {})
-> EmmyTableType
EmmyFunctionType<- ('fun' Cut %s* EmmyFunctionArgs? %s* EmmyFunctionRtn?)
diff --git a/server/src/vm/emmy.lua b/server/src/vm/emmy.lua
index cf6d7026..a66738e5 100644
--- a/server/src/vm/emmy.lua
+++ b/server/src/vm/emmy.lua
@@ -29,6 +29,7 @@ function mt:doEmmy(action)
elseif tp == 'emmyArrayType' then
self:doEmmyArrayType(action)
elseif tp == 'emmyTableType' then
+ self:doEmmyTableType(action)
elseif tp == 'emmyFunctionType' then
elseif tp == 'emmySee' then
elseif tp == 'emmyIncomplete' then
@@ -237,6 +238,20 @@ function mt:doEmmyArrayType(action)
return type
end
+function mt:doEmmyTableType(action)
+ ---@type emmyMgr
+ local emmyMgr = self.emmyMgr
+ self:instantSource(action)
+ local keyType = self:buildEmmyType(action[1])
+ local valueType = self:buildEmmyType(action[2])
+ local type = emmyMgr:addTableType(action, keyType, valueType)
+ 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
index e27b8584..b8d821ef 100644
--- a/server/src/vm/ipairs.lua
+++ b/server/src/vm/ipairs.lua
@@ -33,10 +33,15 @@ function mt:callNext(func, values, source)
local emmy = tbl:getEmmy()
if emmy then
if emmy.type == 'emmy.arrayType' then
- local key = self:createValue('integer', self:getDefaultSource())
+ local key = self:createValue('integer', source)
local value = self:createValue(emmy:getName(), source)
func:setReturn(1, key)
func:setReturn(2, value)
+ elseif emmy.type == 'emmy.tableType' then
+ local key = self:createValue(emmy:getKeyType():getType(), source)
+ local value = self:createValue(emmy:getValueType():getType(), source)
+ func:setReturn(1, key)
+ func:setReturn(2, value)
end
end
end
diff --git a/server/src/vm/local.lua b/server/src/vm/local.lua
index ad7d80e8..ce47414a 100644
--- a/server/src/vm/local.lua
+++ b/server/src/vm/local.lua
@@ -143,6 +143,7 @@ function mt:setEmmy(emmy)
if emmy.type ~= 'emmy.class'
and emmy.type ~= 'emmy.type'
and emmy.type ~= 'emmy.arrayType'
+ and emmy.type ~= 'emmy.tableType'
then
return
end
diff --git a/server/src/vm/value.lua b/server/src/vm/value.lua
index d974cec0..6cfaec4b 100644
--- a/server/src/vm/value.lua
+++ b/server/src/vm/value.lua
@@ -190,6 +190,8 @@ function mt:getChild(index, source)
if type(index) == 'number' then
value = create(emmy:getName(), source)
end
+ elseif emmy.type == 'emmy.tableType' then
+ value = create(emmy:getValueType():getType(), source)
end
end
if not value then
@@ -587,8 +589,12 @@ function mt:setEmmy(emmy)
end)
elseif emmy.type == 'emmy.arrayType' then
---@type EmmyArrayType
- local EmmyArrayType = emmy
- EmmyArrayType:setValue(self)
+ local emmyArrayType = emmy
+ emmyArrayType:setValue(self)
+ elseif emmy.type == 'emmy.tableType' then
+ ---@type EmmyTableType
+ local emmyTableType = emmy
+ emmyTableType:setValue(self)
else
return
end
diff --git a/server/test/hover/init.lua b/server/test/hover/init.lua
index 485b68a7..685ee507 100644
--- a/server/test/hover/init.lua
+++ b/server/test/hover/init.lua
@@ -691,3 +691,52 @@ end
[[
local k: integer
]]
+
+TEST [[
+---@type table<ClassA, ClassB>
+local <?x?>
+]]
+[[
+local x: {
+ [*ClassA]: ClassB,
+}
+]]
+
+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
+]]