From 0cc8975ae429489dd3354109df3ad29b7598d85f Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Sep 2024 12:29:35 +0100 Subject: [PATCH] add classes for each parser.object type --- script/parser/compile.lua | 70 +++++++--- script/parser/guide.lua | 284 +++++++++++++++++++++++++++++++++++--- script/parser/luadoc.lua | 2 +- script/vm/compiler.lua | 16 +-- script/vm/doc.lua | 2 +- script/vm/generic.lua | 2 +- script/vm/global.lua | 4 +- script/vm/sign.lua | 2 +- script/vm/tracer.lua | 2 +- script/vm/variable.lua | 2 +- script/vm/visible.lua | 2 +- 11 files changed, 335 insertions(+), 53 deletions(-) diff --git a/script/parser/compile.lua b/script/parser/compile.lua index c007ed512..1261b84cc 100644 --- a/script/parser/compile.lua +++ b/script/parser/compile.lua @@ -816,6 +816,7 @@ local function resolveLable(label, obj) end end +---@param gotos parser.object.goto[] local function resolveGoTo(gotos) for i = 1, #gotos do local action = gotos[i] @@ -848,6 +849,7 @@ local function popChunk() Chunk[#Chunk] = nil end +---@return parser.object.nil? local function parseNil() if Tokens[Index + 1] ~= 'nil' then return nil @@ -861,6 +863,7 @@ local function parseNil() } end +---@return parser.object.boolean? local function parseBoolean() local word = Tokens[Index+1] if word ~= 'true' @@ -1342,6 +1345,7 @@ local function dropNumberTail(offset, integer) return finish + 1 end +---@return (parser.object.number|parser.object.integer)? local function parseNumber() local offset = Tokens[Index] if not offset then @@ -1379,6 +1383,7 @@ local function parseNumber() if neg then number = - number end + --- @type parser.object.number|parser.object.integer local result = { type = integer and 'integer' or 'number', start = startPos, @@ -1412,6 +1417,7 @@ local function isKeyWord(word, nextToken) return false end +---@return parser.object.name? local function parseName(asAction) local word = peekWord() if not word then @@ -1552,11 +1558,13 @@ local function parseExpList(mini) return list end +---@return parser.object.index local function parseIndex() local start = getPosition(Tokens[Index], 'left') Index = Index + 2 skipSpace() local exp = parseExp() + --- @type parser.object.index local index = { type = 'index', start = start, @@ -1578,13 +1586,18 @@ local function parseIndex() return index end +---@return parser.object.table local function parseTable() + local start = getPosition(Tokens[Index], 'left') + local finish = getPosition(Tokens[Index], 'right') + ---@type parser.object.table local tbl = { type = 'table', - start = getPosition(Tokens[Index], 'left'), - finish = getPosition(Tokens[Index], 'right'), + start = start, + finish = finish, + bstart = finish, + bfinish = finish, } - tbl.bstart = tbl.finish Index = Index + 2 local index = 0 local tindex = 0 @@ -1624,6 +1637,7 @@ local function parseTable() wantSep = true skipSpace() local fvalue = parseExp() + ---@type parser.object.tablefield local tfield = { type = 'tablefield', start = name.start, @@ -1634,8 +1648,9 @@ local function parseTable() field = name, value = fvalue, } - name.type = 'field' - name.parent = tfield + local field = name --[[@as parser.object.field]] + field.type = 'field' + field.parent = tfield if fvalue then fvalue.parent = tfield else @@ -1667,6 +1682,7 @@ local function parseTable() end index = index + 1 tindex = tindex + 1 + ---@type parser.object.tableexp local texp = { type = 'tableexp', start = exp.start, @@ -1689,7 +1705,7 @@ local function parseTable() } end wantSep = true - local tindex = parseIndex() + local tindex = parseIndex() --[[@as parser.object.tableindex]] skipSpace() tindex.type = 'tableindex' tindex.node = tbl @@ -1803,7 +1819,12 @@ local function parseSimple(node, funcName) } Index = Index + 2 skipSpace() - local field = parseName(true) + local field = parseName(true) --[[@as parser.object.field?]] + if field then + field.type = 'field' + end + + ---@type parser.object.getfield local getfield = { type = 'getfield', start = node.start, @@ -1814,7 +1835,6 @@ local function parseSimple(node, funcName) } if field then field.parent = getfield - field.type = 'field' if currentName then if node.type == 'getlocal' or node.type == 'getglobal' @@ -1843,7 +1863,8 @@ local function parseSimple(node, funcName) } Index = Index + 2 skipSpace() - local method = parseName(true) + local method = parseName(true) --[[@as parser.object.method?]] + ---@type parser.object.getmethod local getmethod = { type = 'getmethod', start = node.start, @@ -1904,12 +1925,14 @@ local function parseSimple(node, funcName) break end local tbl = parseTable() + ---@type parser.object.call local call = { type = 'call', start = node.start, finish = tbl.finish, node = node, } + ---@type parser.object.callargs local args = { type = 'callargs', start = tbl.start, @@ -1970,7 +1993,7 @@ local function parseSimple(node, funcName) node.parent = call node = call else - local index = parseIndex() + local index = parseIndex() --[[@as parser.object.getindex]] local bstart = index.start index.type = 'getindex' index.start = node.start @@ -2279,6 +2302,7 @@ local function parseParams(params, isLambda) return params end +---@return parser.object.function local function parseFunction(isLocal, isAction) local funcLeft = getPosition(Tokens[Index], 'left') local funcRight = getPosition(Tokens[Index] + 7, 'right') @@ -2292,6 +2316,7 @@ local function parseFunction(isLocal, isAction) [2] = funcRight, }, } + ---@cast func parser.object.function Index = Index + 2 skipSpace(true) local hasLeftParen = Tokens[Index + 1] == '(' @@ -2463,6 +2488,7 @@ local function parseLambda(isDoublePipe) if child then -- create dummy return + ---@type parser.object.return local rtn = { type = 'return', start = child.start, @@ -2741,6 +2767,7 @@ function parseExp(asAction, level) missExp() end end + ---@type parser.object.binary local bin = { type = 'binary', start = exp.start, @@ -3199,7 +3226,11 @@ local function parseLabel() local left = getPosition(Tokens[Index], 'left') Index = Index + 2 skipSpace() - local label = parseName() + local label = parseName() --[[@as parser.object.label]] + if label then + label.type = 'label' + end + skipSpace() if not label then @@ -3218,7 +3249,6 @@ local function parseLabel() return nil end - label.type = 'label' pushActionIntoCurrentChunk(label) local block = guide.getBlock(label) @@ -3262,20 +3292,23 @@ local function parseLabel() return label end +---@return parser.object.goto? local function parseGoTo() local start = getPosition(Tokens[Index], 'left') Index = Index + 2 skipSpace() - local action = parseName() + local action = parseName() --[[@as parser.object.goto]] + if action then + action.type = 'goto' + action.keyStart = start + end + if not action then missName() return nil end - action.type = 'goto' - action.keyStart = start - for i = #Chunk, 1, -1 do local chunk = Chunk[i] if chunk.type == 'function' @@ -3305,6 +3338,7 @@ local function parseIfBlock(parent) local ifLeft = getPosition(Tokens[Index], 'left') local ifRight = getPosition(Tokens[Index] + 1, 'right') Index = Index + 2 + ---@type parser.object.ifblock local ifblock = { type = 'ifblock', parent = parent, @@ -3712,6 +3746,7 @@ local function parseFor() end local function parseWhile() + ---@type parser.object.while local action = { type = 'while', start = getPosition(Tokens[Index], 'left'), @@ -3840,6 +3875,7 @@ local function parseRepeat() return action end +---@return parser.object.break local function parseBreak() local returnLeft = getPosition(Tokens[Index], 'left') local returnRight = getPosition(Tokens[Index] + #Tokens[Index + 1] - 1, 'right') @@ -3952,7 +3988,7 @@ function parseAction() exp.parent = name if name.type == 'setlocal' then local loc = name.node - if loc.attrs then + if loc and loc.attrs then pushError { type = 'SET_CONST', start = name.start, diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 429785125..0aef537bd 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -1,12 +1,271 @@ local error = error local type = type ----@class parser.object ----@field bindDocs parser.object[] +---@alias parser.object +---| parser.object.binary +---| parser.object.boolean +---| parser.object.break +---| parser.object.getglobal +---| parser.object.call +---| parser.object.callargs +---| parser.object.elseifblock +---| parser.object.field +---| parser.object.function +---| parser.object.getfield +---| parser.object.getindex +---| parser.object.getlocal +---| parser.object.getmethod +---| parser.object.goto +---| parser.object.ifblock +---| parser.object.index +---| parser.object.integer +---| parser.object.label +---| parser.object.local +---| parser.object.method +---| parser.object.name +---| parser.object.nil +---| parser.object.number +---| parser.object.paren +---| parser.object.repeat +---| parser.object.return +---| parser.object.self +---| parser.object.setfield +---| parser.object.setindex +---| parser.object.setlocal +---| parser.object.table +---| parser.object.tableexp +---| parser.object.tablefield +---| parser.object.tableindex +---| parser.object.while +--- +--- Everything else +---| parser.object.other + +---@class parser.object.base +---@field start integer +---@field vstart integer +---@field finish integer +---@field uri? uri +---@field parent? parser.object +---@field hasExit? true +---@field docs parser.object.other +---@field bindDocs? parser.object.other[] +--- +--- Used to mark expressions that are redundant +---@field redundant? { max: integer, passed: integer } +--- +---@field package _root parser.object +---@field package _eachCache? parser.object[] +---@field package _isGlobal? boolean +---@field package _typeCache? parser.object[][] + +---@class parser.object.nil : parser.object.base +---@field type 'nil' + +---@class parser.object.boolean : parser.object.base +---@field type 'boolean' +---@field [1] boolean value + +---@class parser.object.integer : parser.object.base +---@field type 'integer' +---@field [1] integer value + +---@class parser.object.number : parser.object.base +---@field type 'number' +---@field [1] number value + +---@class parser.object.name : parser.object.base +---@field type 'name' +---@field [1] string value + +---@class parser.object.field : parser.object.base +---@field type 'field' +---@field [1] string value + +---@class parser.object.method : parser.object.base +---@field type 'method' +---@field [1] string value + +---@class parser.object.call : parser.object.base +---@field type 'call' +---@field args? parser.object.callargs +---@field node parser.object +---@field extParent? parser.object[] + +---@class parser.object.callargs : parser.object.base +---@field type 'callargs' +---@field parent parser.object +---@field [integer] parser.object + +---@class parser.object.getmethod : parser.object.base +---@field type 'getmethod' +---@field node parser.object +---@field colon { type: 'colon', start: integer, finish: integer } +---@field method? parser.object.method + +---@class parser.object.getfield : parser.object.base +---@field type 'getfield' +---@field dot { type: 'dot', start: integer, finish: integer } +---@field field? parser.object.field +---@field node parser.object + +---@class parser.object.setfield : parser.object.base +---@field type 'setfield' +---@field node parser.object +---@field field? parser.object.field +---@field value? parser.object + +---@class parser.object.getindex : parser.object.base +---@field type 'getindex' +---@field index? parser.object +---@field node parser.object + +---@class parser.object.setindex : parser.object.base +---@field type 'setindex' +---@field node parser.object +---@field index? parser.object.index +---@field value? parser.object + +---@class parser.object.getlocal : parser.object.base +---@field type 'getlocal' +---@field node parser.object.local|parser.object.self +---@field [1] string Name + +---@class parser.object.setlocal : parser.object.base +---@field type 'setlocal' +---@field node parser.object.local|parser.object.self +---@field value parser.object + +---@class parser.object.table : parser.object.base +---@field type 'table' +---@field bstart integer +---@field bfinish integer +---@field [integer] parser.object + +---@class parser.object.index : parser.object.base +---@field type 'index' +---@field index? parser.object + +---@class parser.object.tablefield : parser.object.base +---@field type 'tablefield' +---@field field parser.object +---@field value? parser.object +---@field node? parser.object + +---@class parser.object.tableindex : parser.object.base +---@field type 'tableindex' +---@field index? parser.object +---@field node parser.object.table +---@field range? integer +---@field value? parser.object + +---@class parser.object.tableexp : parser.object.base +---@field type 'tableexp' +---@field value parser.object +---@field tindex? integer + +---@class parser.object.break : parser.object.base +---@field type 'break' + +---@class parser.object.local : parser.object.base +---@field type 'local' +---@field effect integer +---@field attrs? parser.object +---@field ref? parser.object[] References to local +---@field locPos? integer Start position of the 'local' keyword +---@field value? parser.object +---@field tag? '_ENV' +---@field [1] string Name of local variable + +---@class parser.object.self : parser.object.local +---@field type 'self' +---@field parent parser.object + +---@class parser.object.goto : parser.object.base +---@field type 'goto' +---@field node? parser.object.label +---@field keyStart integer +---@field [1] string name + +---@class parser.object.return : parser.object.base +---@field type 'return' +---@field [1] parser.object + +---@class parser.binop +---@field type 'or' | 'and' | '<=' | '>=' | '<' | '>' | '~=' | '==' | '|' | '~' | '&' | '<<' | '>>' | '..' | '+' | '-' | '*' | '//' | '/' | '%' | '^' +---@field start integer +---@field finish integer + +---@class parser.object.binary : parser.object.base +---@field type 'binary +---@field op parser.binop +---@field [1] parser.object +---@field [2] parser.object? + +---@class parser.object.label : parser.object.base +---@field type 'label' +---@field ref? parser.object.goto[] References to label +---@field [1] string value + +---@class parser.object.getglobal : parser.object.base +---@field type 'getglobal' +---@field node parser.object.local +---@field value parser.object +---@field [1] string Name + +---@class parser.object.paren : parser.object.base +---@field type 'paren' +---@field exp? parser.object + +---@class parser.object.block.base : parser.object.base +---@field bstart integer Block start +---@field bfinish? integer Block end +---@field labels? table +---@field locals parser.object.other[] +---@field gotos parser.object.goto[] +---@field breaks parser.object.break[] +---@field hasGoTo? true +---@field hasReturn? true +---@field hasBreak? true +---@field [integer] parser.object + +---@class parser.object.ifblock : parser.object.block.base +---@field type 'ifblock' +---@field parent parser.object.other +---@field filter? parser.object? +---@field keyword [integer,integer] + +---@class parser.object.elseifblock : parser.object.block.base +---@field type 'elseifblock' +---@field parent parser.object.other +---@field filter? parser.object? +---@field keyword [integer,integer] + +---@class parser.object.repeat : parser.object.block.base +---@field type 'repeat' +---@field filter? parser.object +---@field keyword [integer,integer, integer, integer] + +---@class parser.object.while : parser.object.block.base +---@field type 'while' +---@field keyword [integer,integer] +---@field filter? parser.object + +---@class parser.object.function : parser.object.block.base +---@field type 'function' +---@field keyword [integer,integer] +---@field vararg? parser.object.other +---@field args? parser.object.other +---@field name? parser.object +---@field parent parser.object +--- +---@field returns? parser.object.other[] +---@field locPos? integer Start position of the 'local' keyword + +---@class parser.object.other : parser.object.base ---@field bindGroup parser.object[] ---@field bindSource parser.object ---@field value parser.object ----@field parent parser.object ---@field type string ---@field special string ---@field tag string @@ -16,9 +275,6 @@ local type = type ---@field breaks? parser.object[] ---@field exps parser.object[] ---@field keys parser.object ----@field uri uri ----@field start integer ----@field finish integer ---@field range integer ---@field effect integer ---@field bstart integer @@ -33,9 +289,6 @@ local type = type ---@field extends parser.object[]|parser.object ---@field types parser.object[] ---@field fields parser.object[] ----@field tkey parser.object ----@field tvalue parser.object ----@field tindex integer ---@field op parser.object ---@field next parser.object ---@field docParam parser.object @@ -57,15 +310,12 @@ local type = type ---@field returnIndex integer ---@field assignIndex integer ---@field docIndex integer ----@field docs parser.object ---@field state table ---@field comment table ---@field optional boolean ---@field max parser.object ---@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[] @@ -73,14 +323,7 @@ local type = type ---@field hasGoTo? true ---@field hasReturn? true ---@field hasBreak? true ----@field hasExit? true ---@field [integer] parser.object|any ----@field dot { type: string, start: integer, finish: integer } ----@field colon { type: string, start: integer, finish: integer } ----@field package _root parser.object ----@field package _eachCache? parser.object[] ----@field package _isGlobal? boolean ----@field package _typeCache? parser.object[][] ---@class guide ---@field debugMode boolean @@ -346,6 +589,7 @@ function m.getBlock(obj) end obj = obj.parent end + ---@cast obj -? -- make stack local stack = {} for _ = 1, 10 do @@ -476,6 +720,7 @@ function m.getUri(obj) if obj.uri then return obj.uri end + ---@cast obj parser.object local root = m.getRoot(obj) if root then return root.uri or '' @@ -1159,6 +1404,7 @@ function m.isGlobal(source) or source.type == 'getfield' or source.type == 'setindex' or source.type == 'getindex' then + --- @type parser.object local current = source while current do local node = current.node diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index edffbc4d0..70db251d8 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -139,7 +139,7 @@ Symbol <- ({} { ---@alias parser.visibleType 'public' | 'protected' | 'private' | 'package' ----@class parser.object +---@class parser.object.base ---@field literal boolean ---@field signs parser.object[] ---@field originalComment parser.object diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua index aa51bcddf..1f92a5d8c 100644 --- a/script/vm/compiler.lua +++ b/script/vm/compiler.lua @@ -7,7 +7,7 @@ local files = require 'files' local vm = require 'vm.vm' local plugin = require 'plugin' ----@class parser.object +---@class parser.object.base ---@field _compiledNodes boolean ---@field _node vm.node ---@field cindex integer @@ -825,7 +825,7 @@ end ---@return vm.node ---@return parser.object? function vm.selectNode(list, index) - local exp + local exp ---@type parser.object if list[index] then exp = list[index] index = 1 @@ -1056,7 +1056,7 @@ function vm.compileCallArg(arg, call, index) return vm.getNode(arg) end ----@class parser.object +---@class parser.object.base ---@field package _iterator? table ---@field package _iterArgs? table ---@field package _iterVars? table @@ -1168,9 +1168,10 @@ local function compileFunctionParam(func, source) end end + local parent = func.parent local derviationParam = config.get(guide.getUri(func), 'Lua.type.inferParamType') - if derviationParam and func.parent.type == 'local' and func.parent.ref then - local refs = func.parent.ref + if derviationParam and parent.type == 'local' and parent.ref then + local refs = assert(parent.ref) local found for _, ref in ipairs(refs) do if ref.parent.type ~= 'call' then @@ -1191,7 +1192,6 @@ local function compileFunctionParam(func, source) end do - local parent = func.parent local key = vm.getKeyName(parent) local classDef = vm.getParentClass(parent) local suri = guide.getUri(func) @@ -1271,7 +1271,7 @@ local function compileLocal(source) end end if source.parent.type == 'funcargs' and not hasMarkDoc and not hasMarkParam then - local func = source.parent.parent + local func = source.parent.parent --[[@as parser.object.function]] local interfaces = plugin.getPluginInterfaces(guide.getUri(source)) local hasDocArg = false if interfaces then @@ -1653,7 +1653,7 @@ local compilerSwitch = util.switch() : case 'function.return' ---@param source parser.object : call(function (source) - local func = source.parent + local func = source.parent --[[@as parser.object.function]] local index = source.returnIndex local hasMarkDoc if func.bindDocs then diff --git a/script/vm/doc.lua b/script/vm/doc.lua index c936d2f3f..4c33659c4 100644 --- a/script/vm/doc.lua +++ b/script/vm/doc.lua @@ -4,7 +4,7 @@ local guide = require 'parser.guide' local vm = require 'vm.vm' local config = require 'config' ----@class parser.object +---@class parser.object.base ---@field package _castTargetHead? parser.object | vm.global | false ---@field package _validVersions? table ---@field package _deprecated? parser.object | false diff --git a/script/vm/generic.lua b/script/vm/generic.lua index ed832d9bd..4bc6c2350 100644 --- a/script/vm/generic.lua +++ b/script/vm/generic.lua @@ -1,7 +1,7 @@ ---@class vm local vm = require 'vm.vm' ----@class parser.object +---@class parser.object.base ---@field package _generic vm.generic ---@field package _resolved vm.node diff --git a/script/vm/global.lua b/script/vm/global.lua index ed2b4802a..1f9e597c0 100644 --- a/script/vm/global.lua +++ b/script/vm/global.lua @@ -10,7 +10,7 @@ local allGlobals = {} ---@type table> local globalSubs = util.multiTable(2) ----@class parser.object +---@class parser.object.base ---@field package _globalBase parser.object ---@field package _globalBaseMap table ---@field global vm.global @@ -168,7 +168,7 @@ local function createGlobal(name, cate) }, mt) end ----@class parser.object +---@class parser.object.base ---@field package _globalNode vm.global|false ---@field package _enums? parser.object[] diff --git a/script/vm/sign.lua b/script/vm/sign.lua index ddc8258f5..69239c8bd 100644 --- a/script/vm/sign.lua +++ b/script/vm/sign.lua @@ -273,7 +273,7 @@ function vm.createSign() return genericMgr end ----@class parser.object +---@class parser.object.base ---@field package _sign vm.sign|false|nil ---@param source parser.object diff --git a/script/vm/tracer.lua b/script/vm/tracer.lua index ef94cc9e8..d2693eca4 100644 --- a/script/vm/tracer.lua +++ b/script/vm/tracer.lua @@ -3,7 +3,7 @@ local vm = require 'vm.vm' local guide = require 'parser.guide' local util = require 'utility' ----@class parser.object +---@class parser.object.base ---@field package _tracer? vm.tracer ---@field package _casts? parser.object[] diff --git a/script/vm/variable.lua b/script/vm/variable.lua index 150ad18b5..ca04191c2 100644 --- a/script/vm/variable.lua +++ b/script/vm/variable.lua @@ -27,7 +27,7 @@ local function createVariable(root, id) return variable end ----@class parser.object +---@class parser.object.base ---@field package _variableNode vm.variable|false ---@field package _variableNodes table diff --git a/script/vm/visible.lua b/script/vm/visible.lua index 6d78596b6..ce760ff5c 100644 --- a/script/vm/visible.lua +++ b/script/vm/visible.lua @@ -4,7 +4,7 @@ local guide = require 'parser.guide' local config = require 'config' local glob = require 'glob' ----@class parser.object +---@class parser.object.base ---@field package _visibleType? parser.visibleType local function globMatch(patterns, fieldName)