From 42f9c7d02d6062ce7216abc1489f7a48761cd574 Mon Sep 17 00:00:00 2001 From: Lei Zhu Date: Tue, 29 Dec 2020 19:37:21 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=AF=B9=20doc.type.map?= =?UTF-8?q?=20=E6=94=AF=E6=8C=81=E7=9A=84=E5=88=9D=E7=89=88=EF=BC=8C?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E5=A4=84=E7=90=86=E6=8E=A8=E5=AF=BC=20v1[1].?= =?UTF-8?q?bar1=20=E7=9A=84=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/parser/guide.lua | 36 +++++++++++++++++++++++++++++------- script/parser/luadoc.lua | 30 ++++++++++++++++++------------ test/definition/luadoc.lua | 10 ++++++++++ test/example/guide.txt | 6 +++--- test/hover/init.lua | 2 +- 5 files changed, 61 insertions(+), 23 deletions(-) diff --git a/script/parser/guide.lua b/script/parser/guide.lua index a6149dd7f..93c6ffbba 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -95,7 +95,7 @@ m.childMap = { ['doc.generic'] = {'#generics', 'comment'}, ['doc.generic.object'] = {'generic', 'extends', 'comment'}, ['doc.vararg'] = {'vararg', 'comment'}, - ['doc.type.table'] = {'key', 'value', 'comment'}, + ['doc.type.table'] = {'node', 'key', 'value', 'comment'}, ['doc.type.function'] = {'#args', '#returns', 'comment'}, ['doc.type.typeliteral'] = {'node'}, ['doc.overload'] = {'overload', 'comment'}, @@ -167,6 +167,21 @@ function m.getParentFunction(obj) return nil end +--- 寻找父的table类型 doc.type.table +function m.getParentDocTypeTable(obj) + for _ = 1, 1000 do + local parent = obj.parent + if not parent then + return nil + end + if parent.type == 'doc.type.table' then + return obj + end + obj = parent + end + error('guide.getParentDocTypeTable overstack') +end + --- 寻找所在区块 function m.getBlock(obj) for _ = 1, 1000 do @@ -1686,9 +1701,12 @@ function m.checkSameSimpleByDoc(status, obj, start, pushQueue, mode) for _, res in ipairs(pieceResult) do pushQueue(res, start, true) end - local state = m.getDocState(obj) - if state.type == 'doc.type' and mode == 'ref' then - m.checkSameSimpleOfRefByDocSource(status, state, start, pushQueue, mode) + local parentDocTypeTable = m.getParentDocTypeTable(obj) + if not parentDocTypeTable then + local state = m.getDocState(obj) + if state.type == 'doc.type' and mode == 'ref' then + m.checkSameSimpleOfRefByDocSource(status, state, start, pushQueue, mode) + end end return true elseif obj.type == 'doc.field' then @@ -1699,6 +1717,10 @@ function m.checkSameSimpleByDoc(status, obj, start, pushQueue, mode) elseif obj.type == 'doc.type.array' then pushQueue(obj.node, start + 1, true) return true + elseif obj.type == 'doc.type.table' then + pushQueue(obj.node, start + 1, true) + pushQueue(obj.value, start + 1, true) + return true end end @@ -2812,7 +2834,7 @@ function m.viewInferType(infers) or src.type == 'doc.class.name' or src.type == 'doc.type.name' or src.type == 'doc.type.array' - or src.type == 'doc.type.generic' then + or src.type == 'doc.type.table' then if infer.type ~= 'any' then hasDoc = true break @@ -2827,7 +2849,7 @@ function m.viewInferType(infers) or src.type == 'doc.class.name' or src.type == 'doc.type.name' or src.type == 'doc.type.array' - or src.type == 'doc.type.generic' + or src.type == 'doc.type.table' or src.type == 'doc.type.enum' or src.type == 'doc.resume' then local tp = infer.type or 'any' @@ -3056,7 +3078,7 @@ function m.getDocTypeUnitName(status, unit) typeName = 'function' elseif unit.type == 'doc.type.array' then typeName = m.getDocTypeUnitName(status, unit.node) .. '[]' - elseif unit.type == 'doc.type.generic' then + elseif unit.type == 'doc.type.table' then typeName = ('%s<%s, %s>'):format( m.getDocTypeUnitName(status, unit.node), m.viewInferType(m.getDocTypeNames(status, unit.key)), diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 990b46067..9ea674f4a 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -260,30 +260,36 @@ local function parseTypeUnitArray(node) return result end -local function parseTypeUnitGeneric(node) +local function parseTypeUnitTable(parent, node) if not checkToken('symbol', '<', 1) then return nil end if not nextSymbolOrError('<') then return nil end - local key = parseType(node) + + local result = { + type = 'doc.type.table', + start = node.start, + node = node, + parent = parent, + } + + local key = parseType(result) if not key or not nextSymbolOrError(',') then return nil end - local value = parseType(node) + local value = parseType(result) if not value then return nil end nextSymbolOrError('>') - local result = { - type = 'doc.type.generic', - start = node.start, - finish = getFinish(), - node = node, - key = key, - value = value, - } + + node.parent = result; + result.finish = getFinish() + result.key = key + result.value = value + return result end @@ -397,7 +403,7 @@ local function parseTypeUnit(parent, content) result.parent = parent while true do local newResult = parseTypeUnitArray(result) - or parseTypeUnitGeneric(result) + or parseTypeUnitTable(parent, result) if not newResult then break end diff --git a/test/definition/luadoc.lua b/test/definition/luadoc.lua index 1f3dae007..469c790d6 100644 --- a/test/definition/luadoc.lua +++ b/test/definition/luadoc.lua @@ -253,3 +253,13 @@ function Generic(arg1) print(arg1) end local v1 = Generic("Foo") print(v1.) ]] + +TEST [[ +---@class Foo +local Foo = {} +function Foo:() end + +---@type table +local v1 +print(v1[1].) +]] diff --git a/test/example/guide.txt b/test/example/guide.txt index 437e37b0c..da8d5c326 100644 --- a/test/example/guide.txt +++ b/test/example/guide.txt @@ -2702,7 +2702,7 @@ function m.viewInferType(infers) or src.type == 'doc.class.name' or src.type == 'doc.type.name' or src.type == 'doc.type.array' - or src.type == 'doc.type.generic' then + or src.type == 'doc.type.table' then if infer.type ~= 'any' then hasDoc = true break @@ -2717,7 +2717,7 @@ function m.viewInferType(infers) or src.type == 'doc.class.name' or src.type == 'doc.type.name' or src.type == 'doc.type.array' - or src.type == 'doc.type.generic' + or src.type == 'doc.type.table' or src.type == 'doc.type.enum' or src.type == 'doc.resume' then local tp = infer.type or 'any' @@ -2946,7 +2946,7 @@ local function getDocTypeUnitName(status, unit) typeName = 'function' elseif unit.type == 'doc.type.array' then typeName = getDocTypeUnitName(status, unit.node) .. '[]' - elseif unit.type == 'doc.type.generic' then + elseif unit.type == 'doc.type.table' then typeName = ('%s<%s, %s>'):format( getDocTypeUnitName(status, unit.node), m.viewInferType(m.getDocTypeNames(status, unit.key)), diff --git a/test/hover/init.lua b/test/hover/init.lua index 7c0100ca1..d3d61aed5 100644 --- a/test/hover/init.lua +++ b/test/hover/init.lua @@ -1171,7 +1171,7 @@ TEST [[ local ]] [[ -local x: table +local x: table {} ]] --TEST [[ From 573db3376fa2972cb7d9af0fa560d4e0395ce191 Mon Sep 17 00:00:00 2001 From: Lei Zhu Date: Mon, 4 Jan 2021 12:01:21 +0800 Subject: [PATCH 2/5] =?UTF-8?q?@type=20table=20=E6=94=AF=E6=8C=81=20for=20?= =?UTF-8?q?pairs()=E3=80=81ipairs()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/parser/guide.lua | 70 +++++++++++++++++++++++++++++++++++++- test/definition/luadoc.lua | 54 +++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 1 deletion(-) diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 93c6ffbba..7a5be591f 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -1718,7 +1718,7 @@ function m.checkSameSimpleByDoc(status, obj, start, pushQueue, mode) pushQueue(obj.node, start + 1, true) return true elseif obj.type == 'doc.type.table' then - pushQueue(obj.node, start + 1, true) + pushQueue(obj.node, start, true) pushQueue(obj.value, start + 1, true) return true end @@ -2178,6 +2178,72 @@ function m.checkSameSimpleAsSetValue(status, ref, start, pushQueue) end end +local function getTableAndIndexIfIsForPairsKeyOrValue(ref) + if ref.type ~= 'local' then + return + end + + if not ref.parent or ref.parent.type ~= 'in' then + return + end + + if not ref.value or ref.value.type ~= 'select' then + return + end + + local rootSelectObj = ref.value + if rootSelectObj.index ~= 1 and rootSelectObj.index ~= 2 then + return + end + + if not rootSelectObj.vararg or rootSelectObj.vararg.type ~= 'call' then + return + end + local rootCallObj = rootSelectObj.vararg + + if not rootCallObj.node or rootCallObj.node.type ~= 'call' then + return + end + local pairsCallObj = rootCallObj.node + + if not pairsCallObj.node or pairsCallObj.node.type ~= 'getglobal' + or (pairsCallObj.node[1] ~= 'pairs' and pairsCallObj.node[1] ~= 'ipairs') then + return + end + + if not pairsCallObj.args or not pairsCallObj.args[1] then + return + end + local tableObj = pairsCallObj.args[1] + + return tableObj, rootSelectObj.index +end + +function m.checkSameSimpleAsKeyOrValueInForParis(status, ref, start, pushQueue) + local tableObj, index = getTableAndIndexIfIsForPairsKeyOrValue(ref) + if not tableObj then + return + end + + local newStatus = m.status(status) + m.searchRefs(newStatus, tableObj, 'def') + for _, def in ipairs(newStatus.results) do + if def.bindDocs then + for _, binddoc in ipairs(def.bindDocs) do + if binddoc.type == 'doc.type' then + if binddoc.types[1] and binddoc.types[1].type == 'doc.type.table' then + if index == 1 then + pushQueue(binddoc.types[1].key, start, true) + elseif index == 2 then + pushQueue(binddoc.types[1].value, start, true) + end + end + end + end + end + end +end + local function hasTypeName(doc, name) if doc.type ~= 'doc.type' then return false @@ -2425,6 +2491,8 @@ function m.checkSameSimple(status, simple, ref, start, force, mode, pushQueue) m.checkSameSimpleAsReturn(status, ref, i, pushQueue) -- 检查形如 a = f 的情况 m.checkSameSimpleAsSetValue(status, ref, i, pushQueue) + -- 检查形如 for k,v in pairs()/ipairs() do end 的情况 + m.checkSameSimpleAsKeyOrValueInForParis(status, ref, i, pushQueue) end end if i == #simple then diff --git a/test/definition/luadoc.lua b/test/definition/luadoc.lua index 469c790d6..3a6ff15d9 100644 --- a/test/definition/luadoc.lua +++ b/test/definition/luadoc.lua @@ -263,3 +263,57 @@ function Foo:() end local v1 print(v1[1].) ]] + +TEST [[ +---@class Foo +local Foo = {} +function Foo:() end + +---@class Foo2 +local Foo2 = {} +function Foo2:bar1() end + +---@type Foo2 +local v1 +print(v1[1].) +]] + +--TODO 得扩展 simple 的信息才能识别这种情况了 +--TEST [[ +-----@class Foo +--local Foo = {} +--function Foo:bar1() end +-- +-----@class Foo2 +--local Foo2 = {} +--function Foo2:() end +-- +-----@type Foo2 +--local v1 +--print(v1.) +--]] + +TEST [[ +---@class Foo +local Foo = {} +function Foo:() end + +---@type table +local v1 +for i, v in ipairs(v1) do + print(v.) +end +]] + +TEST [[ +---@class Foo +local Foo = {} +function Foo:() end + +---@type table +local v1 +for k, v in pairs(v1) do + print(k.) + print(v.bar1) +end +]] From c57556e25cb02e01011272c305854d0f1c106e1c Mon Sep 17 00:00:00 2001 From: Lei Zhu Date: Mon, 4 Jan 2021 14:59:10 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0table<=20table<>>?= =?UTF-8?q?=E8=BF=99=E7=A7=8D=E5=B5=8C=E5=A5=97table=E7=9A=84=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/definition/luadoc.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/definition/luadoc.lua b/test/definition/luadoc.lua index 3a6ff15d9..210f5a264 100644 --- a/test/definition/luadoc.lua +++ b/test/definition/luadoc.lua @@ -317,3 +317,16 @@ for k, v in pairs(v1) do print(v.bar1) end ]] + +TEST [[ +---@class Foo +local Foo = {} +function Foo:() end + +---@type table> +local v1 +for i, v in ipairs(v1) do + local v2 = v[1] + print(v2.) +end +]] From 39bbefd8b4c98be50955b2484af1a6b6f9541f54 Mon Sep 17 00:00:00 2001 From: Lei Zhu Date: Tue, 5 Jan 2021 16:50:34 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E5=8E=9F=E7=94=9FAPI=E4=B8=8D=E8=A6=81?= =?UTF-8?q?=E5=8E=BB=E5=88=A4=E5=90=8D=E5=AD=97=EF=BC=8C=E7=94=A8=20specia?= =?UTF-8?q?l=20=E5=AD=97=E6=AE=B5=E6=9D=A5=E5=88=A4=E6=96=AD=EF=BC=8C?= =?UTF-8?q?=E8=BF=99=E6=A0=B7=E6=94=AF=E6=8C=81=20local=20ipairs=20=3D=20i?= =?UTF-8?q?pairs=20=E7=9A=84=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/parser/compile.lua | 2 ++ script/parser/guide.lua | 4 ++-- test/definition/luadoc.lua | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/script/parser/compile.lua b/script/parser/compile.lua index d4129ab4f..f9992047a 100644 --- a/script/parser/compile.lua +++ b/script/parser/compile.lua @@ -12,6 +12,8 @@ local specials = { ['loadfile'] = true, ['pcall'] = true, ['xpcall'] = true, + ['pairs'] = true, + ['ipairs'] = true, } _ENV = nil diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 7a5be591f..56f6ac386 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -2206,8 +2206,8 @@ local function getTableAndIndexIfIsForPairsKeyOrValue(ref) end local pairsCallObj = rootCallObj.node - if not pairsCallObj.node or pairsCallObj.node.type ~= 'getglobal' - or (pairsCallObj.node[1] ~= 'pairs' and pairsCallObj.node[1] ~= 'ipairs') then + if not pairsCallObj.node + or (pairsCallObj.node.special ~= 'pairs' and pairsCallObj.node.special ~= 'ipairs') then return end diff --git a/test/definition/luadoc.lua b/test/definition/luadoc.lua index 210f5a264..3c0c764bc 100644 --- a/test/definition/luadoc.lua +++ b/test/definition/luadoc.lua @@ -300,6 +300,7 @@ function Foo:() end ---@type table local v1 +local ipairs = ipairs for i, v in ipairs(v1) do print(v.) end From 217aa4e586b1786bc6b82828279b745a29290f4d Mon Sep 17 00:00:00 2001 From: Lei Zhu Date: Tue, 5 Jan 2021 20:50:51 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E9=80=9A=E8=BF=87=E6=89=A9=E5=B1=95=20getA?= =?UTF-8?q?rrayLevel=20=E6=9D=A5=E6=89=BE=E5=88=B0=E5=B1=82=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/parser/guide.lua | 20 +++++++++++++------- script/vm/getDocs.lua | 5 +++++ test/definition/luadoc.lua | 10 ++++++++++ test/hover/init.lua | 2 +- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 5264a2b67..d0e82ba8a 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -1663,12 +1663,20 @@ function m.checkSameSimpleOfRefByDocSource(status, obj, start, pushQueue, mode) end end -local function getArrayLevel(obj) +local function getArrayOrTableLevel(obj) local level = 0 while true do local parent = obj.parent if parent.type == 'doc.type.array' then level = level + 1 + elseif parent.type == 'doc.type.table' then + if obj.type == 'doc.type' then + level = level + 1 + -- else 只存在 obj.type == 'doc.type.name' 的情况,即 table 中的 table,这种是不需要再增加层级的 + end + elseif parent.type == 'doc.type' and parent.parent and parent.parent.type == 'doc.type.table' then + level = level + 1 + parent = parent.parent else break end @@ -1725,12 +1733,10 @@ function m.checkSameSimpleByDoc(status, obj, start, pushQueue, mode) for _, res in ipairs(pieceResult) do pushQueue(res, start, true) end - local parentDocTypeTable = m.getParentDocTypeTable(obj) - if not parentDocTypeTable then - local state = m.getDocState(obj) - if state.type == 'doc.type' and mode == 'ref' then - m.checkSameSimpleOfRefByDocSource(status, state, start - getArrayLevel(obj), pushQueue, mode) - end + + local state = m.getDocState(obj) + if state.type == 'doc.type' and mode == 'ref' then + m.checkSameSimpleOfRefByDocSource(status, state, start - getArrayOrTableLevel(obj), pushQueue, mode) end return true elseif obj.type == 'doc.field' then diff --git a/script/vm/getDocs.lua b/script/vm/getDocs.lua index 632dd1c28..790a9b50d 100644 --- a/script/vm/getDocs.lua +++ b/script/vm/getDocs.lua @@ -16,6 +16,11 @@ local function getTypesOfFile(uri) or src.type == 'doc.class.name' or src.type == 'doc.extends.name' or src.type == 'doc.alias.name' then + if src.type == 'doc.type.name' then + if guide.getParentDocTypeTable(src) then + return + end + end local name = src[1] if name then if not types[name] then diff --git a/test/definition/luadoc.lua b/test/definition/luadoc.lua index 3c0c764bc..5315b5fd6 100644 --- a/test/definition/luadoc.lua +++ b/test/definition/luadoc.lua @@ -331,3 +331,13 @@ for i, v in ipairs(v1) do print(v2.) end ]] + +TEST [[ +---@class Foo +local Foo = {} +function Foo:() end + +---@type table> +local v1 +print(v1[1][1].) +]] diff --git a/test/hover/init.lua b/test/hover/init.lua index 35222f32d..5b3acded2 100644 --- a/test/hover/init.lua +++ b/test/hover/init.lua @@ -1171,7 +1171,7 @@ TEST [[ local ]] [[ -local x: table {} +local x: table ]] --TEST [[