diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-07-18 01:07:30 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2022-07-18 01:07:30 +0800 |
commit | dca751cf110a96a351c8cadc049ac364dc41a4dd (patch) | |
tree | 785d41633d4ee6bfa3e97ec25043c5cedbc6da28 /script | |
parent | 04c671114d1d4c4bcfbad74c8341b24844552865 (diff) | |
download | lua-language-server-dca751cf110a96a351c8cadc049ac364dc41a4dd.zip |
#1255
diagnostic for enum
Diffstat (limited to 'script')
-rw-r--r-- | script/core/hover/init.lua | 28 | ||||
-rw-r--r-- | script/core/hover/label.lua | 5 | ||||
-rw-r--r-- | script/parser/guide.lua | 2 | ||||
-rw-r--r-- | script/parser/luadoc.lua | 3 | ||||
-rw-r--r-- | script/vm/compiler.lua | 8 | ||||
-rw-r--r-- | script/vm/global.lua | 24 | ||||
-rw-r--r-- | script/vm/type.lua | 54 |
7 files changed, 103 insertions, 21 deletions
diff --git a/script/core/hover/init.lua b/script/core/hover/init.lua index 949156aa..5a65cbce 100644 --- a/script/core/hover/init.lua +++ b/script/core/hover/init.lua @@ -92,19 +92,21 @@ local function getHover(source) end local accept = { - ['local'] = true, - ['setlocal'] = true, - ['getlocal'] = true, - ['setglobal'] = true, - ['getglobal'] = true, - ['field'] = true, - ['method'] = true, - ['string'] = true, - ['number'] = true, - ['integer'] = true, - ['doc.type.name'] = true, - ['function'] = true, - ['doc.module'] = true, + ['local'] = true, + ['setlocal'] = true, + ['getlocal'] = true, + ['setglobal'] = true, + ['getglobal'] = true, + ['field'] = true, + ['method'] = true, + ['string'] = true, + ['number'] = true, + ['integer'] = true, + ['doc.type.name'] = true, + ['doc.class.name'] = true, + ['doc.enum.name'] = true, + ['function'] = true, + ['doc.module'] = true, } ---@async diff --git a/script/core/hover/label.lua b/script/core/hover/label.lua index d5c0a11e..5c502ec1 100644 --- a/script/core/hover/label.lua +++ b/script/core/hover/label.lua @@ -36,7 +36,7 @@ local function asDocTypeName(source) return '(alias) ' .. doc.alias[1] .. ' ' .. lang.script('HOVER_EXTENDS', vm.getInfer(doc.extends):view(guide.getUri(source))) end if doc.type == 'doc.enum' then - return '(enum) ' .. doc.enum[1] .. ' ' .. lang.script('HOVER_EXTENDS', vm.getInfer(doc.extends):view(guide.getUri(source))) + return '(enum) ' .. doc.enum[1] end end end @@ -216,7 +216,8 @@ return function (source, oop) elseif source.type == 'number' or source.type == 'integer' then return asNumber(source) - elseif source.type == 'doc.type.name' then + elseif source.type == 'doc.type.name' + or source.type == 'doc.enum.name' then return asDocTypeName(source) elseif source.type == 'doc.field' then return asDocFieldName(source) diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 8506f7c5..e4faf47f 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -4,7 +4,7 @@ local type = type ---@class parser.object ---@field bindDocs parser.object[] ---@field bindGroup parser.object[] ----@field bindSource parser.object[] +---@field bindSource parser.object ---@field value parser.object ---@field parent parser.object ---@field type string diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 68286fab..6bf1a338 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -1829,7 +1829,8 @@ local function bindCommentsAndFields(binded) end bindCommentsToDoc(doc, comments) comments = {} - elseif doc.type == 'doc.alias' then + elseif doc.type == 'doc.alias' + or doc.type == 'doc.enum' then bindCommentsToDoc(doc, comments) comments = {} elseif doc.type == 'doc.comment' then diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua index d94dd1f4..04a4f0c5 100644 --- a/script/vm/compiler.lua +++ b/script/vm/compiler.lua @@ -32,10 +32,6 @@ local function bindDocs(source) vm.setNode(source, vm.compileNode(doc)) return true end - if doc.type == 'doc.enum' then - vm.setNode(source, vm.compileNode(doc)) - return true - end if doc.type == 'doc.param' then local node = vm.compileNode(doc) if doc.optional then @@ -1586,6 +1582,10 @@ local compilerSwitch = util.switch() : call(function (source) vm.setNode(source, vm.compileNode(source.parent)) end) + : case 'doc.enum.name' + : call(function (source) + vm.setNode(source, vm.compileNode(source.parent)) + end) : case 'doc.field' : call(function (source) if not source.extends then diff --git a/script/vm/global.lua b/script/vm/global.lua index 3fe1bee8..d9509fe7 100644 --- a/script/vm/global.lua +++ b/script/vm/global.lua @@ -130,6 +130,7 @@ end ---@class parser.object ---@field _globalNode vm.global|false +---@field _enums? (string|integer)[] ---@type table<string, vm.global> local allGlobals = {} @@ -329,6 +330,29 @@ local compilerGlobalSwitch = util.switch() local enum = vm.declareGlobal('type', name, uri) enum:addSet(uri, source) source._globalNode = enum + + local tbl = source.bindSource and source.bindSource.value + if not tbl or tbl.type ~= 'table' then + return + end + source._enums = {} + for _, field in ipairs(tbl) do + if field.type == 'tablefield' + or field.type == 'tableindex' then + if not field.value then + goto CONTINUE + end + local key = guide.getKeyName(field) + if not key then + goto CONTINUE + end + if field.value.type == 'integer' + or field.value.type == 'string' then + source._enums[#source._enums+1] = field.value[1] + end + ::CONTINUE:: + end + end end) : case 'doc.type.name' : call(function (source) diff --git a/script/vm/type.lua b/script/vm/type.lua index 4aa1f8c8..30d509ce 100644 --- a/script/vm/type.lua +++ b/script/vm/type.lua @@ -2,6 +2,7 @@ local vm = require 'vm.vm' local guide = require 'parser.guide' local config = require 'config.config' +local util = require 'utility' ---@param object vm.node.object ---@return string? @@ -40,6 +41,51 @@ local function getNodeName(object) return nil end +---@param parentName string +---@param child vm.node.object +---@param uri uri +---@return boolean? +local function checkEnum(parentName, child, uri) + local parentClass = vm.getGlobal('type', parentName) + if not parentClass then + return nil + end + for _, set in ipairs(parentClass:getSets(uri)) do + if set.type == 'doc.enum' then + if child.type ~= 'string' + and child.type ~= 'doc.type.string' + and child.type ~= 'integer' + and child.type ~= 'number' + and child.type ~= 'doc.type.integer' then + return false + end + return util.arrayHas(set._enums, child[1]) + end + end + + return nil +end + +---@param parent vm.node.object +---@param child vm.node.object +---@return boolean +local function checkValue(parent, child) + if parent.type == 'doc.type.integer' then + if child.type == 'integer' + or child.type == 'doc.type.integer' + or child.type == 'number' then + return parent[1] == child[1] + end + elseif parent.type == 'doc.type.string' then + if child.type == 'string' + or child.type == 'doc.type.string' then + return parent[1] == child[1] + end + end + + return true +end + ---@param uri uri ---@param child vm.node|string|vm.node.object ---@param parent vm.node|string|vm.node.object @@ -121,6 +167,9 @@ function vm.isSubType(uri, child, parent, mark) end if childName == parentName then + if not checkValue(parent, child) then + return false + end return true end @@ -144,6 +193,11 @@ function vm.isSubType(uri, child, parent, mark) return true end + local isEnum = checkEnum(parentName, child, uri) + if isEnum ~= nil then + return isEnum + end + -- TODO: check duck if parentName == 'table' and not guide.isBasicType(childName) then return true |