diff options
Diffstat (limited to 'script/parser')
-rw-r--r-- | script/parser/guide.lua | 52 | ||||
-rw-r--r-- | script/parser/luadoc.lua | 1023 | ||||
-rw-r--r-- | script/parser/newparser.lua | 50 |
3 files changed, 614 insertions, 511 deletions
diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 0ece65fc..06169b09 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -16,6 +16,7 @@ local type = type ---@field uri uri ---@field start integer ---@field finish integer +---@field range integer ---@field effect integer ---@field attrs string[] ---@field specials parser.object[] @@ -56,6 +57,14 @@ local type = type ---@field init parser.object ---@field step parser.object ---@field redundant { max: integer, passed: integer } +---@field filter parser.object +---@field loc parser.object +---@field keyword integer[] +---@field casts parser.object[] +---@field mode? '+' | '-' +---@field hasGoTo? true +---@field hasReturn? true +---@field hasBreak? true ---@field _root parser.object ---@class guide @@ -71,6 +80,7 @@ local blockTypes = { ['repeat'] = true, ['do'] = true, ['function'] = true, + ['if'] = true, ['ifblock'] = true, ['elseblock'] = true, ['elseifblock'] = true, @@ -141,6 +151,9 @@ local childMap = { ['doc.see'] = {'name', 'field'}, ['doc.version'] = {'#versions'}, ['doc.diagnostic'] = {'#names'}, + ['doc.as'] = {'as'}, + ['doc.cast'] = {'loc', '#casts'}, + ['doc.cast.block'] = {'extends'}, } ---@type table<string, fun(obj: parser.object, list: parser.object[])> @@ -393,6 +406,7 @@ function m.getRoot(obj) end local parent = obj.parent if not parent then + log.error('Can not find out root:', obj.type) return nil end obj = parent @@ -413,6 +427,7 @@ function m.getUri(obj) return '' end +---@return parser.object? function m.getENV(source, start) if not start then start = 1 @@ -446,19 +461,17 @@ function m.getFunctionVarArgs(func) end --- 获取指定区块中可见的局部变量 ----@param block table ----@param name string {comment = '变量名'} ----@param pos integer {comment = '可见位置'} -function m.getLocal(block, name, pos) - block = m.getBlock(block) - for _ = 1, 10000 do - if not block then - return nil - end - local locals = block.locals - local res +---@param source parser.object +---@param name string # 变量名 +---@param pos integer # 可见位置 +---@return parser.object? +function m.getLocal(source, name, pos) + local root = m.getRoot(source) + local res + m.eachSourceContain(root, pos, function (src) + local locals = src.locals if not locals then - goto CONTINUE + return end for i = 1, #locals do local loc = locals[i] @@ -471,13 +484,8 @@ function m.getLocal(block, name, pos) end end end - if res then - return res, res - end - ::CONTINUE:: - block = m.getParentBlock(block) - end - error('guide.getLocal overstack') + end) + return res end --- 获取指定区块中所有的可见局部变量名称 @@ -602,6 +610,9 @@ local function addChilds(list, obj) end --- 遍历所有包含position的source +---@param ast parser.object +---@param position integer +---@param callback fun(src: parser.object) function m.eachSourceContain(ast, position, callback) local list = { ast } local mark = {} @@ -922,6 +933,7 @@ function m.getKeyNameOfLiteral(obj) end end +---@return string? function m.getKeyName(obj) if not obj then return nil @@ -1027,8 +1039,6 @@ function m.getKeyType(obj) return type(obj.field[1]) elseif tp == 'doc.type.field' then return type(obj.name[1]) - elseif tp == 'dummy' then - return 'string' end if tp == 'doc.field.name' then return type(obj[1]) diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 5a2e1d09..d8e31950 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -2,10 +2,11 @@ local m = require 'lpeglabel' local re = require 'parser.relabel' local guide = require 'parser.guide' local parser = require 'parser.newparser' +local util = require 'utility' local TokenTypes, TokenStarts, TokenFinishs, TokenContents, TokenMarks local Ci, Offset, pushWarning, NextComment, Lines -local parseType +local parseType, parseTypeUnit ---@type any local Parser = re.compile([[ Main <- (Token / Sp)* @@ -52,6 +53,7 @@ Symbol <- ({} { / '...' / '[' / ']' + / '-' !'-' } {}) -> Symbol ]], { @@ -124,6 +126,8 @@ Symbol <- ({} { ---@class parser.object ---@field literal boolean ---@field signs parser.object[] +---@field originalComment parser.object +---@field as? parser.object local function trim(str) return str:match '^%s*(%S+)%s*$' @@ -336,104 +340,6 @@ local function parseSigns(parent) return signs end -local function parseClass(parent) - local result = { - type = 'doc.class', - parent = parent, - fields = {}, - } - result.class = parseName('doc.class.name', result) - if not result.class then - pushWarning { - type = 'LUADOC_MISS_CLASS_NAME', - start = getFinish(), - finish = getFinish(), - } - return nil - end - result.start = getStart() - result.finish = getFinish() - result.signs = parseSigns(result) - if not checkToken('symbol', ':', 1) then - return result - end - nextToken() - - result.extends = {} - - while true do - local extend = parseName('doc.extends.name', result) - or parseTable(result) - if not extend then - pushWarning { - type = 'LUADOC_MISS_CLASS_EXTENDS_NAME', - start = getFinish(), - finish = getFinish(), - } - return result - end - result.extends[#result.extends+1] = extend - result.finish = getFinish() - if not checkToken('symbol', ',', 1) then - break - end - nextToken() - end - return result -end - -local function parseTypeUnitArray(parent, node) - if not checkToken('symbol', '[]', 1) then - return nil - end - nextToken() - local result = { - type = 'doc.type.array', - start = node.start, - finish = getFinish(), - node = node, - parent = parent, - } - node.parent = result - return result -end - -local function parseTypeUnitSign(parent, node) - if not checkToken('symbol', '<', 1) then - return nil - end - nextToken() - local result = { - type = 'doc.type.sign', - start = node.start, - finish = getFinish(), - node = node, - parent = parent, - signs = {}, - } - node.parent = result - while true do - local sign = parseType(result) - if not sign then - pushWarning { - type = 'LUA_DOC_MISS_SIGN', - start = getFinish(), - finish = getFinish(), - } - break - end - result.signs[#result.signs+1] = sign - if checkToken('symbol', ',', 1) then - nextToken() - else - break - end - end - nextSymbolOrError '>' - result.finish = getFinish() - return result -end - local function parseDots(tp, parent) if not checkToken('symbol', '...', 1) then return @@ -527,8 +433,6 @@ local function parseTypeUnitFunction(parent) return typeUnit end -local parseTypeUnit - local function parseFunction(parent) local _, content = peekToken() if content == 'async' then @@ -551,6 +455,58 @@ local function parseFunction(parent) end end +local function parseTypeUnitArray(parent, node) + if not checkToken('symbol', '[]', 1) then + return nil + end + nextToken() + local result = { + type = 'doc.type.array', + start = node.start, + finish = getFinish(), + node = node, + parent = parent, + } + node.parent = result + return result +end + +local function parseTypeUnitSign(parent, node) + if not checkToken('symbol', '<', 1) then + return nil + end + nextToken() + local result = { + type = 'doc.type.sign', + start = node.start, + finish = getFinish(), + node = node, + parent = parent, + signs = {}, + } + node.parent = result + while true do + local sign = parseType(result) + if not sign then + pushWarning { + type = 'LUA_DOC_MISS_SIGN', + start = getFinish(), + finish = getFinish(), + } + break + end + result.signs[#result.signs+1] = sign + if checkToken('symbol', ',', 1) then + nextToken() + else + break + end + end + nextSymbolOrError '>' + result.finish = getFinish() + return result +end + local function parseString(parent) local tp, content = peekToken() if not tp or tp ~= 'string' then @@ -709,6 +665,10 @@ function parseType(parent) if not result.start then result.start = getFinish() end + if checkToken('symbol', '?', 1) then + nextToken() + result.optional = true + end result.finish = getFinish() result.firstFinish = result.finish @@ -785,405 +745,534 @@ function parseType(parent) return result end -local function parseAlias() - local result = { - type = 'doc.alias', - } - result.alias = parseName('doc.alias.name', result) - if not result.alias then - pushWarning { - type = 'LUADOC_MISS_ALIAS_NAME', - start = getFinish(), - finish = getFinish(), - } - return nil - end - result.start = getStart() - result.signs = parseSigns(result) - result.extends = parseType(result) - if not result.extends then - pushWarning { - type = 'LUADOC_MISS_ALIAS_EXTENDS', - start = getFinish(), - finish = getFinish(), - } - return nil - end - result.finish = getFinish() - return result -end - -local function parseParam() - local result = { - type = 'doc.param', - } - result.param = parseName('doc.param.name', result) - or parseDots('doc.param.name', result) - if not result.param then - pushWarning { - type = 'LUADOC_MISS_PARAM_NAME', - start = getFinish(), - finish = getFinish(), +local docSwitch = util.switch() + : case 'class' + : call(function () + local result = { + type = 'doc.class', + fields = {}, } - return nil - end - if checkToken('symbol', '?', 1) then - nextToken() - result.optional = true - end - result.start = result.param.start - result.finish = getFinish() - result.extends = parseType(result) - if not result.extends then - pushWarning { - type = 'LUADOC_MISS_PARAM_EXTENDS', - start = getFinish(), - finish = getFinish(), - } - return result - end - result.finish = getFinish() - result.firstFinish = result.extends.firstFinish - return result -end - -local function parseReturn() - local result = { - type = 'doc.return', - returns = {}, - } - while true do - local docType = parseType(result) - if not docType then - break - end - if not result.start then - result.start = docType.start - end - if checkToken('symbol', '?', 1) then - nextToken() - docType.optional = true + result.class = parseName('doc.class.name', result) + if not result.class then + pushWarning { + type = 'LUADOC_MISS_CLASS_NAME', + start = getFinish(), + finish = getFinish(), + } + return nil end - docType.name = parseName('doc.return.name', docType) - result.returns[#result.returns+1] = docType - if not checkToken('symbol', ',', 1) then - break + result.start = getStart() + result.finish = getFinish() + result.signs = parseSigns(result) + if not checkToken('symbol', ':', 1) then + return result end nextToken() - end - if #result.returns == 0 then - return nil - end - result.finish = getFinish() - return result -end -local function parseField() - local result = { - type = 'doc.field', - } - try(function () - local tp, value = nextToken() - if tp == 'name' then - if value == 'public' - or value == 'protected' - or value == 'private' then - result.visible = value - result.start = getStart() - return true + result.extends = {} + + while true do + local extend = parseName('doc.extends.name', result) + or parseTable(result) + if not extend then + pushWarning { + type = 'LUADOC_MISS_CLASS_EXTENDS_NAME', + start = getFinish(), + finish = getFinish(), + } + return result end + result.extends[#result.extends+1] = extend + result.finish = getFinish() + if not checkToken('symbol', ',', 1) then + break + end + nextToken() end - return false + return result end) - result.field = parseName('doc.field.name', result) - or parseIndexField('doc.field.name', result) - if not result.field then - pushWarning { - type = 'LUADOC_MISS_FIELD_NAME', - start = getFinish(), - finish = getFinish(), - } - return nil - end - if not result.start then - result.start = result.field.start - end - if checkToken('symbol', '?', 1) then - nextToken() - result.optional = true - end - result.extends = parseType(result) - if not result.extends then - pushWarning { - type = 'LUADOC_MISS_FIELD_EXTENDS', - start = getFinish(), - finish = getFinish(), - } - return nil - end - result.finish = getFinish() - return result -end - -local function parseGeneric() - local result = { - type = 'doc.generic', - generics = {}, - } - while true do - local object = { - type = 'doc.generic.object', - parent = result, + : case 'type' + : call(function () + return parseType() + end) + : case 'alias' + : call(function () + local result = { + type = 'doc.alias', } - object.generic = parseName('doc.generic.name', object) - if not object.generic then + result.alias = parseName('doc.alias.name', result) + if not result.alias then pushWarning { - type = 'LUADOC_MISS_GENERIC_NAME', + type = 'LUADOC_MISS_ALIAS_NAME', start = getFinish(), finish = getFinish(), } return nil end - object.start = object.generic.start - if not result.start then - result.start = object.start + result.start = getStart() + result.signs = parseSigns(result) + result.extends = parseType(result) + if not result.extends then + pushWarning { + type = 'LUADOC_MISS_ALIAS_EXTENDS', + start = getFinish(), + finish = getFinish(), + } + return nil end - if checkToken('symbol', ':', 1) then + result.finish = getFinish() + return result + end) + : case 'param' + : call(function () + local result = { + type = 'doc.param', + } + result.param = parseName('doc.param.name', result) + or parseDots('doc.param.name', result) + if not result.param then + pushWarning { + type = 'LUADOC_MISS_PARAM_NAME', + start = getFinish(), + finish = getFinish(), + } + return nil + end + if checkToken('symbol', '?', 1) then nextToken() - object.extends = parseType(object) + result.optional = true end - object.finish = getFinish() - result.generics[#result.generics+1] = object - if not checkToken('symbol', ',', 1) then - break + result.start = result.param.start + result.finish = getFinish() + result.extends = parseType(result) + if not result.extends then + pushWarning { + type = 'LUADOC_MISS_PARAM_EXTENDS', + start = getFinish(), + finish = getFinish(), + } + return result end - nextToken() - end - result.finish = getFinish() - return result -end - -local function parseVararg() - local result = { - type = 'doc.vararg', - } - result.vararg = parseType(result) - if not result.vararg then - pushWarning { - type = 'LUADOC_MISS_VARARG_TYPE', - start = getFinish(), - finish = getFinish(), + result.finish = getFinish() + result.firstFinish = result.extends.firstFinish + return result + end) + : case 'return' + : call(function () + local result = { + type = 'doc.return', + returns = {}, } - return - end - result.start = result.vararg.start - result.finish = result.vararg.finish - return result -end - -local function parseOverload() - local tp, name = peekToken() - if tp ~= 'name' - or (name ~= 'fun' and name ~= 'async') then - pushWarning { - type = 'LUADOC_MISS_FUN_AFTER_OVERLOAD', - start = getFinish(), - finish = getFinish(), + while true do + local docType = parseType(result) + if not docType then + break + end + if not result.start then + result.start = docType.start + end + if checkToken('symbol', '?', 1) then + nextToken() + docType.optional = true + end + docType.name = parseName('doc.return.name', docType) + result.returns[#result.returns+1] = docType + if not checkToken('symbol', ',', 1) then + break + end + nextToken() + end + if #result.returns == 0 then + return nil + end + result.finish = getFinish() + return result + end) + : case 'field' + : call(function () + local result = { + type = 'doc.field', } - return nil - end - local result = { - type = 'doc.overload', - } - result.overload = parseFunction(result) - if not result.overload then - return nil - end - result.overload.parent = result - result.start = result.overload.start - result.finish = result.overload.finish - return result -end - -local function parseDeprecated() - return { - type = 'doc.deprecated', - start = getFinish(), - finish = getFinish(), - } -end - -local function parseMeta() - return { - type = 'doc.meta', - start = getFinish(), - finish = getFinish(), - } -end - -local function parseVersion() - local result = { - type = 'doc.version', - versions = {}, - } - while true do - local tp, text = nextToken() - if not tp then + try(function () + local tp, value = nextToken() + if tp == 'name' then + if value == 'public' + or value == 'protected' + or value == 'private' then + result.visible = value + result.start = getStart() + return true + end + end + return false + end) + result.field = parseName('doc.field.name', result) + or parseIndexField('doc.field.name', result) + if not result.field then pushWarning { - type = 'LUADOC_MISS_VERSION', + type = 'LUADOC_MISS_FIELD_NAME', start = getFinish(), finish = getFinish(), } - break + return nil end if not result.start then - result.start = getStart() + result.start = result.field.start end - local version = { - type = 'doc.version.unit', - parent = result, - start = getStart(), + if checkToken('symbol', '?', 1) then + nextToken() + result.optional = true + end + result.extends = parseType(result) + if not result.extends then + pushWarning { + type = 'LUADOC_MISS_FIELD_EXTENDS', + start = getFinish(), + finish = getFinish(), + } + return nil + end + result.finish = getFinish() + return result + end) + : case 'generic' + : call(function () + local result = { + type = 'doc.generic', + generics = {}, } - if tp == 'symbol' then - if text == '>' then - version.ge = true - elseif text == '<' then - version.le = true + while true do + local object = { + type = 'doc.generic.object', + parent = result, + } + object.generic = parseName('doc.generic.name', object) + if not object.generic then + pushWarning { + type = 'LUADOC_MISS_GENERIC_NAME', + start = getFinish(), + finish = getFinish(), + } + return nil + end + object.start = object.generic.start + if not result.start then + result.start = object.start end - tp, text = nextToken() + if checkToken('symbol', ':', 1) then + nextToken() + object.extends = parseType(object) + end + object.finish = getFinish() + result.generics[#result.generics+1] = object + if not checkToken('symbol', ',', 1) then + break + end + nextToken() end - if tp ~= 'name' then + result.finish = getFinish() + return result + end) + : case 'vararg' + : call(function () + local result = { + type = 'doc.vararg', + } + result.vararg = parseType(result) + if not result.vararg then pushWarning { - type = 'LUADOC_MISS_VERSION', - start = getStart(), + type = 'LUADOC_MISS_VARARG_TYPE', + start = getFinish(), finish = getFinish(), } - break + return end - version.version = tonumber(text) or text - version.finish = getFinish() - result.versions[#result.versions+1] = version - if not checkToken('symbol', ',', 1) then - break + result.start = result.vararg.start + result.finish = result.vararg.finish + return result + end) + : case 'overload' + : call(function () + local tp, name = peekToken() + if tp ~= 'name' + or (name ~= 'fun' and name ~= 'async') then + pushWarning { + type = 'LUADOC_MISS_FUN_AFTER_OVERLOAD', + start = getFinish(), + finish = getFinish(), + } + return nil end - nextToken() - end - if #result.versions == 0 then - return nil - end - result.finish = getFinish() - return result -end - -local function parseSee() - local result = { - type = 'doc.see', - } - result.name = parseName('doc.see.name', result) - if not result.name then - return nil - end - result.start = result.name.start - result.finish = result.name.finish - if checkToken('symbol', '#', 1) then - nextToken() - result.field = parseName('doc.see.field', result) - result.finish = getFinish() - end - return result -end - -local function parseDiagnostic() - local result = { - type = 'doc.diagnostic', - } - local nextTP, mode = nextToken() - if nextTP ~= 'name' then - pushWarning { - type = 'LUADOC_MISS_DIAG_MODE', + local result = { + type = 'doc.overload', + } + result.overload = parseFunction(result) + if not result.overload then + return nil + end + result.overload.parent = result + result.start = result.overload.start + result.finish = result.overload.finish + return result + end) + : case 'deprecated' + : call(function () + return { + type = 'doc.deprecated', start = getFinish(), finish = getFinish(), } - return nil - end - result.mode = mode - result.start = getStart() - result.finish = getFinish() - if mode ~= 'disable-next-line' - and mode ~= 'disable-line' - and mode ~= 'disable' - and mode ~= 'enable' then - pushWarning { - type = 'LUADOC_ERROR_DIAG_MODE', - start = result.start, - finish = result.finish, + end) + : case 'meta' + : call(function () + return { + type = 'doc.meta', + start = getFinish(), + finish = getFinish(), + } + end) + : case 'version' + : call(function () + local result = { + type = 'doc.version', + versions = {}, } - end - - if checkToken('symbol', ':', 1) then - nextToken() - result.names = {} while true do - local name = parseName('doc.diagnostic.name', result) - if not name then + local tp, text = nextToken() + if not tp then pushWarning { - type = 'LUADOC_MISS_DIAG_NAME', + type = 'LUADOC_MISS_VERSION', start = getFinish(), finish = getFinish(), } - return result + break + end + if not result.start then + result.start = getStart() end - result.names[#result.names+1] = name + local version = { + type = 'doc.version.unit', + parent = result, + start = getStart(), + } + if tp == 'symbol' then + if text == '>' then + version.ge = true + elseif text == '<' then + version.le = true + end + tp, text = nextToken() + end + if tp ~= 'name' then + pushWarning { + type = 'LUADOC_MISS_VERSION', + start = getStart(), + finish = getFinish(), + } + break + end + version.version = tonumber(text) or text + version.finish = getFinish() + result.versions[#result.versions+1] = version if not checkToken('symbol', ',', 1) then break end nextToken() end - end + if #result.versions == 0 then + return nil + end + result.finish = getFinish() + return result + end) + : case 'see' + : call(function () + local result = { + type = 'doc.see', + } + result.name = parseName('doc.see.name', result) + if not result.name then + return nil + end + result.start = result.name.start + result.finish = result.name.finish + if checkToken('symbol', '#', 1) then + nextToken() + result.field = parseName('doc.see.field', result) + result.finish = getFinish() + end + return result + end) + : case 'diagnostic' + : call(function () + local result = { + type = 'doc.diagnostic', + } + local nextTP, mode = nextToken() + if nextTP ~= 'name' then + pushWarning { + type = 'LUADOC_MISS_DIAG_MODE', + start = getFinish(), + finish = getFinish(), + } + return nil + end + result.mode = mode + result.start = getStart() + result.finish = getFinish() + if mode ~= 'disable-next-line' + and mode ~= 'disable-line' + and mode ~= 'disable' + and mode ~= 'enable' then + pushWarning { + type = 'LUADOC_ERROR_DIAG_MODE', + start = result.start, + finish = result.finish, + } + end - result.finish = getFinish() + if checkToken('symbol', ':', 1) then + nextToken() + result.names = {} + while true do + local name = parseName('doc.diagnostic.name', result) + if not name then + pushWarning { + type = 'LUADOC_MISS_DIAG_NAME', + start = getFinish(), + finish = getFinish(), + } + return result + end + result.names[#result.names+1] = name + if not checkToken('symbol', ',', 1) then + break + end + nextToken() + end + end - return result -end + result.finish = getFinish() -local function parseModule() - local result = { - type = 'doc.module', - start = getFinish(), - finish = getFinish(), - } - local tp, content = peekToken() - if tp == 'string' then - result.module = content - nextToken() - result.start = getStart() + return result + end) + : case 'module' + : call(function () + local result = { + type = 'doc.module', + start = getFinish(), + finish = getFinish(), + } + local tp, content = peekToken() + if tp == 'string' then + result.module = content + nextToken() + result.start = getStart() + result.finish = getFinish() + result.smark = getMark() + else + pushWarning { + type = 'LUADOC_MISS_MODULE_NAME', + start = getFinish(), + finish = getFinish(), + } + end + return result + end) + : case 'async' + : call(function () + return { + type = 'doc.async', + start = getFinish(), + finish = getFinish(), + } + end) + : case 'nodiscard' + : call(function () + return { + type = 'doc.nodiscard', + start = getFinish(), + finish = getFinish(), + } + end) + : case 'as' + : call(function () + local result = { + type = 'doc.as', + start = getFinish(), + finish = getFinish(), + } + result.as = parseType(result) result.finish = getFinish() - result.smark = getMark() - else - pushWarning { - type = 'LUADOC_MISS_MODULE_NAME', + return result + end) + : case 'cast' + : call(function () + local result = { + type = 'doc.cast', start = getFinish(), finish = getFinish(), + casts = {}, } - end - return result -end -local function parseAsync() - return { - type = 'doc.async', - start = getFinish(), - finish = getFinish(), - } -end + local loc = parseName('doc.cast.name', result) + if not loc then + pushWarning { + type = 'LUADOC_MISS_LOCAL_NAME', + start = getFinish(), + finish = getFinish(), + } + return result + end -local function parseNoDiscard() - return { - type = 'doc.nodiscard', - start = getFinish(), - finish = getFinish(), - } -end + result.loc = loc + result.finish = loc.finish + + while true do + local block = { + type = 'doc.cast.block', + parent = result, + start = getFinish(), + finish = getFinish(), + } + if checkToken('symbol', '+', 1) then + block.mode = '+' + nextToken() + block.start = getStart() + block.finish = getFinish() + elseif checkToken('symbol', '-', 1) then + block.mode = '-' + nextToken() + block.start = getStart() + block.finish = getFinish() + end + + if checkToken('symbol', '?', 1) then + block.optional = true + nextToken() + block.start = block.start or getStart() + block.finish = block.finish + else + block.extends = parseType(block) + if block.extends then + block.start = block.start or block.extends.start + block.finish = block.extends.finish + end + end + + if block.optional or block.extends then + result.casts[#result.casts+1] = block + end + + if checkToken('symbol', ',', 1) then + nextToken() + else + break + end + end + + return result + end) local function convertTokens() local tp, text = nextToken() @@ -1198,41 +1287,7 @@ local function convertTokens() } return nil end - if text == 'class' then - return parseClass() - elseif text == 'type' then - return parseType() - elseif text == 'alias' then - return parseAlias() - elseif text == 'param' then - return parseParam() - elseif text == 'return' then - return parseReturn() - elseif text == 'field' then - return parseField() - elseif text == 'generic' then - return parseGeneric() - elseif text == 'vararg' then - return parseVararg() - elseif text == 'overload' then - return parseOverload() - elseif text == 'deprecated' then - return parseDeprecated() - elseif text == 'meta' then - return parseMeta() - elseif text == 'version' then - return parseVersion() - elseif text == 'see' then - return parseSee() - elseif text == 'diagnostic' then - return parseDiagnostic() - elseif text == 'module' then - return parseModule() - elseif text == 'async' then - return parseAsync() - elseif text == 'nodiscard' then - return parseNoDiscard() - end + return docSwitch(text) end local function trimTailComment(text) @@ -1257,7 +1312,8 @@ end local function buildLuaDoc(comment) local text = comment.text - local _, startPos = text:find('^%-%s*@') + local startPos = (comment.type == 'comment.short' and text:match '^%-%s*@()') + or (comment.type == 'comment.long' and text:match '^@()') if not startPos then return { type = 'doc.comment', @@ -1268,9 +1324,9 @@ local function buildLuaDoc(comment) } end - local doc = text:sub(startPos + 1) + local doc = text:sub(startPos) - parseTokens(doc, comment.start + startPos + 1) + parseTokens(doc, comment.start + startPos) local result = convertTokens() if result then result.range = comment.finish @@ -1313,16 +1369,21 @@ local function isNextLine(binded, doc) return false end local lastDoc = binded[#binded] - if lastDoc.type == 'doc.type' then + if lastDoc.type == 'doc.type' + or lastDoc.type == 'doc.module' then return false end if lastDoc.type == 'doc.class' or lastDoc.type == 'doc.field' then if doc.type ~= 'doc.field' - and doc.type ~= 'doc.comment' then + and doc.type ~= 'doc.comment' + and doc.type ~= 'doc.overload' then return false end end + if doc.type == 'doc.cast' then + return false + end local lastRow = guide.rowColOf(lastDoc.finish) local newRow = guide.rowColOf(doc.start) return newRow - lastRow == 1 @@ -1400,11 +1461,13 @@ local function bindDocsBetween(sources, binded, bindSources, start, finish) if src.start >= start then if src.type == 'local' or src.type == 'self' + or src.type == 'setlocal' or src.type == 'setglobal' or src.type == 'tablefield' or src.type == 'tableindex' or src.type == 'setfield' or src.type == 'setindex' + or src.type == 'setmethod' or src.type == 'function' then src.bindDocs = binded bindSources[#bindSources+1] = src diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index e226417f..630c12c2 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -117,6 +117,7 @@ local Specials = { ['xpcall'] = true, ['pairs'] = true, ['ipairs'] = true, + ['assert'] = true, } local UnarySymbol = { @@ -537,6 +538,7 @@ local function skipComment(isAction) if longComment then longComment.type = 'comment.long' longComment.text = longComment[1] + longComment.mark = longComment[2] longComment[1] = nil longComment[2] = nil State.comms[#State.comms+1] = longComment @@ -689,9 +691,6 @@ local function parseLocalAttrs() end local function createLocal(obj, attrs) - if not obj then - return nil - end obj.type = 'local' obj.effect = obj.finish @@ -2891,7 +2890,11 @@ local function parseLocal() pushActionIntoCurrentChunk(loc) skipSpace() parseMultiVars(loc, parseName, true) - loc.effect = lastRightPosition() + if loc.value then + loc.effect = loc.value.finish + else + loc.effect = loc.finish + end return loc end @@ -2946,13 +2949,22 @@ local function parseReturn() end pushActionIntoCurrentChunk(rtn) for i = #Chunk, 1, -1 do - local func = Chunk[i] - if func.type == 'function' - or func.type == 'main' then - if not func.returns then - func.returns = {} + local block = Chunk[i] + if block.type == 'function' + or block.type == 'main' then + if not block.returns then + block.returns = {} end - func.returns[#func.returns+1] = rtn + block.returns[#block.returns+1] = rtn + break + end + end + for i = #Chunk, 1, -1 do + local block = Chunk[i] + if block.type == 'ifblock' + or block.type == 'elseifblock' + or block.type == 'else' then + block.hasReturn = true break end end @@ -3052,6 +3064,15 @@ local function parseGoTo() break end end + for i = #Chunk, 1, -1 do + local chunk = Chunk[i] + if chunk.type == 'ifblock' + or chunk.type == 'elseifblock' + or chunk.type == 'elseblock' then + chunk.hasGoTo = true + break + end + end pushActionIntoCurrentChunk(action) return action @@ -3586,6 +3607,15 @@ local function parseBreak() break end end + for i = #Chunk, 1, -1 do + local chunk = Chunk[i] + if chunk.type == 'ifblock' + or chunk.type == 'elseifblock' + or chunk.type == 'elseblock' then + chunk.hasBreak = true + break + end + end if not ok and Mode == 'Lua' then pushError { type = 'BREAK_OUTSIDE', |