From 2a29458c86628a2af20da4ebeb39a8f81d4ea53a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Tue, 14 Sep 2021 16:59:55 +0800 Subject: update parser --- script/parser/compile.lua | 17 +- script/parser/grammar.lua | 2 +- script/parser/guide.lua | 4 +- script/parser/init.lua | 1 + script/parser/lines.lua | 2 +- script/parser/luadoc.lua | 4 +- script/parser/newparser.lua | 3528 +++++++++++++++++++++++++++++++++++++++++++ script/parser/parse.lua | 17 +- script/parser/tokens.lua | 38 + 9 files changed, 3595 insertions(+), 18 deletions(-) create mode 100644 script/parser/newparser.lua create mode 100644 script/parser/tokens.lua diff --git a/script/parser/compile.lua b/script/parser/compile.lua index 207664cc..d6c6a526 100644 --- a/script/parser/compile.lua +++ b/script/parser/compile.lua @@ -1,4 +1,6 @@ local guide = require 'parser.guide' +local parse = require 'parser.parse' +local newparser = require 'parser.newparser' local type = type local tableInsert = table.insert local pairs = pairs @@ -566,8 +568,12 @@ local function PostCompile() end end -return function (self, lua, mode, version, options) - local state, err = self:parse(lua, mode, version, options) +return function (lua, mode, version, options) + do + local state, err = newparser(lua, mode, version, options) + return state, err + end + local state, err = parse(lua, mode, version, options) if not state then return nil, err end @@ -576,11 +582,7 @@ return function (self, lua, mode, version, options) --end local clock = os.clock() pushError = state.pushError - if version == 'Lua 5.1' or version == 'LuaJIT' then - ENVMode = '@fenv' - else - ENVMode = '_ENV' - end + ENVMode = state.ENVMode Compiled = {} GoToTag = {} LocalCount = 0 @@ -590,7 +592,6 @@ return function (self, lua, mode, version, options) Root.state = state end Options = options - state.ENVMode = ENVMode if type(state.ast) == 'table' then Compile(state.ast) end diff --git a/script/parser/grammar.lua b/script/parser/grammar.lua index 1a3913e0..154bd7ba 100644 --- a/script/parser/grammar.lua +++ b/script/parser/grammar.lua @@ -557,7 +557,7 @@ Lua <- Head? Head <- '#' (!%nl .)* ]] -return function (self, lua, mode) +return function (lua, mode) local gram = compiled[mode] or compiled['Lua'] local r, _, pos = gram:match(lua) if not r then diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 6dcfbf95..e5e9ead1 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -85,6 +85,7 @@ local breakBlockTypes = { ['in'] = true, ['loop'] = true, ['repeat'] = true, + ['for'] = true, } local childMap = { @@ -722,9 +723,6 @@ function m.eachSource(ast, callback) end --- 获取指定的 special ----@param ast parser.guide.object ----@param name string ----@param callback fun(source: parser.guide.object) function m.eachSpecialOf(ast, name, callback) local root = m.getRoot(ast) if not root.specials then diff --git a/script/parser/init.lua b/script/parser/init.lua index ba40d145..219f8900 100644 --- a/script/parser/init.lua +++ b/script/parser/init.lua @@ -7,6 +7,7 @@ local api = { lines = require 'parser.lines', guide = require 'parser.guide', luadoc = require 'parser.luadoc', + tokens = require 'parser.tokens', } return api diff --git a/script/parser/lines.lua b/script/parser/lines.lua index 1aba0ae5..06023df1 100644 --- a/script/parser/lines.lua +++ b/script/parser/lines.lua @@ -2,7 +2,7 @@ local sfind = string.find local ssub = string.sub ---@param text string -return function (self, text) +return function (text) local current = 1 local lines = {} local i = 1 diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index da612e60..26341571 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -1375,7 +1375,7 @@ local function bindDocs(state) bindDoc(sources, Lines, binded) end -return function (_, state) +return function (state) local ast = state.ast local comments = state.comms table.sort(comments, function (a, b) @@ -1389,7 +1389,7 @@ return function (_, state) pushError = state.pushError - Lines = lines(nil, state.lua) + Lines = lines(state.lua) local ci = 1 NextComment = function (offset, peek) diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua new file mode 100644 index 00000000..7fd0ec31 --- /dev/null +++ b/script/parser/newparser.lua @@ -0,0 +1,3528 @@ +local tokens = require 'parser.tokens' +local guide = require 'parser.guide' + +local sbyte = string.byte +local sfind = string.find +local smatch = string.match +local sgsub = string.gsub +local ssub = string.sub +local schar = string.char +local supper = string.upper +local uchar = utf8.char +local tconcat = table.concat +local tinsert = table.insert +local tointeger = math.tointeger +local mtype = math.type +local tonumber = tonumber +local maxinteger = math.maxinteger +local assert = assert +local next = next + +_ENV = nil + +---@alias parser.position integer + +---@param str string +---@return table +local function stringToCharMap(str) + local map = {} + local pos = 1 + while pos <= #str do + local byte = sbyte(str, pos, pos) + map[schar(byte)] = true + pos = pos + 1 + if ssub(str, pos, pos) == '-' + and pos < #str then + pos = pos + 1 + local byte2 = sbyte(str, pos, pos) + assert(byte < byte2) + for b = byte + 1, byte2 do + map[schar(b)] = true + end + pos = pos + 1 + end + end + return map +end + +local CharMapNumber = stringToCharMap '0-9' +local CharMapN16 = stringToCharMap 'xX' +local CharMapN2 = stringToCharMap 'bB' +local CharMapE10 = stringToCharMap 'eE' +local CharMapE16 = stringToCharMap 'pP' +local CharMapSign = stringToCharMap '+-' +local CharMapSB = stringToCharMap 'ao|~&=<>.*/%^+-' +local CharMapSU = stringToCharMap 'n#~!-' +local CharMapSimple = stringToCharMap '.:([\'"{' +local CharMapStrSH = stringToCharMap '\'"' +local CharMapStrLH = stringToCharMap '[' +local CharMapTSep = stringToCharMap ',;' +local CharMapWord = stringToCharMap '_a-zA-Z\x80-\xff' + +local EscMap = { + ['a'] = '\a', + ['b'] = '\b', + ['f'] = '\f', + ['n'] = '\n', + ['r'] = '\r', + ['t'] = '\t', + ['v'] = '\v', + ['\\'] = '\\', + ['\''] = '\'', + ['\"'] = '\"', +} + +local NLMap = { + ['\n'] = true, + ['\r'] = true, + ['\r\n'] = true, +} + +local LineMulti = 10000 + +-- goto 单独处理 +local KeyWord = { + ['and'] = true, + ['break'] = true, + ['do'] = true, + ['else'] = true, + ['elseif'] = true, + ['end'] = true, + ['false'] = true, + ['for'] = true, + ['function'] = true, + ['if'] = true, + ['in'] = true, + ['local'] = true, + ['nil'] = true, + ['not'] = true, + ['or'] = true, + ['repeat'] = true, + ['return'] = true, + ['then'] = true, + ['true'] = true, + ['until'] = true, + ['while'] = true, +} + +local Specials = { + ['_G'] = true, + ['rawset'] = true, + ['rawget'] = true, + ['setmetatable'] = true, + ['require'] = true, + ['dofile'] = true, + ['loadfile'] = true, + ['pcall'] = true, + ['xpcall'] = true, + ['pairs'] = true, + ['ipairs'] = true, +} + +local UnarySymbol = { + ['not'] = 11, + ['#'] = 11, + ['~'] = 11, + ['-'] = 11, +} + +local BinarySymbol = { + ['or'] = 1, + ['and'] = 2, + ['<='] = 3, + ['>='] = 3, + ['<'] = 3, + ['>'] = 3, + ['~='] = 3, + ['=='] = 3, + ['|'] = 4, + ['~'] = 5, + ['&'] = 6, + ['<<'] = 7, + ['>>'] = 7, + ['..'] = 8, + ['+'] = 9, + ['-'] = 9, + ['*'] = 10, + ['//'] = 10, + ['/'] = 10, + ['%'] = 10, + ['^'] = 12, +} + +local BinaryAlias = { + ['&&'] = 'and', + ['||'] = 'or', + ['!='] = '~=', +} + +local BinaryActionAlias = { + ['='] = '==', +} + +local UnaryAlias = { + ['!'] = 'not', +} + +local SymbolForward = { + [01] = true, + [02] = true, + [03] = true, + [04] = true, + [05] = true, + [06] = true, + [07] = true, + [08] = false, + [09] = true, + [10] = true, + [11] = true, + [12] = false, +} + +local GetToSetMap = { + ['getglobal'] = 'setglobal', + ['getlocal'] = 'setlocal', + ['getfield'] = 'setfield', + ['getindex'] = 'setindex', + ['getmethod'] = 'setmethod', +} + +local ChunkFinishMap = { + ['end'] = true, + ['else'] = true, + ['elseif'] = true, + ['in'] = true, + ['do'] = true, + ['then'] = true, + ['until'] = true, + [';'] = true, + [']'] = true, + [')'] = true, + ['}'] = true, +} + +local State, Lua, Line, LineOffset, Chunk, Tokens, Index, LastTokenFinish, Mode, LocalCount + +local LocalLimit = 200 + +local parseExp, parseAction + +local function pushError(err) + local errs = State.errs + if err.finish < err.start then + err.finish = err.start + end + local last = errs[#errs] + if last then + if last.start <= err.start and last.finish >= err.finish then + return + end + end + err.level = err.level or 'error' + errs[#errs+1] = err + return err +end + +local function addSpecial(name, obj) + local root = State.ast + if not root.specials then + root.specials = {} + end + if not root.specials[name] then + root.specials[name] = {} + end + root.specials[name][#root.specials[name]+1] = obj + obj.special = name +end + +---@param offset integer +---@param leftOrRight '"left"'|'"right"' +local function getPosition(offset, leftOrRight) + if not offset or offset > #Lua then + return LineMulti * Line + #Lua - LineOffset + 1 + end + if leftOrRight == 'left' then + return LineMulti * Line + offset - LineOffset + else + return LineMulti * Line + offset - LineOffset + 1 + end +end + +---@return string word +---@return parser.position startPosition +---@return parser.position finishPosition +---@return integer newOffset +local function peekWord() + local word = Tokens[Index + 1] + if not word then + return nil + end + if not CharMapWord[ssub(word, 1, 1)] then + return nil + end + local startPos = getPosition(Tokens[Index] , 'left') + local finishPos = getPosition(Tokens[Index] + #word - 1, 'right') + return word, startPos, finishPos +end + +local function lastRightPosition() + if Index < 2 then + return 0 + end + local token = Tokens[Index - 1] + if NLMap[token] then + return LastTokenFinish + elseif token then + return getPosition(Tokens[Index - 2] + #token - 1, 'right') + else + return getPosition(#Lua, 'right') + end +end + +local function missSymbol(symbol, start, finish) + pushError { + type = 'MISS_SYMBOL', + start = start or lastRightPosition(), + finish = finish or start or lastRightPosition(), + info = { + symbol = symbol, + } + } +end + +local function missExp() + pushError { + type = 'MISS_EXP', + start = lastRightPosition(), + finish = lastRightPosition(), + } +end + +local function missName(pos) + pushError { + type = 'MISS_NAME', + start = pos or lastRightPosition(), + finish = pos or lastRightPosition(), + } +end + +local function missEnd(relatedStart, relatedFinish) + pushError { + type = 'MISS_SYMBOL', + start = lastRightPosition(), + finish = lastRightPosition(), + info = { + symbol = 'end', + related = { + { + start = relatedStart, + finish = relatedFinish, + } + } + } + } + pushError { + type = 'MISS_END', + start = relatedStart, + finish = relatedFinish, + } +end + +local function unknownSymbol(start, finish, word) + local token = word or Tokens[Index + 1] + if not token then + return false + end + pushError { + type = 'UNKNOWN_SYMBOL', + start = start or getPosition(Tokens[Index], 'left'), + finish = finish or getPosition(Tokens[Index] + #token - 1, 'right'), + info = { + symbol = token, + } + } + return true +end + +local function skipUnknownSymbol(stopSymbol) + if unknownSymbol() then + Index = Index + 2 + return true + end + return false +end + +local function skipNL() + local token = Tokens[Index + 1] + if NLMap[token] then + if Index >= 2 and not NLMap[Tokens[Index - 1]] then + LastTokenFinish = getPosition(Tokens[Index - 2] + #Tokens[Index - 1] - 1, 'right') + end + Line = Line + 1 + LineOffset = Tokens[Index] + #token + Index = Index + 2 + return true + end + return false +end + +local function fastForwardToken(offset) + while true do + local myOffset = Tokens[Index] + if not myOffset + or myOffset >= offset then + break + end + Index = Index + 2 + end +end + +local function resolveLongString(finishMark) + skipNL() + local miss + local start = Tokens[Index] + local finishOffset = sfind(Lua, finishMark, start, true) + if not finishOffset then + finishOffset = #Lua + 1 + miss = true + end + local stringResult = ssub(Lua, start, finishOffset - 1) + local lastLN = stringResult:find '[\r\n][^\r\n]*$' + if lastLN then + local result, count = stringResult + : gsub('\r\n', '\n') + : gsub('[\r\n]', '\n') + Line = Line + count + LineOffset = lastLN + start + stringResult = result + end + fastForwardToken(finishOffset + #finishMark) + if miss then + local pos = getPosition(finishOffset - 1, 'right') + pushError { + type = 'MISS_SYMBOL', + start = pos, + finish = pos, + info = { + symbol = finishMark, + }, + fix = { + title = 'ADD_LSTRING_END', + { + start = pos, + finish = pos, + text = finishMark, + } + }, + } + end + return stringResult, getPosition(finishOffset + #finishMark - 1, 'right') +end + +local function parseLongString() + local start, finish, mark = sfind(Lua, '^(%[%=*%[)', Tokens[Index]) + if not mark then + return nil + end + fastForwardToken(finish + 1) + local startPos = getPosition(start, 'left') + local finishMark = sgsub(mark, '%[', ']') + local stringResult, finishOffset = resolveLongString(finishMark) + return { + type = 'string', + start = startPos, + finish = getPosition(finishOffset, 'right'), + [1] = stringResult, + [2] = mark, + } +end + +local function pushCommentHeadError(left) + if State.options.nonstandardSymbol and State.options.nonstandardSymbol['//'] then + return + end + pushError { + type = 'ERR_COMMENT_PREFIX', + start = left, + finish = left + 2, + fix = { + title = 'FIX_COMMENT_PREFIX', + { + start = left, + finish = left + 2, + text = '--', + }, + } + } +end + +local function pushLongCommentError(left, right) + if State.options.nonstandardSymbol and State.options.nonstandardSymbol['/**/'] then + return + end + pushError { + type = 'ERR_C_LONG_COMMENT', + start = left, + finish = right, + fix = { + title = 'FIX_C_LONG_COMMENT', + { + start = left, + finish = left + 2, + text = '--[[', + }, + { + start = right - 2, + finish = right, + text = '--]]' + }, + } + } +end + +local function skipComment(isAction) + local token = Tokens[Index + 1] + if token == '--' + or (token == '//' and isAction) then + local left = getPosition(Tokens[Index], 'left') + if token == '//' then + pushCommentHeadError(left) + end + Index = Index + 2 + local longComment = parseLongString() + if longComment then + return true + end + while true do + local nl = Tokens[Index + 1] + if not nl or NLMap[nl] then + break + end + Index = Index + 2 + end + return true + end + if token == '/*' then + local left = getPosition(Tokens[Index], 'left') + Index = Index + 2 + local result, right = resolveLongString '*/' + pushLongCommentError(left, right) + return true + end + return false +end + +local function skipSpace(isAction) + repeat until not skipNL() + and not skipComment(isAction) +end + +local function expectAssign() + local token = Tokens[Index + 1] + if token == '=' then + Index = Index + 2 + return true + end + if token == '==' then + local left = getPosition(Tokens[Index], 'left') + local right = getPosition(Tokens[Index] + #token - 1, 'right') + pushError { + type = 'ERR_ASSIGN_AS_EQ', + start = left, + finish = right, + fix = { + title = 'FIX_ASSIGN_AS_EQ', + { + start = left, + finish = right, + text = '=', + } + } + } + Index = Index + 2 + return true + end + return false +end + +local function parseLocalAttrs() + local attrs + while true do + skipSpace() + local token = Tokens[Index + 1] + if token ~= '<' then + break + end + if not attrs then + attrs = {} + end + local attr = { + type = 'localattr', + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index], 'right'), + } + attrs[#attrs+1] = attr + Index = Index + 2 + skipSpace() + local word, wstart, wfinish = peekWord() + if word then + attr[1] = word + attr.finish = wfinish + Index = Index + 2 + else + missName() + end + attr.finish = lastRightPosition() + skipSpace() + if Tokens[Index + 1] == '>' then + attr.finish = getPosition(Tokens[Index], 'right') + Index = Index + 2 + elseif Tokens[Index + 1] == '>=' then + attr.finish = getPosition(Tokens[Index], 'right') + pushError { + type = 'MISS_SPACE_BETWEEN', + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index] + 1, 'right'), + } + Index = Index + 2 + else + missSymbol '>' + end + if State.version ~= 'Lua 5.4' then + pushError { + type = 'UNSUPPORT_SYMBOL', + start = attr.start, + finish = attr.finish, + version = 'Lua 5.4', + info = { + version = State.version + } + } + end + end + return attrs +end + +local function createLocal(obj, attrs) + if not obj then + return nil + end + obj.type = 'local' + obj.effect = obj.finish + + if attrs then + obj.attrs = attrs + for i = 1, #attrs do + local attr = attrs[i] + attr.parent = obj + end + end + + local chunk = Chunk[#Chunk] + if chunk then + local locals = chunk.locals + if not locals then + locals = {} + chunk.locals = locals + end + locals[#locals+1] = obj + LocalCount = LocalCount + 1 + if LocalCount > LocalLimit then + pushError { + type = 'LOCAL_LIMIT', + start = obj.start, + finish = obj.finish, + } + end + end + return obj +end + +local function pushChunk(chunk) + Chunk[#Chunk+1] = chunk +end + +local function resolveLable(label, obj) + if not label.ref then + label.ref = {} + end + label.ref[#label.ref+1] = obj + obj.node = label + + -- 如果有局部变量在 goto 与 label 之间声明, + -- 并在 label 之后使用,则算作语法错误 + + -- 如果 label 在 goto 之前声明,那么不会有中间声明的局部变量 + if obj.start > label.start then + return + end + + local block = guide.getBlock(obj) + local locals = block and block.locals + if not locals then + return + end + + for i = 1, #locals do + local loc = locals[i] + -- 检查局部变量声明位置为 goto 与 label 之间 + if loc.start < obj.start or loc.finish > label.finish then + goto CONTINUE + end + -- 检查局部变量的使用位置在 label 之后 + local refs = loc.ref + if not refs then + goto CONTINUE + end + for j = 1, #refs do + local ref = refs[j] + if ref.finish > label.finish then + pushError { + type = 'JUMP_LOCAL_SCOPE', + start = obj.start, + finish = obj.finish, + info = { + loc = loc[1], + }, + relative = { + { + start = label.start, + finish = label.finish, + }, + { + start = loc.start, + finish = loc.finish, + } + }, + } + return + end + end + ::CONTINUE:: + end +end + +local function resolveGoTo(gotos) + for i = 1, #gotos do + local action = gotos[i] + local label = guide.getLabel(action, action[1]) + if label then + resolveLable(label, action) + else + pushError { + type = 'NO_VISIBLE_LABEL', + start = action.start, + finish = action.finish, + info = { + label = action[1], + } + } + end + end +end + +local function popChunk() + local chunk = Chunk[#Chunk] + if chunk.gotos then + resolveGoTo(chunk.gotos) + chunk.gotos = nil + end + local lastAction = chunk[#chunk] + if lastAction then + chunk.finish = lastAction.finish + end + Chunk[#Chunk] = nil +end + +local function parseNil() + if Tokens[Index + 1] ~= 'nil' then + return nil + end + local offset = Tokens[Index] + Index = Index + 2 + return { + type = 'nil', + start = getPosition(offset, 'left'), + finish = getPosition(offset + 2, 'right'), + } +end + +local function parseBoolean() + local word = Tokens[Index+1] + if word ~= 'true' + and word ~= 'false' then + return nil + end + local start = getPosition(Tokens[Index], 'left') + local finish = getPosition(Tokens[Index] + #word - 1, 'right') + Index = Index + 2 + return { + type = 'boolean', + start = start, + finish = finish, + [1] = word == 'true' and true or false, + } +end + +local function parseStringUnicode() + local offset = Tokens[Index] + 1 + if ssub(Lua, offset, offset) ~= '{' then + local pos = getPosition(offset, 'left') + missSymbol('{', pos) + return nil, offset + end + local leftPos = getPosition(offset, 'left') + local x16 = smatch(Lua, '^%w*', offset + 1) + local rightPos = getPosition(offset + #x16, 'right') + offset = offset + #x16 + 1 + if ssub(Lua, offset, offset) == '}' then + offset = offset + 1 + rightPos = rightPos + 1 + else + missSymbol('}', rightPos) + end + offset = offset + 1 + if #x16 == 0 then + pushError { + type = 'UTF8_SMALL', + start = leftPos, + finish = rightPos, + } + return '', offset + end + if State.version ~= 'Lua 5.3' + and State.version ~= 'Lua 5.4' + and State.version ~= 'LuaJIT' + then + pushError { + type = 'ERR_ESC', + start = leftPos - 2, + finish = rightPos, + version = {'Lua 5.3', 'Lua 5.4', 'LuaJIT'}, + info = { + version = State.version, + } + } + return nil, offset + end + local byte = tonumber(x16, 16) + if not byte then + for i = 1, #x16 do + if not tonumber(ssub(x16, i, i), 16) then + pushError { + type = 'MUST_X16', + start = leftPos + i, + finish = leftPos + i + 1, + } + end + end + return nil, offset + end + if State.version == 'Lua 5.4' then + if byte < 0 or byte > 0x7FFFFFFF then + pushError { + type = 'UTF8_MAX', + start = leftPos, + finish = rightPos, + info = { + min = '00000000', + max = '7FFFFFFF', + } + } + return nil, offset + end + else + if byte < 0 or byte > 0x10FFFF then + pushError { + type = 'UTF8_MAX', + start = leftPos, + finish = rightPos, + version = byte <= 0x7FFFFFFF and 'Lua 5.4' or nil, + info = { + min = '000000', + max = '10FFFF', + } + } + end + end + if byte >= 0 and byte <= 0x10FFFF then + return uchar(byte), offset + end + return '', offset +end + +local stringPool = {} +local function parseShortString() + local mark = Tokens[Index+1] + local startOffset = Tokens[Index] + local startPos = getPosition(startOffset, 'left') + Index = Index + 2 + -- empty string + if Tokens[Index+1] == mark then + local finishPos = getPosition(Tokens[Index], 'right') + Index = Index + 2 + return { + type = 'string', + start = startPos, + finish = finishPos, + [1] = '', + [2] = mark, + } + end + local stringIndex = 0 + local currentOffset = startOffset + 1 + while true do + local token = Tokens[Index + 1] + if token == mark then + stringIndex = stringIndex + 1 + stringPool[stringIndex] = ssub(Lua, currentOffset, Tokens[Index] - 1) + Index = Index + 2 + break + end + if not token + or NLMap[token] then + missSymbol(mark) + break + end + if token == '\\' then + stringIndex = stringIndex + 1 + stringPool[stringIndex] = ssub(Lua, currentOffset, Tokens[Index] - 1) + currentOffset = Tokens[Index] + Index = Index + 2 + -- has space? + if Tokens[Index] - currentOffset > 1 then + pushError { + type = 'ERR_ESC', + start = getPosition(currentOffset, 'left'), + finish = getPosition(currentOffset + 1, 'right'), + } + goto CONTINUE + end + local nextToken = ssub(Tokens[Index + 1], 1, 1) + if EscMap[nextToken] then + stringIndex = stringIndex + 1 + stringPool[stringIndex] = EscMap[nextToken] + currentOffset = Tokens[Index] + #nextToken + Index = Index + 2 + goto CONTINUE + end + if nextToken == mark then + stringIndex = stringIndex + 1 + stringPool[stringIndex] = mark + currentOffset = Tokens[Index] + #nextToken + Index = Index + 2 + goto CONTINUE + end + if nextToken == 'z' then + Index = Index + 2 + repeat until not skipNL() + currentOffset = Tokens[Index] + goto CONTINUE + end + if CharMapNumber[nextToken] then + local numbers = smatch(Tokens[Index + 1], '^%d+') + if #numbers > 3 then + numbers = ssub(numbers, 1, 3) + end + currentOffset = Tokens[Index] + #numbers + fastForwardToken(currentOffset) + local byte = tointeger(numbers) + if byte <= 255 then + stringIndex = stringIndex + 1 + stringPool[stringIndex] = schar(byte) + else + -- TODO pushError + end + goto CONTINUE + end + if nextToken == 'x' then + local left = getPosition(Tokens[Index] - 1, 'left') + local x16 = ssub(Tokens[Index + 1], 2, 3) + local byte = tonumber(x16, 16) + if byte then + currentOffset = Tokens[Index] + 3 + stringIndex = stringIndex + 1 + stringPool[stringIndex] = schar(byte) + else + currentOffset = Tokens[Index] + 1 + pushError { + type = 'MISS_ESC_X', + start = getPosition(currentOffset, 'left'), + finish = getPosition(currentOffset + 1, 'right'), + } + end + if State.version == 'Lua 5.1' then + pushError { + type = 'ERR_ESC', + start = left, + finish = left + 4, + version = {'Lua 5.2', 'Lua 5.3', 'Lua 5.4', 'LuaJIT'}, + info = { + version = State.version, + } + } + end + Index = Index + 2 + goto CONTINUE + end + if nextToken == 'u' then + local str, newOffset = parseStringUnicode() + if str then + stringIndex = stringIndex + 1 + stringPool[stringIndex] = str + end + currentOffset = newOffset + fastForwardToken(currentOffset - 1) + goto CONTINUE + end + if NLMap[nextToken] then + stringPool[stringIndex] = '\n' + currentOffset = Tokens[Index] + #nextToken + Index = Index + 2 + goto CONTINUE + end + pushError { + type = 'ERR_ESC', + start = getPosition(currentOffset, 'left'), + finish = getPosition(currentOffset + 1, 'right'), + } + end + Index = Index + 2 + ::CONTINUE:: + end + local stringResult = tconcat(stringPool, '', 1, stringIndex) + return { + type = 'string', + start = startPos, + finish = lastRightPosition(), + [1] = stringResult, + [2] = mark, + } +end + +local function parseString() + local c = Tokens[Index + 1] + if CharMapStrSH[c] then + return parseShortString() + end + if CharMapStrLH[c] then + return parseLongString() + end + return nil +end + +local function parseNumber10(start) + local integer = true + local integerPart = smatch(Lua, '^%d*', start) + local offset = start + #integerPart + -- float part + if ssub(Lua, offset, offset) == '.' then + local floatPart = smatch(Lua, '^%d*', offset + 1) + integer = false + offset = offset + #floatPart + 1 + end + -- exp part + local echar = ssub(Lua, offset, offset) + if CharMapE10[echar] then + integer = false + offset = offset + 1 + local nextChar = ssub(Lua, offset, offset) + if CharMapSign[nextChar] then + offset = offset + 1 + end + local exp = smatch(Lua, '^%d*', offset) + offset = offset + #exp + if #exp == 0 then + pushError { + type = 'MISS_EXPONENT', + start = getPosition(offset - 1, 'right'), + finish = getPosition(offset - 1, 'right'), + } + end + end + return tonumber(ssub(Lua, start, offset - 1)), offset, integer +end + +local function parseNumber16(start) + local integerPart = smatch(Lua, '^[%da-fA-F]*', start) + local offset = start + #integerPart + local integer = true + -- float part + if ssub(Lua, offset, offset) == '.' then + local floatPart = smatch(Lua, '^[%da-fA-F]*', offset + 1) + integer = false + offset = offset + #floatPart + 1 + if #integerPart == 0 and #floatPart == 0 then + pushError { + type = 'MUST_X16', + start = getPosition(offset - 1, 'right'), + finish = getPosition(offset - 1, 'right'), + } + end + else + if #integerPart == 0 then + pushError { + type = 'MUST_X16', + start = getPosition(offset - 1, 'right'), + finish = getPosition(offset - 1, 'right'), + } + return 0, offset + end + end + -- exp part + local echar = ssub(Lua, offset, offset) + if CharMapE16[echar] then + integer = false + offset = offset + 1 + local nextChar = ssub(Lua, offset, offset) + if CharMapSign[nextChar] then + offset = offset + 1 + end + local exp = smatch(Lua, '^%d*', offset) + offset = offset + #exp + end + local n = tonumber(ssub(Lua, start - 2, offset - 1)) + return n, offset, integer +end + +local function parseNumber2(start) + local bins = smatch(Lua, '^[01]*', start) + local offset = start + #bins + if State.version ~= 'LuaJIT' then + pushError { + type = 'UNSUPPORT_SYMBOL', + start = getPosition(start - 2, 'left'), + finish = getPosition(offset - 1, 'right'), + version = 'LuaJIT', + info = { + version = 'Lua 5.4', + } + } + end + return tonumber(bins, 2), offset +end + +local function dropNumberTail(offset, integer) + local _, finish, word = sfind(Lua, '^([%.%w_\x80-\xff]+)', offset) + if not finish then + return offset + end + if integer then + if supper(ssub(word, 1, 2)) == 'LL' then + if State.version ~= 'LuaJIT' then + pushError { + type = 'UNSUPPORT_SYMBOL', + start = getPosition(offset, 'left'), + finish = getPosition(offset + 1, 'right'), + version = 'LuaJIT', + info = { + version = State.version, + } + } + end + offset = offset + 2 + word = ssub(word, offset) + elseif supper(ssub(word, 1, 3)) == 'ULL' then + if State.version ~= 'LuaJIT' then + pushError { + type = 'UNSUPPORT_SYMBOL', + start = getPosition(offset, 'left'), + finish = getPosition(offset + 2, 'right'), + version = 'LuaJIT', + info = { + version = State.version, + } + } + end + offset = offset + 3 + word = ssub(word, offset) + end + end + if supper(ssub(word, 1, 1)) == 'I' then + if State.version ~= 'LuaJIT' then + pushError { + type = 'UNSUPPORT_SYMBOL', + start = getPosition(offset, 'left'), + finish = getPosition(offset, 'right'), + version = 'LuaJIT', + info = { + version = State.version, + } + } + end + offset = offset + 1 + word = ssub(word, offset) + end + if #word > 0 then + pushError { + type = 'MALFORMED_NUMBER', + start = getPosition(offset, 'left'), + finish = getPosition(finish, 'right'), + } + end + return finish + 1 +end + +local function parseNumber() + local offset = Tokens[Index] + if not offset then + return nil + end + local startPos = getPosition(offset, 'left') + local neg + if ssub(Lua, offset, offset) == '-' then + neg = true + offset = offset + 1 + end + local number, integer + local firstChar = ssub(Lua, offset, offset) + if firstChar == '.' then + number, offset = parseNumber10(offset) + integer = false + elseif firstChar == '0' then + local nextChar = ssub(Lua, offset + 1, offset + 1) + if CharMapN16[nextChar] then + number, offset, integer = parseNumber16(offset + 2) + elseif CharMapN2[nextChar] then + number, offset = parseNumber2(offset + 2) + integer = true + else + number, offset, integer = parseNumber10(offset) + end + elseif CharMapNumber[firstChar] then + number, offset, integer = parseNumber10(offset) + else + return nil + end + if not number then + number = 0 + end + if neg then + number = - number + end + local result = { + type = integer and 'integer' or 'number', + start = startPos, + finish = getPosition(offset - 1, 'right'), + [1] = number, + } + offset = dropNumberTail(offset, integer) + fastForwardToken(offset) + return result +end + +local function isKeyWord(word) + if KeyWord[word] then + return true + end + if word == 'goto' then + return State.version ~= 'Lua 5.1' + end + return false +end + +local function parseName() + local word = peekWord() + if not word then + return nil + end + if ChunkFinishMap[word] then + return nil + end + local startPos = getPosition(Tokens[Index], 'left') + local finishPos = getPosition(Tokens[Index] + #word - 1, 'right') + Index = Index + 2 + if not State.options.unicodeName and word:find '[\x80-\xff]' then + pushError { + type = 'UNICODE_NAME', + start = startPos, + finish = finishPos, + } + end + if isKeyWord(word) then + pushError { + type = 'KEYWORD', + start = startPos, + finish = finishPos, + } + end + return { + type = 'name', + start = startPos, + finish = finishPos, + [1] = word, + } +end + +local function parseNameOrList() + local first = parseName() + if not first then + return nil + end + skipSpace() + local list + while true do + if Tokens[Index + 1] ~= ',' then + break + end + Index = Index + 2 + skipSpace() + local name = parseName() + if not name then + missName() + break + end + if not list then + list = { + type = 'list', + start = first.start, + finish = first.finish, + [1] = first + } + end + list[#list+1] = name + list.finish = name.finish + end + return list or first +end + +local function dropTail() + local token = Tokens[Index + 1] + if token ~= '?' + and token ~= ':' then + return + end + local pl, pt, pp = 0, 0, 0 + while true do + local token = Tokens[Index + 1] + if not token then + break + end + if NLMap[token] then + break + end + if token == ',' then + if pl > 0 + or pt > 0 + or pp > 0 then + goto CONTINUE + else + break + end + end + if token == '<' then + pl = pl + 1 + goto CONTINUE + end + if token == '{' then + pt = pt + 1 + goto CONTINUE + end + if token == '(' then + pp = pp + 1 + goto CONTINUE + end + if token == '>' then + if pl <= 0 then + break + end + pl = pl - 1 + goto CONTINUE + end + if token == '}' then + if pt <= 0 then + break + end + pt = pt - 1 + goto CONTINUE + end + if token == ')' then + if pp <= 0 then + break + end + pp = pp - 1 + goto CONTINUE + end + ::CONTINUE:: + Index = Index + 2 + end +end + +local function parseExpList(mini) + local list + local wantSep = false + while true do + skipSpace() + local token = Tokens[Index + 1] + if not token then + break + end + if ChunkFinishMap[token] then + break + end + if token == ',' then + local sepPos = getPosition(Tokens[Index], 'right') + if not wantSep then + pushError { + type = 'UNEXPECT_SYMBOL', + start = getPosition(Tokens[Index], 'left'), + finish = sepPos, + info = { + symbol = ',', + } + } + end + wantSep = false + Index = Index + 2 + goto CONTINUE + else + if mini then + if wantSep then + break + end + local nextToken = peekWord() + if isKeyWord(nextToken) + and nextToken ~= 'function' then + break + end + end + local exp = parseExp() + if not exp then + break + end + dropTail() + if wantSep then + missSymbol(',', list[#list].finish, exp.start) + end + wantSep = true + if not list then + list = { + type = 'list', + start = exp.start, + } + end + list[#list+1] = exp + list.finish = exp.finish + exp.parent = list + end + ::CONTINUE:: + end + if not list then + return nil + end + if not wantSep then + missExp() + end + return list +end + +local function parseIndex() + local bstart = getPosition(Tokens[Index], 'left') + Index = Index + 2 + skipSpace() + local exp = parseExp() + local index = { + type = 'index', + start = bstart, + finish = exp and exp.finish or (bstart + 1), + index = exp + } + if exp then + exp.parent = index + else + missExp() + end + skipSpace() + if Tokens[Index + 1] == ']' then + index.finish = getPosition(Tokens[Index], 'right') + Index = Index + 2 + else + missSymbol ']' + end + return index +end + +local function parseTable() + local tbl = { + type = 'table', + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index], 'right'), + } + Index = Index + 2 + local index = 0 + local wantSep = false + while true do + skipSpace() + local token = Tokens[Index + 1] + if token == '}' then + Index = Index + 2 + break + end + if CharMapTSep[token] then + if not wantSep then + missExp() + end + wantSep = false + Index = Index + 2 + goto CONTINUE + end + local lastRight = lastRightPosition() + if token == '[' then + if wantSep then + pushError { + type = 'MISS_SEP_IN_TABLE', + start = lastRight, + finish = getPosition(Tokens[Index], 'left'), + } + end + wantSep = true + index = index + 1 + local tindex = parseIndex() + skipSpace() + if expectAssign() then + skipSpace() + local ivalue = parseExp() + tindex.type = 'tableindex' + tindex.parent = tbl + if ivalue then + ivalue.parent = tindex + tindex.finish = ivalue.finish + tindex.value = ivalue + else + missExp() + end + tbl[index] = tindex + else + missSymbol '=' + end + goto CONTINUE + end + + local exp = parseExp(true) + if exp then + if wantSep then + pushError { + type = 'MISS_SEP_IN_TABLE', + start = lastRight, + finish = exp.start, + } + end + wantSep = true + index = index + 1 + if exp.type == 'varargs' then + tbl[index] = exp + exp.parent = tbl + goto CONTINUE + end + if exp.type == 'getlocal' + or exp.type == 'getglobal' then + skipSpace() + if expectAssign() then + local eqRight = lastRightPosition() + skipSpace() + local fvalue = parseExp() + local tfield = { + type = 'tablefield', + start = exp.start, + finish = fvalue and fvalue.finish or eqRight, + parent = tbl, + field = exp, + value = fvalue, + } + exp.type = 'field' + exp.parent = tfield + if fvalue then + fvalue.parent = tfield + else + missExp() + end + tbl[index] = tfield + goto CONTINUE + end + end + local texp = { + type = 'tableexp', + start = exp.start, + finish = exp.finish, + tindex = index, + parent = tbl, + value = exp, + } + exp.parent = texp + tbl[index] = texp + goto CONTINUE + end + missSymbol '}' + break + ::CONTINUE:: + end + tbl.finish = getPosition(Tokens[Index - 2], 'right') + return tbl +end + +local function parseSimple(node, funcName) + local lastMethod + while true do + if lastMethod and node.node == lastMethod then + if node.type ~= 'call' then + missSymbol('(', node.node.finish, node.node.finish) + end + lastMethod = nil + end + skipSpace() + local token = Tokens[Index + 1] + if token == '.' then + local dot = { + type = token, + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index], 'right'), + } + Index = Index + 2 + skipSpace() + local field = parseName() + local getfield = { + type = 'getfield', + start = node.start, + finish = lastRightPosition(), + node = node, + dot = dot, + field = field + } + if field then + field.parent = node + field.type = 'field' + else + pushError { + type = 'MISS_FIELD', + start = lastRightPosition(), + finish = lastRightPosition(), + } + end + node.next = getfield + node = getfield + elseif token == ':' then + local colon = { + type = token, + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index], 'right'), + } + Index = Index + 2 + skipSpace() + local method = parseName() + local getmethod = { + type = 'getmethod', + start = node.start, + finish = lastRightPosition(), + node = node, + colon = colon, + method = method + } + if method then + method.parent = node + method.type = 'method' + else + pushError { + type = 'MISS_METHOD', + start = lastRightPosition(), + finish = lastRightPosition(), + } + end + node.next = getmethod + node = getmethod + if lastMethod then + missSymbol('(', node.node.finish, node.node.finish) + end + lastMethod = getmethod + elseif token == '(' then + if funcName then + break + end + local startPos = getPosition(Tokens[Index], 'left') + local call = { + type = 'call', + start = node.start, + node = node, + } + Index = Index + 2 + local args = parseExpList() + if Tokens[Index + 1] == ')' then + call.finish = getPosition(Tokens[Index], 'right') + Index = Index + 2 + else + missSymbol ')' + end + if args then + args.type = 'callargs' + args.start = startPos + args.finish = call.finish + args.parent = call + call.args = args + end + if node.type == 'getmethod' then + -- dummy param `self` + if not call.args then + call.args = { + type = 'callargs', + start = call.start, + finish = call.finish, + parent = call, + } + end + local newNode = {} + for k, v in next, call.node.node do + newNode[k] = v + end + newNode.mirror = call.node.node + newNode.dummy = true + newNode.parent = call.args + call.node.node.mirror = newNode + tinsert(call.args, 1, newNode) + end + node = call + elseif token == '{' then + if funcName then + break + end + local str = parseTable() + local call = { + type = 'call', + start = node.start, + finish = str.finish, + node = node, + } + local args = { + type = 'callargs', + start = str.start, + finish = str.finish, + parent = call, + [1] = str, + } + call.args = args + str.parent = args + return call + elseif CharMapStrSH[token] then + if funcName then + break + end + local str = parseShortString() + local call = { + type = 'call', + start = node.start, + finish = str.finish, + node = node, + } + local args = { + type = 'callargs', + start = str.start, + finish = str.finish, + parent = call, + [1] = str, + } + call.args = args + str.parent = args + return call + elseif CharMapStrLH[token] then + local str = parseLongString() + if str then + if funcName then + break + end + local call = { + type = 'call', + start = node.start, + finish = str.finish, + node = node, + } + local args = { + type = 'callargs', + start = str.start, + finish = str.finish, + parent = call, + [1] = str, + } + call.args = args + str.parent = args + return call + else + local index = parseIndex() + index.type = 'getindex' + index.bstart = index.start + index.start = node.start + index.node = node + node.next = index + node = index + if funcName then + pushError { + type = 'INDEX_IN_FUNC_NAME', + start = index.bstart, + finish = index.finish, + } + end + end + else + break + end + end + if node.type == 'call' + and node.node == lastMethod then + lastMethod = nil + end + if node == lastMethod then + if funcName then + lastMethod = nil + end + end + if lastMethod then + missSymbol('(', lastMethod.finish) + end + return node +end + +local function parseVarargs() + local varargs = { + type = 'varargs', + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index] + 2, 'right'), + } + Index = Index + 2 + for i = #Chunk, 1, -1 do + local chunk = Chunk[i] + if chunk.vararg then + if not chunk.vararg.ref then + chunk.vararg.ref = {} + end + chunk.vararg.ref[#chunk.vararg.ref+1] = varargs + varargs.node = chunk.vararg + break + end + if chunk.type == 'function' then + break + end + end + if not varargs.node and Mode == 'Lua' then + pushError { + type = 'UNEXPECT_DOTS', + start = varargs.start, + finish = varargs.finish, + } + end + return varargs +end + +local function parseParen() + local pl = Tokens[Index] + local paren = { + type = 'paren', + start = getPosition(pl, 'left'), + finish = getPosition(pl, 'right') + } + Index = Index + 2 + skipSpace() + local exp = parseExp() + if exp then + paren.exp = exp + paren.finish = exp.finish + exp.parent = paren + else + missExp() + end + skipSpace() + if Tokens[Index + 1] == ')' then + paren.finish = getPosition(Tokens[Index], 'right') + Index = Index + 2 + else + missSymbol ')' + end + return paren +end + +local function getLocal(name, pos) + for i = #Chunk, 1, -1 do + local chunk = Chunk[i] + local locals = chunk.locals + if locals then + local res + for n = 1, #locals do + local loc = locals[n] + if loc.effect > pos then + break + end + if loc[1] == name then + if not res or res.effect < loc.effect then + res = loc + end + end + end + if res then + return res + end + end + end +end + +local function resolveName(node) + if not node then + return nil + end + local loc = getLocal(node[1], node.start) + if loc then + node.type = 'getlocal' + node.node = loc + if not loc.ref then + loc.ref = {} + end + loc.ref[#loc.ref+1] = node + else + node.type = 'getglobal' + local env = getLocal(State.ENVMode, node.start) + if env then + node.node = env + if not env.ref then + env.ref = {} + end + env.ref[#env.ref+1] = node + end + end + local name = node[1] + if Specials[name] then + addSpecial(name, node) + else + local ospeicals = State.options.special + if ospeicals and ospeicals[name] then + addSpecial(name, node) + end + end + return node +end + +local function isChunkFinishToken(token) + local currentChunk = Chunk[#Chunk] + if not currentChunk then + return false + end + local tp = currentChunk.type + if tp == 'main' then + return false + end + if tp == 'for' + or tp == 'in' + or tp == 'loop' then + return token == 'do' + or token == 'end' + end + if tp == 'if' + or tp == 'ifblock' + or tp == 'elseifblock' + or tp == 'elseblock' then + return token == 'then' + or token == 'end' + or token == 'else' + or token == 'elseif' + end + return token ~= 'do' +end + +local function parseActions() + local rtn, last + while true do + skipSpace(true) + local token = Tokens[Index + 1] + if token == ';' then + Index = Index + 2 + goto CONTINUE + end + if ChunkFinishMap[token] + and isChunkFinishToken(token) then + break + end + local action, failed = parseAction() + if failed then + break + end + if action then + if action.type == 'return' then + rtn = action + end + last = action + end + ::CONTINUE:: + end + if rtn and rtn ~= last then + pushError { + type = 'ACTION_AFTER_RETURN', + start = rtn.start, + finish = rtn.finish, + } + end +end + +local function parseParams(params) + local lastSep + local hasDots + while true do + skipSpace() + local token = Tokens[Index + 1] + if not token or token == ')' then + if lastSep then + missName() + end + break + end + if token == ',' then + if lastSep or lastSep == nil then + missName() + else + lastSep = true + end + Index = Index + 2 + goto CONTINUE + end + if token == '...' then + if lastSep == false then + missSymbol ',' + end + lastSep = false + if not params then + params = {} + end + local vararg = { + type = '...', + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index] + 2, 'right'), + parent = params, + } + local chunk = Chunk[#Chunk] + chunk.vararg = vararg + params[#params+1] = vararg + if hasDots then + pushError { + type = 'ARGS_AFTER_DOTS', + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index] + 2, 'right'), + } + end + hasDots = true + Index = Index + 2 + goto CONTINUE + end + if CharMapWord[ssub(token, 1, 1)] then + if lastSep == false then + missSymbol ',' + end + lastSep = false + if not params then + params = {} + end + params[#params+1] = createLocal { + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index] + #token - 1, 'right'), + parent = params, + [1] = token, + } + if hasDots then + pushError { + type = 'ARGS_AFTER_DOTS', + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index] + #token - 1, 'right'), + } + end + Index = Index + 2 + goto CONTINUE + end + skipUnknownSymbol '%,%)%.' + ::CONTINUE:: + end + return params +end + +local function parseFunction(isLocal, isAction) + local funcLeft = getPosition(Tokens[Index], 'left') + local funcRight = getPosition(Tokens[Index] + 7, 'right') + local func = { + type = 'function', + start = funcLeft, + finish = funcRight, + keyword = { + [1] = funcLeft, + [2] = funcRight, + }, + } + Index = Index + 2 + local LastLocalCount = LocalCount + LocalCount = 0 + skipSpace() + local hasLeftParen = Tokens[Index + 1] == '(' + if not hasLeftParen then + local name = parseName() + if name then + local simple = parseSimple(name, true) + if isLocal then + if simple == name then + createLocal(name) + else + resolveName(name) + pushError { + type = 'UNEXPECT_LFUNC_NAME', + start = simple.start, + finish = simple.finish, + } + end + else + resolveName(name) + end + func.name = simple + func.finish = simple.finish + if not isAction then + pushError { + type = 'UNEXPECT_EFUNC_NAME', + start = simple.start, + finish = simple.finish, + } + end + skipSpace() + hasLeftParen = Tokens[Index + 1] == '(' + end + end + pushChunk(func) + local params + if func.name and func.name.type == 'getmethod' then + if func.name.type == 'getmethod' then + params = {} + params[1] = createLocal { + start = funcRight, + finish = funcRight, + method = func.name, + parent = params, + tag = 'self', + dummy = true, + [1] = 'self', + } + end + end + if hasLeftParen then + local parenLeft = getPosition(Tokens[Index], 'left') + Index = Index + 2 + params = parseParams(params) + if params then + params.type = 'funcargs' + params.start = parenLeft + params.finish = lastRightPosition() + params.parent = func + func.args = params + func.finish = params.finish + end + skipSpace() + if Tokens[Index + 1] == ')' then + local parenRight = getPosition(Tokens[Index], 'right') + func.finish = parenRight + if params then + params.finish = parenRight + end + Index = Index + 2 + skipSpace() + else + if params then + params.finish = func.finish + end + missSymbol ')' + end + else + missSymbol '(' + end + parseActions() + popChunk() + if Tokens[Index + 1] == 'end' then + local endLeft = getPosition(Tokens[Index], 'left') + local endRight = getPosition(Tokens[Index] + 2, 'right') + func.keyword[3] = endLeft + func.keyword[4] = endRight + func.finish = endRight + Index = Index + 2 + else + missEnd(funcLeft, funcRight) + end + LocalCount = LastLocalCount + return func +end + +local function parseExpUnit() + local token = Tokens[Index + 1] + if token == '(' then + local paren = parseParen() + return parseSimple(paren, false) + end + + if token == '...' then + local varargs = parseVarargs() + return varargs + end + + if token == '{' then + local table = parseTable() + return table + end + + if CharMapStrSH[token] then + local string = parseShortString() + return string + end + + if CharMapStrLH[token] then + local string = parseLongString() + return string + end + + local number = parseNumber() + if number then + return number + end + + if ChunkFinishMap[token] then + return nil + end + + if token == 'nil' then + return parseNil() + end + + if token == 'true' + or token == 'false' then + return parseBoolean() + end + + if token == 'function' then + return parseFunction() + end + + local node = parseName() + if node then + return parseSimple(resolveName(node), false) + end + + return nil +end + +local function parseUnaryOP(level) + local token = Tokens[Index + 1] + local symbol = UnarySymbol[token] and token or UnaryAlias[token] + if not symbol then + return nil + end + local myLevel = UnarySymbol[symbol] + if level and myLevel < level then + return nil + end + local op = { + type = symbol, + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index] + #symbol - 1, 'right'), + } + Index = Index + 2 + return op, myLevel +end + +---@param level integer # op level must greater than this level +local function parseBinaryOP(asAction, level) + local token = Tokens[Index + 1] + local symbol = (BinarySymbol[token] and token) + or BinaryAlias[token] + or (not asAction and BinaryActionAlias[token]) + if not symbol then + return nil + end + local myLevel = BinarySymbol[symbol] + if level and myLevel < level then + return nil + end + local op = { + type = symbol, + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index] + #token - 1, 'right'), + } + if not asAction then + if token == '=' then + pushError { + type = 'ERR_EQ_AS_ASSIGN', + start = op.start, + finish = op.finish, + fix = { + title = 'FIX_EQ_AS_ASSIGN', + { + start = op.start, + finish = op.finish, + text = '==', + } + } + } + end + end + if BinaryAlias[token] then + if State.options.nonstandardSymbol and State.options.nonstandardSymbol[token] then + else + pushError { + type = 'ERR_NONSTANDARD_SYMBOL', + start = op.start, + finish = op.finish, + info = { + symbol = symbol, + }, + fix = { + title = 'FIX_NONSTANDARD_SYMBOL', + symbol = symbol, + { + start = op.start, + finish = op.finish, + text = symbol, + }, + } + } + end + end + if token == '//' + or token == '<<' + or token == '>>' then + if State.version ~= 'Lua 5.3' + and State.version ~= 'Lua 5.4' then + pushError { + type = 'UNSUPPORT_SYMBOL', + version = {'Lua 5.3', 'Lua 5.4'}, + start = op.start, + finish = op.finish, + info = { + version = State.version, + } + } + end + end + Index = Index + 2 + return op, myLevel +end + +function parseExp(asAction, level) + local exp + local uop, uopLevel = parseUnaryOP(level) + if uop then + skipSpace() + local child = parseExp(asAction, uopLevel) + exp = { + type = 'unary', + op = uop, + start = uop.start, + finish = child and child.finish or uop.finish, + [1] = child, + } + if child then + child.parent = exp + else + missExp() + end + else + exp = parseExpUnit() + if not exp then + return nil + end + end + + while true do + skipSpace() + local bop, bopLevel = parseBinaryOP(asAction, level) + if not bop then + break + end + + ::AGAIN:: + skipSpace() + local isForward = SymbolForward[bopLevel] + local child = parseExp(asAction, isForward and (bopLevel + 0.5) or bopLevel) + if not child then + if skipUnknownSymbol() then + goto AGAIN + else + missExp() + end + end + local bin = { + type = 'binary', + start = exp.start, + finish = child and child.finish or bop.finish, + op = bop, + [1] = exp, + [2] = child + } + exp.parent = bin + if child then + child.parent = bin + end + exp = bin + end + + return exp +end + +local function skipSeps() + while true do + skipSpace() + if Tokens[Index + 1] == ',' then + missExp() + Index = Index + 2 + else + break + end + end +end + +---@return parser.guide.object first +---@return parser.guide.object second +---@return parser.guide.object[] rest +local function parseSetValues() + skipSpace() + local first = parseExp() + if not first then + return nil + end + skipSpace() + if Tokens[Index + 1] ~= ',' then + return first + end + Index = Index + 2 + skipSeps() + local second = parseExp() + if not second then + missExp() + return first + end + skipSpace() + if Tokens[Index + 1] ~= ',' then + return first, second + end + Index = Index + 2 + skipSeps() + local third = parseExp() + if not third then + missExp() + return first, second + end + + local rest = { third } + while true do + skipSpace() + if Tokens[Index + 1] ~= ',' then + return first, second, rest + end + Index = Index + 2 + skipSeps() + local exp = parseExp() + if not exp then + missExp() + return first, second, rest + end + rest[#rest+1] = exp + end +end + +local function pushActionIntoCurrentChunk(action) + local chunk = Chunk[#Chunk] + if chunk then + chunk[#chunk+1] = action + action.parent = chunk + end +end + +---@return parser.guide.object second +---@return parser.guide.object[] rest +local function parseVarTails(parser, isLocal) + if Tokens[Index + 1] ~= ',' then + return + end + Index = Index + 2 + skipSpace() + local second = parser(true) + if not second then + missName() + return + end + if isLocal then + createLocal(second, parseLocalAttrs()) + second.effect = maxinteger + end + skipSpace() + if Tokens[Index + 1] ~= ',' then + return second + end + Index = Index + 2 + skipSeps() + local third = parser(true) + if not third then + missName() + return second + end + if isLocal then + createLocal(third, parseLocalAttrs()) + third.effect = maxinteger + end + local rest = { third } + while true do + skipSpace() + if Tokens[Index + 1] ~= ',' then + return second, rest + end + Index = Index + 2 + skipSeps() + local name = parser(true) + if not name then + missName() + return second, rest + end + if isLocal then + createLocal(name, parseLocalAttrs()) + name.effect = maxinteger + end + rest[#rest+1] = name + end +end + +local function bindValue(n, v, index, lastValue, isLocal, isSet) + if isLocal then + n.effect = lastRightPosition() + elseif isSet then + n.type = GetToSetMap[n.type] or n.type + if n.type == 'setlocal' then + local loc = n.node + if loc.attrs then + pushError { + type = 'SET_CONST', + start = n.start, + finish = n.finish, + } + end + end + end + if not v and lastValue then + if lastValue.type == 'call' + or lastValue.type == 'varargs' then + v = lastValue + if not v.extParent then + v.extParent = {} + end + end + end + if v then + if v.type == 'call' + or v.type == 'varargs' then + local select = { + type = 'select', + sindex = index, + start = v.start, + finish = v.finish, + vararg = v + } + if v.parent then + v.extParent[#v.extParent+1] = select + else + v.parent = select + end + v = select + end + n.value = v + n.range = v.finish + v.parent = n + if isLocal then + n.effect = lastRightPosition() + end + end +end + +local function parseMultiVars(n1, parser, isLocal) + local n2, nrest = parseVarTails(parser, isLocal) + skipSpace() + local v1, v2, vrest + local isSet + if expectAssign() then + v1, v2, vrest = parseSetValues() + isSet = true + if not v1 then + missExp() + end + end + bindValue(n1, v1, 1, nil, isLocal, isSet) + local lastValue = v1 + if n2 then + bindValue(n2, v2, 2, lastValue, isLocal, isSet) + lastValue = v2 or lastValue + pushActionIntoCurrentChunk(n2) + end + if nrest then + for i = 1, #nrest do + local n = nrest[i] + local v = vrest and vrest[i] + bindValue(n, v, i + 2, lastValue, isLocal, isSet) + lastValue = v or lastValue + pushActionIntoCurrentChunk(n) + end + end + + if v2 and not n2 then + v2.redundant = true + pushActionIntoCurrentChunk(v2) + end + if vrest then + for i = 1, #vrest do + local v = vrest[i] + if not nrest or not nrest[i] then + v.redundant = true + pushActionIntoCurrentChunk(v) + end + end + end + + return n1, isSet +end + +local function compileExpAsAction(exp) + pushActionIntoCurrentChunk(exp) + if GetToSetMap[exp.type] then + skipSpace() + local action, isSet = parseMultiVars(exp, parseExp) + if isSet + or action.type == 'getmethod' then + return action + end + end + + if exp.type == 'call' then + return exp + end + + if exp.type == 'binary' then + if GetToSetMap[exp[1].type] then + local op = exp.op + if op.type == '==' then + pushError { + type = 'ERR_ASSIGN_AS_EQ', + start = op.start, + finish = op.finish, + fix = { + title = 'FIX_ASSIGN_AS_EQ', + { + start = op.start, + finish = op.finish, + text = '=', + } + } + } + return + end + end + end + + pushError { + type = 'EXP_IN_ACTION', + start = exp.start, + finish = exp.finish, + } +end + +local function parseLocal() + Index = Index + 2 + skipSpace() + local word = peekWord() + if not word then + missName() + return nil + end + + if word == 'function' then + local func = parseFunction(true, true) + local name = func.name + if name then + func.name = nil + name.value = func + name.vstart = func.start + name.range = func.finish + func.parent = name + pushActionIntoCurrentChunk(name) + return name + else + missName(func.keyword[2]) + pushActionIntoCurrentChunk(func) + return func + end + end + + local name = parseName() + if not name then + missName() + return nil + end + local loc = createLocal(name, parseLocalAttrs()) + loc.effect = maxinteger + pushActionIntoCurrentChunk(loc) + skipSpace() + parseMultiVars(loc, parseName, true) + loc.effect = lastRightPosition() + + return loc +end + +local function parseDo() + local doLeft = getPosition(Tokens[Index], 'left') + local doRight = getPosition(Tokens[Index] + 1, 'right') + local obj = { + type = 'do', + start = doLeft, + finish = doRight, + keyword = { + [1] = doLeft, + [2] = doRight, + }, + } + Index = Index + 2 + pushActionIntoCurrentChunk(obj) + pushChunk(obj) + parseActions() + popChunk() + if Tokens[Index + 1] == 'end' then + obj.finish = getPosition(Tokens[Index] + 2, 'right') + obj.keyword[3] = getPosition(Tokens[Index], 'left') + obj.keyword[4] = getPosition(Tokens[Index] + 2, 'right') + Index = Index + 2 + else + missEnd(doLeft, doRight) + end + if obj.locals then + LocalCount = LocalCount - #obj.locals + end + + return obj +end + +local function parseReturn() + local returnLeft = getPosition(Tokens[Index], 'left') + local returnRight = getPosition(Tokens[Index] + 5, 'right') + Index = Index + 2 + skipSpace() + local rtn = parseExpList(true) + if rtn then + rtn.type = 'return' + rtn.start = returnLeft + else + rtn = { + type = 'return', + start = returnLeft, + finish = returnRight, + } + 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 = {} + end + func.returns[#func.returns+1] = rtn + break + end + end + + return rtn +end + +local function parseLabel() + local left = getPosition(Tokens[Index], 'left') + Index = Index + 2 + skipSpace() + local label = parseName() + skipSpace() + + if not label then + missName() + end + + if Tokens[Index + 1] == '::' then + Index = Index + 2 + else + if label then + missSymbol '::' + end + end + + if not label then + return nil + end + + label.type = 'label' + pushActionIntoCurrentChunk(label) + + local block = guide.getBlock(label) + if block then + if not block.labels then + block.labels = {} + end + local name = label[1] + local olabel = guide.getLabel(block, name) + if olabel then + if State.version == 'Lua 5.4' + or block == guide.getBlock(olabel) then + pushError { + type = 'REDEFINED_LABEL', + start = label.start, + finish = label.finish, + relative = { + { + olabel.start, + olabel.finish, + } + } + } + end + end + block.labels[name] = label + end + + if State.version == 'Lua 5.1' then + pushError { + type = 'UNSUPPORT_SYMBOL', + start = left, + finish = lastRightPosition(), + version = {'Lua 5.2', 'Lua 5.3', 'Lua 5.4', 'LuaJIT'}, + info = { + version = State.version, + } + } + return + end + return label +end + +local function parseGoTo() + Index = Index + 2 + skipSpace() + + local action = parseName() + if not action then + missName() + return nil + end + + action.type = 'goto' + + for i = #Chunk, 1, -1 do + local chunk = Chunk[i] + if chunk.type == 'function' + or chunk.type == 'main' then + if not chunk.gotos then + chunk.gotos = {} + end + chunk.gotos[#chunk.gotos+1] = action + break + end + end + + pushActionIntoCurrentChunk(action) + return action +end + +local function parseIfBlock(parent) + local ifLeft = getPosition(Tokens[Index], 'left') + local ifRight = getPosition(Tokens[Index] + 1, 'right') + Index = Index + 2 + local ifblock = { + type = 'ifblock', + parent = parent, + start = ifLeft, + finish = ifRight, + keyword = { + [1] = ifLeft, + [2] = ifRight, + } + } + skipSpace() + local filter = parseExp() + if filter then + ifblock.filter = filter + ifblock.finish = filter.finish + filter.parent = ifblock + else + missExp() + end + skipSpace() + local thenToken = Tokens[Index + 1] + if thenToken == 'then' + or thenToken == 'do' then + ifblock.finish = getPosition(Tokens[Index] + #thenToken - 1, 'right') + ifblock.keyword[3] = getPosition(Tokens[Index], 'left') + ifblock.keyword[4] = ifblock.finish + if thenToken == 'do' then + pushError { + type = 'ERR_THEN_AS_DO', + start = ifblock.keyword[3], + finish = ifblock.keyword[4], + fix = { + title = 'FIX_THEN_AS_DO', + { + start = ifblock.keyword[3], + finish = ifblock.keyword[4], + text = 'then', + } + } + } + end + Index = Index + 2 + else + missSymbol 'then' + end + pushChunk(ifblock) + parseActions() + popChunk() + if ifblock.locals then + LocalCount = LocalCount - #ifblock.locals + end + return ifblock +end + +local function parseElseIfBlock(parent) + local ifLeft = getPosition(Tokens[Index], 'left') + local ifRight = getPosition(Tokens[Index] + 5, 'right') + local elseifblock = { + type = 'elseifblock', + parent = parent, + start = ifLeft, + finish = ifRight, + keyword = { + [1] = ifLeft, + [2] = ifRight, + } + } + Index = Index + 2 + skipSpace() + local filter = parseExp() + if filter then + elseifblock.filter = filter + elseifblock.finish = filter.finish + filter.parent = elseifblock + else + missExp() + end + skipSpace() + local thenToken = Tokens[Index + 1] + if thenToken == 'then' + or thenToken == 'do' then + elseifblock.finish = getPosition(Tokens[Index] + #thenToken - 1, 'right') + elseifblock.keyword[3] = getPosition(Tokens[Index], 'left') + elseifblock.keyword[4] = elseifblock.finish + if thenToken == 'do' then + pushError { + type = 'ERR_THEN_AS_DO', + start = elseifblock.keyword[3], + finish = elseifblock.keyword[4], + fix = { + title = 'FIX_THEN_AS_DO', + { + start = elseifblock.keyword[3], + finish = elseifblock.keyword[4], + text = 'then', + } + } + } + end + Index = Index + 2 + else + missSymbol 'then' + end + pushChunk(elseifblock) + parseActions() + popChunk() + if elseifblock.locals then + LocalCount = LocalCount - #elseifblock.locals + end + return elseifblock +end + +local function parseElseBlock(parent) + local ifLeft = getPosition(Tokens[Index], 'left') + local ifRight = getPosition(Tokens[Index] + 3, 'right') + local elseblock = { + type = 'elseblock', + parent = parent, + start = ifLeft, + finish = ifRight, + keyword = { + [1] = ifLeft, + [2] = ifRight, + } + } + Index = Index + 2 + skipSpace() + pushChunk(elseblock) + parseActions() + popChunk() + if elseblock.locals then + LocalCount = LocalCount - #elseblock.locals + end + return elseblock +end + +local function parseIf() + local token = Tokens[Index + 1] + local left = getPosition(Tokens[Index], 'left') + local action = { + type = 'if', + start = left, + finish = getPosition(Tokens[Index] + #token - 1, 'right'), + } + pushActionIntoCurrentChunk(action) + if token ~= 'if' then + missSymbol('if', left, left) + end + local hasElse + while true do + local word = Tokens[Index + 1] + local child + if word == 'if' then + child = parseIfBlock(action) + elseif word == 'elseif' then + child = parseElseIfBlock(action) + elseif word == 'else' then + child = parseElseBlock(action) + end + if not child then + break + end + if hasElse then + pushError { + type = 'BLOCK_AFTER_ELSE', + start = child.start, + finish = child.finish, + } + end + if word == 'else' then + hasElse = true + end + action[#action+1] = child + action.finish = child.finish + skipSpace() + end + + if Tokens[Index + 1] == 'end' then + action.finish = getPosition(Tokens[Index] + 2, 'right') + Index = Index + 2 + else + missEnd(action[1].keyword[1], action[1].keyword[2]) + end + + return action +end + +local function parseFor() + local action = { + type = 'for', + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index] + 2, 'right'), + keyword = {}, + } + action.keyword[1] = action.start + action.keyword[2] = action.finish + Index = Index + 2 + pushActionIntoCurrentChunk(action) + pushChunk(action) + skipSpace() + local nameOrList = parseNameOrList() + if not nameOrList then + missName() + end + skipSpace() + -- for i = + if expectAssign() then + action.type = 'loop' + + skipSpace() + local expList = parseExpList() + local name + if nameOrList then + if nameOrList.type == 'name' then + name = nameOrList + else + name = nameOrList[1] + end + end + if name then + local loc = createLocal(name) + loc.parent = action + action.finish = name.finish + action.loc = loc + end + if expList then + local value = expList[1] + if value then + value.parent = action + action.init = value + action.finish = expList[#expList].finish + end + local max = expList[2] + if max then + max.parent = action + action.max = max + action.finish = max.finish + else + pushError { + type = 'MISS_LOOP_MAX', + start = lastRightPosition(), + finish = lastRightPosition(), + } + end + local step = expList[3] + if step then + step.parent = action + action.step = step + action.finish = step.finish + end + else + pushError { + type = 'MISS_LOOP_MIN', + start = lastRightPosition(), + finish = lastRightPosition(), + } + end + + if action.loc then + action.loc.effect = action.finish + end + elseif Tokens[Index + 1] == 'in' then + action.type = 'in' + local inLeft = getPosition(Tokens[Index], 'left') + local inRight = getPosition(Tokens[Index] + 1, 'right') + Index = Index + 2 + skipSpace() + + local exps = parseExpList() + + action.finish = inRight + action.keyword[3] = inLeft + action.keyword[4] = inRight + + local list + if nameOrList and nameOrList.type == 'name' then + list = { + type = 'list', + start = nameOrList.start, + finish = nameOrList.finish, + [1] = nameOrList, + } + else + list = nameOrList + end + + if exps then + local lastExp = exps[#exps] + if lastExp then + action.finish = lastExp.finish + end + + action.exps = exps + for i = 1, #exps do + local exp = exps[i] + exp.parent = action + end + else + missExp() + end + + if list then + local lastName = list[#list] + list.range = lastName and lastName.range or inRight + action.keys = list + for i = 1, #list do + local loc = createLocal(list[i]) + loc.parent = action + loc.effect = action.finish + end + end + else + missSymbol 'in' + end + + skipSpace() + local doToken = Tokens[Index + 1] + if doToken == 'do' + or doToken == 'then' then + local left = getPosition(Tokens[Index], 'left') + local right = getPosition(Tokens[Index] + #doToken - 1, 'right') + action.finish = left + action.keyword[#action.keyword+1] = left + action.keyword[#action.keyword+1] = right + if doToken == 'then' then + pushError { + type = 'ERR_DO_AS_THEN', + start = left, + finish = right, + fix = { + title = 'FIX_DO_AS_THEN', + { + start = left, + finish = right, + text = 'do', + } + } + } + end + Index = Index + 2 + else + missSymbol 'do' + end + + skipSpace() + parseActions() + popChunk() + + skipSpace() + if Tokens[Index + 1] == 'end' then + action.finish = getPosition(Tokens[Index] + 2, 'right') + action.keyword[#action.keyword+1] = getPosition(Tokens[Index], 'left') + action.keyword[#action.keyword+1] = action.finish + Index = Index + 2 + else + missEnd(action.keyword[1], action.keyword[2]) + end + + if action.locals then + LocalCount = LocalCount - #action.locals + end + + return action +end + +local function parseWhile() + local action = { + type = 'while', + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index] + 4, 'right'), + keyword = {}, + } + action.keyword[1] = action.start + action.keyword[2] = action.finish + Index = Index + 2 + + skipSpace() + local filter = parseExp() + if filter then + action.filter = filter + action.finish = filter.finish + filter.parent = action + else + missExp() + end + + skipSpace() + local doToken = Tokens[Index + 1] + if doToken == 'do' + or doToken == 'then' then + local left = getPosition(Tokens[Index], 'left') + local right = getPosition(Tokens[Index] + #doToken - 1, 'right') + action.finish = left + action.keyword[#action.keyword+1] = left + action.keyword[#action.keyword+1] = right + if doToken == 'then' then + pushError { + type = 'ERR_DO_AS_THEN', + start = left, + finish = right, + fix = { + title = 'FIX_DO_AS_THEN', + { + start = left, + finish = right, + text = 'do', + } + } + } + end + Index = Index + 2 + else + missSymbol 'do' + end + + pushActionIntoCurrentChunk(action) + pushChunk(action) + skipSpace() + parseActions() + popChunk() + + skipSpace() + if Tokens[Index + 1] == 'end' then + action.finish = getPosition(Tokens[Index] + 2, 'right') + action.keyword[#action.keyword+1] = getPosition(Tokens[Index], 'left') + action.keyword[#action.keyword+1] = action.finish + Index = Index + 2 + else + missEnd(action.keyword[1], action.keyword[2]) + end + + if action.locals then + LocalCount = LocalCount - #action.locals + end + + return action +end + +local function parseRepeat() + local action = { + type = 'repeat', + start = getPosition(Tokens[Index], 'left'), + finish = getPosition(Tokens[Index] + 5, 'right'), + keyword = {}, + } + action.keyword[1] = action.start + action.keyword[2] = action.finish + Index = Index + 2 + + pushActionIntoCurrentChunk(action) + pushChunk(action) + skipSpace() + parseActions() + + skipSpace() + if Tokens[Index + 1] == 'until' then + action.finish = getPosition(Tokens[Index] + 4, 'right') + action.keyword[#action.keyword+1] = getPosition(Tokens[Index], 'left') + action.keyword[#action.keyword+1] = action.finish + Index = Index + 2 + + skipSpace() + local filter = parseExp() + if filter then + action.filter = filter + filter.parent = action + else + missExp() + end + + else + missSymbol 'until' + end + + popChunk() + if action.filter then + action.finish = action.filter.finish + end + + if action.locals then + LocalCount = LocalCount - #action.locals + end + + return action +end + +local function parseBreak() + local returnLeft = getPosition(Tokens[Index], 'left') + local returnRight = getPosition(Tokens[Index] + 4, 'right') + Index = Index + 2 + skipSpace() + local action = { + type = 'break', + start = returnLeft, + finish = returnRight, + } + + local ok + for i = #Chunk, 1, -1 do + local chunk = Chunk[i] + if chunk.type == 'function' then + break + end + if chunk.type == 'while' + or chunk.type == 'in' + or chunk.type == 'loop' + or chunk.type == 'repeat' + or chunk.type == 'for' then + if not chunk.breaks then + chunk.breaks = {} + end + chunk.breaks[#chunk.breaks+1] = action + ok = true + break + end + end + if not ok and Mode == 'Lua' then + pushError { + type = 'BREAK_OUTSIDE', + start = action.start, + finish = action.finish, + } + end + + pushActionIntoCurrentChunk(action) + return action +end + +function parseAction() + local token = Tokens[Index + 1] + + if token == '::' then + return parseLabel() + end + + if token == 'local' then + return parseLocal() + end + + if token == 'if' + or token == 'elseif' + or token == 'else' then + return parseIf() + end + + if token == 'for' then + return parseFor() + end + + if token == 'do' then + return parseDo() + end + + if token == 'return' then + return parseReturn() + end + + if token == 'break' then + return parseBreak() + end + + if token == 'while' then + return parseWhile() + end + + if token == 'repeat' then + return parseRepeat() + end + + if token == 'goto' then + return parseGoTo() + end + + if token == 'function' then + local exp = parseFunction(false, true) + local name = exp.name + if name then + exp.name = nil + name.type = GetToSetMap[name.type] + name.value = exp + name.vstart = exp.start + name.range = exp.finish + exp.parent = name + pushActionIntoCurrentChunk(name) + return name + else + pushActionIntoCurrentChunk(exp) + missName(exp.keyword[2]) + return exp + end + end + + local exp = parseExp(true) + if exp then + local action = compileExpAsAction(exp) + if action then + return action + end + end + return nil, true +end + +local function skipFirstComment() + if Tokens[Index + 1] ~= '#' then + return + end + while true do + Index = Index + 2 + local token = Tokens[Index + 1] + if not token then + break + end + if NLMap[token] then + skipNL() + break + end + end +end + +local function parseLua() + local main = { + type = 'main', + start = 0, + finish = 0, + } + pushChunk(main) + createLocal{ + type = 'local', + start = 0, + finish = 0, + effect = 0, + tag = '_ENV', + special= '_G', + [1] = State.ENVMode, + } + LocalCount = 0 + skipFirstComment() + while true do + parseActions() + if Index <= #Tokens then + unknownSymbol() + Index = Index + 2 + else + break + end + end + popChunk() + main.finish = getPosition(#Lua, 'right') + + return main +end + +local function initState(lua, version, options) + Lua = lua + Line = 0 + LineOffset = 1 + LastTokenFinish = 0 + LocalCount = 0 + Chunk = {} + Tokens = tokens(lua) + Index = 1 + State = { + version = version, + lua = lua, + ast = {}, + errs = {}, + diags = {}, + comms = {}, + options = options or {}, + } + if version == 'Lua 5.1' or version == 'LuaJIT' then + State.ENVMode = '@fenv' + else + State.ENVMode = '_ENV' + end +end + +return function (lua, mode, version, options) + Mode = mode + initState(lua, version, options) + skipSpace() + if mode == 'Lua' then + State.ast = parseLua() + elseif mode == 'Nil' then + State.ast = parseNil() + elseif mode == 'Boolean' then + State.ast = parseBoolean() + elseif mode == 'String' then + State.ast = parseString() + elseif mode == 'Number' then + State.ast = parseNumber() + elseif mode == 'Exp' then + State.ast = parseExp() + elseif mode == 'Action' then + State.ast = parseAction() + end + + return State +end diff --git a/script/parser/parse.lua b/script/parser/parse.lua index 9b8d5496..e7c7d177 100644 --- a/script/parser/parse.lua +++ b/script/parser/parse.lua @@ -1,6 +1,7 @@ -local ast = require 'parser.ast' +local ast = require 'parser.ast' +local grammar = require 'parser.grammar' -return function (self, lua, mode, version, options) +local function buildState(lua, version, options) local errs = {} local diags = {} local comms = {} @@ -36,9 +37,19 @@ return function (self, lua, mode, version, options) comms[#comms+1] = comment end } + if version == 'Lua 5.1' or version == 'LuaJIT' then + state.ENVMode = '@fenv' + else + state.ENVMode = '_ENV' + end + return state +end + +return function (lua, mode, version, options) + local state = buildState(lua, version, options) local clock = os.clock() ast.init(state) - local suc, res, err = xpcall(self.grammar, debug.traceback, self, lua, mode) + local suc, res, err = xpcall(grammar, debug.traceback, lua, mode) ast.close() if not suc then return nil, res diff --git a/script/parser/tokens.lua b/script/parser/tokens.lua new file mode 100644 index 00000000..958f292e --- /dev/null +++ b/script/parser/tokens.lua @@ -0,0 +1,38 @@ +local m = require 'lpeglabel' + +local Sp = m.S' \t' +local Nl = m.P'\r\n' + m.S'\r\n' +local Number = m.R'09'^1 +local Word = m.R('AZ', 'az', '__', '\x80\xff') * m.R('AZ', 'az', '09', '__', '\x80\xff')^0 +local Symbol = m.P'==' + + m.P'~=' + + m.P'--' + + m.P'<<' + + m.P'>>' + + m.P'<=' + + m.P'>=' + + m.P'//' + + m.P'...' + + m.P'..' + + m.P'::' + -- incorrect + + m.P'!=' + + m.P'&&' + + m.P'||' + + m.P'/*' + + m.P'*/' + + m.P'+=' + + m.P'-=' + + m.P'*=' + + m.P'/=' + -- singles + + m.S'+-*/!#%^&()={}[]|\\\'":;<>,.?~`' +local Unknown = (1 - Number - Word - Symbol - Sp - Nl)^1 +local Token = m.Cp() * m.C(Nl + Number + Word + Symbol + Unknown) + +local Parser = m.Ct((Sp^1 + Token)^0) + +return function (lua) + local results = Parser:match(lua) + return results +end -- cgit v1.2.3 From 5a43c5f78a9d13b9d18ba58bd45c85e7521d9f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Tue, 14 Sep 2021 17:23:50 +0800 Subject: fix --- script/brave/work.lua | 4 ++-- script/core/completion.lua | 2 +- script/files.lua | 11 +++++------ script/parser/newparser.lua | 46 ++++++++++++++++++++++++++------------------- 4 files changed, 35 insertions(+), 28 deletions(-) diff --git a/script/brave/work.lua b/script/brave/work.lua index 907f78cf..ee7b4acd 100644 --- a/script/brave/work.lua +++ b/script/brave/work.lua @@ -26,12 +26,12 @@ brave.on('timer', function (time) end) brave.on('compile', function (text) - local state, err = parser:compile(text, 'lua', 'Lua 5.4') + local state, err = parser.compile(text, 'lua', 'Lua 5.4') if not state then log.error(err) return end - local lines = parser:lines(text) + local lines = parser.lines(text) return { root = state.root, value = state.value, diff --git a/script/core/completion.lua b/script/core/completion.lua index fb7b2eb4..f81f8179 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -1049,7 +1049,7 @@ local function tryLabelInString(label, source) if not source or source.type ~= 'string' then return label end - local str = parser:grammar(label, 'String') + local str = parser.grammar(label, 'String') if not str then return label end diff --git a/script/files.lua b/script/files.lua index fa5474ef..ecaaa5a5 100644 --- a/script/files.lua +++ b/script/files.lua @@ -446,14 +446,13 @@ function m.compileState(uri, text) local prog = progress.create(lang.script.WINDOW_COMPILING, 0.5) prog:setMessage(ws.getRelativePath(uri)) local clock = os.clock() - local state, err = parser:compile(text - , 'lua' + local state, err = parser.compile(text + , 'Lua' , config.get 'Lua.runtime.version' , { special = config.get 'Lua.runtime.special', unicodeName = config.get 'Lua.runtime.unicodeName', nonstandardSymbol = config.get 'Lua.runtime.nonstandardSymbol', - delay = await.delay, } ) local passed = os.clock() - clock @@ -465,7 +464,7 @@ function m.compileState(uri, text) state.uri = uri state.ast.uri = uri local clock = os.clock() - parser:luadoc(state) + parser.luadoc(state) local passed = os.clock() - clock if passed > 0.1 then log.warn(('Parse LuaDoc of [%s] takes [%.3f] sec, size [%.3f] kb.'):format(uri, passed, #text / 1000)) @@ -548,7 +547,7 @@ function m.getLines(uri) end local lines = m.linesMap[uri] if not lines then - lines = parser:lines(file.text) + lines = parser.lines(file.text) m.linesMap[uri] = lines end return lines @@ -561,7 +560,7 @@ function m.getOriginLines(uri) end local lines = m.originLinesMap[uri] if not lines then - lines = parser:lines(file.originText) + lines = parser.lines(file.originText) m.originLinesMap[uri] = lines end return lines diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index 7fd0ec31..e1d98d87 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -1598,8 +1598,9 @@ local function parseSimple(node, funcName) finish = lastRightPosition(), } end - node.next = getfield - node = getfield + node.parent = getfield + node.next = getfield + node = getfield elseif token == ':' then local colon = { type = token, @@ -1627,8 +1628,9 @@ local function parseSimple(node, funcName) finish = lastRightPosition(), } end - node.next = getmethod - node = getmethod + node.parent = getmethod + node.next = getmethod + node = getmethod if lastMethod then missSymbol('(', node.node.finish, node.node.finish) end @@ -1678,28 +1680,30 @@ local function parseSimple(node, funcName) call.node.node.mirror = newNode tinsert(call.args, 1, newNode) end + node.parent = call node = call elseif token == '{' then if funcName then break end - local str = parseTable() + local tbl = parseTable() local call = { type = 'call', start = node.start, - finish = str.finish, + finish = tbl.finish, node = node, } local args = { type = 'callargs', - start = str.start, - finish = str.finish, + start = tbl.start, + finish = tbl.finish, parent = call, - [1] = str, + [1] = tbl, } - call.args = args - str.parent = args - return call + call.args = args + tbl.parent = args + node.parent = call + node = call elseif CharMapStrSH[token] then if funcName then break @@ -1718,9 +1722,10 @@ local function parseSimple(node, funcName) parent = call, [1] = str, } - call.args = args - str.parent = args - return call + call.args = args + str.parent = args + node.parent = args + node = call elseif CharMapStrLH[token] then local str = parseLongString() if str then @@ -1740,9 +1745,10 @@ local function parseSimple(node, funcName) parent = call, [1] = str, } - call.args = args - str.parent = args - return call + call.args = args + str.parent = args + node.parent = call + node = call else local index = parseIndex() index.type = 'getindex' @@ -1750,7 +1756,8 @@ local function parseSimple(node, funcName) index.start = node.start index.node = node node.next = index - node = index + node.parent = index + node = index if funcName then pushError { type = 'INDEX_IN_FUNC_NAME', @@ -3458,6 +3465,7 @@ local function parseLua() start = 0, finish = 0, effect = 0, + parent = main, tag = '_ENV', special= '_G', [1] = State.ENVMode, -- cgit v1.2.3 From 4d1b606cc875803cc07031c63cde351300ea664a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Tue, 14 Sep 2021 19:32:31 +0800 Subject: update --- test/basic/noder.lua | 24 ++++++++++------------ test/catch.lua | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 13 deletions(-) create mode 100644 test/catch.lua diff --git a/test/basic/noder.lua b/test/basic/noder.lua index bc572a4c..4c0a1620 100644 --- a/test/basic/noder.lua +++ b/test/basic/noder.lua @@ -2,6 +2,7 @@ local noder = require 'core.noder' local files = require 'files' local util = require 'utility' local guide = require 'parser.guide' +local catch = require 'catch' local function getSource(pos) local ast = files.getState('') @@ -30,12 +31,9 @@ local CARE = {} local function TEST(script) return function (expect) files.removeAll() - local start = script:find('', 1, true) - local pos = (start + finish) // 2 + 1 - local newScript = script:gsub('<[!?]', ' '):gsub('[!?]>', ' ') + local newScript, catched = catch(script, '?') files.setText('', newScript) - local source = getSource(pos) + local source = getSource(catched[1][1]) assert(source) local result = { id = noder.getID(source), @@ -53,21 +51,21 @@ CARE['id'] = true TEST [[ local ]] { - id = 'l:9', + id = 'l:6', } TEST [[ local x print() ]] { - id = 'l:7', + id = 'l:6', } TEST [[ local x = 1 ]] { - id = 'l:7', + id = 'l:6', } TEST [[ @@ -86,14 +84,14 @@ TEST [[ local x print(x.y.) ]] { - id = 'l:7|.y|.z', + id = 'l:6|.y|.z', } TEST [[ local x function x:() end ]] { - id = 'l:7|.f', + id = 'l:6|.f', } TEST [[ @@ -113,7 +111,7 @@ TEST [[ = 1, } ]] { - id = 't:1|.x', + id = 't:0|.x', } TEST [[ @@ -134,12 +132,12 @@ TEST [[ :::: goto label ]] { - id = 'l:5', + id = 'l:2', } TEST [[ ::label:: goto ]] { - id = 'l:3', + id = 'l:2', } diff --git a/test/catch.lua b/test/catch.lua new file mode 100644 index 00000000..910c368f --- /dev/null +++ b/test/catch.lua @@ -0,0 +1,58 @@ + +local function getLine(offset, lns) + for i = 0, #lns do + if offset >= lns[i] + and offset < lns[i+1] then + return i + end + end +end + +local function getPosition(offset, lns) + for i = 0, #lns do + if offset >= lns[i] + and offset < lns[i+1] then + return 10000 * i + offset - lns[i] + end + end +end + +---@param script string +---@param sep string +return function (script, sep) + local pattern = ('()<%%%s.-%%%s>()'):format(sep, sep) + local lns = {} + lns[0] = 0 + for pos in script:gmatch '()\n' do + lns[#lns+1] = pos + end + lns[#lns+1] = math.maxinteger + local codes = {} + local pos = 1 + ---@type integer[] + local list = {} + local cuted = 0 + local lastLine = 0 + for a, b in script:gmatch(pattern) do + codes[#codes+1] = script:sub(pos, a - 1) + codes[#codes+1] = script:sub(a + 2, b - 3) + pos = b + local line1 = getLine(a + 1, lns) + if line1 ~= lastLine then + cuted = 0 + lastLine = line1 + end + cuted = cuted + 2 + local left = getPosition(a + 1, lns) - cuted + local line2 = getLine(b - 3, lns) + if line2 ~= lastLine then + cuted = 0 + lastLine = line2 + end + local right = getPosition(b - 3, lns) - cuted + cuted = cuted + 2 + list[#list+1] = { left, right } + end + codes[#codes+1] = script:sub(pos) + return table.concat(codes), list +end -- cgit v1.2.3 From 5a072004414ff1f8de416c62a4067774f72e7097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Tue, 14 Sep 2021 20:43:33 +0800 Subject: cleanup --- script/core/code-action.lua | 2 +- script/core/completion.lua | 2 +- script/core/diagnostics/newfield-call.lua | 4 +- script/core/diagnostics/newline-call.lua | 4 +- script/core/find-source.lua | 6 +-- script/core/keyword.lua | 4 +- script/core/reference.lua | 4 +- script/core/type-formatting.lua | 2 +- script/files.lua | 2 +- script/parser/guide.lua | 88 +++++++++---------------------- script/parser/luadoc.lua | 12 ++--- script/vm/getDocs.lua | 2 +- test/basic/noder.lua | 2 +- test/catch.lua | 28 ++++++++-- test/references/init.lua | 27 +++------- 15 files changed, 78 insertions(+), 111 deletions(-) diff --git a/script/core/code-action.lua b/script/core/code-action.lua index 64f862f9..1bac9359 100644 --- a/script/core/code-action.lua +++ b/script/core/code-action.lua @@ -57,7 +57,7 @@ end local function disableDiagnostic(uri, code, start, results) local lines = files.getLines(uri) - local row = guide.positionOf(lines, start) + local row = guide.positionOf(start) results[#results+1] = { title = lang.script('ACTION_DISABLE_DIAG', code), kind = 'quickfix', diff --git a/script/core/completion.lua b/script/core/completion.lua index f81f8179..59dc19f3 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -176,7 +176,7 @@ local function getSnip(source) if vm.isMetaFile(uri) then goto CONTINUE end - local row = guide.positionOf(lines, def.start) + local row = guide.positionOf(def.start) local firstRow = lines[row] local lastRow = lines[math.min(row + context - 1, #lines)] local snip = text:sub(firstRow.start, lastRow.finish) diff --git a/script/core/diagnostics/newfield-call.lua b/script/core/diagnostics/newfield-call.lua index fe86ad66..61d52dd2 100644 --- a/script/core/diagnostics/newfield-call.lua +++ b/script/core/diagnostics/newfield-call.lua @@ -27,8 +27,8 @@ return function (uri, callback) local func = call.node local args = call.args if args then - local funcLine = guide.positionOf(lines, func.finish) - local argsLine = guide.positionOf(lines, args.start) + local funcLine = guide.positionOf(func.finish) + local argsLine = guide.positionOf(args.start) if argsLine > funcLine then callback { start = call.start, diff --git a/script/core/diagnostics/newline-call.lua b/script/core/diagnostics/newline-call.lua index 71dc33e2..69bf948f 100644 --- a/script/core/diagnostics/newline-call.lua +++ b/script/core/diagnostics/newline-call.lua @@ -26,8 +26,8 @@ return function (uri, callback) return end - local nodeRow = guide.positionOf(lines, node.finish) - local argRow = guide.positionOf(lines, args.start) + local nodeRow = guide.positionOf(node.finish) + local argRow = guide.positionOf(args.start) if nodeRow == argRow then return end diff --git a/script/core/find-source.lua b/script/core/find-source.lua index edbb1e2c..26a411e5 100644 --- a/script/core/find-source.lua +++ b/script/core/find-source.lua @@ -11,12 +11,12 @@ local function isValidFunctionPos(source, offset) return false end -return function (ast, offset, accept) +return function (ast, position, accept) local len = math.huge local result - guide.eachSourceContain(ast.ast, offset, function (source) + guide.eachSourceContain(ast.ast, position, function (source) if source.type == 'function' then - if not isValidFunctionPos(source, offset) then + if not isValidFunctionPos(source, position) then return end end diff --git a/script/core/keyword.lua b/script/core/keyword.lua index b8e37605..4b43efe5 100644 --- a/script/core/keyword.lua +++ b/script/core/keyword.lua @@ -275,8 +275,8 @@ until $1" if first == 'end' or first == 'else' or first == 'elseif' then - local startRow = guide.positionOf(lines, info.start) - local finishRow = guide.positionOf(lines, pos) + local startRow = guide.positionOf(info.start) + local finishRow = guide.positionOf(pos) local startSp = info.text:match('^%s*', lines[startRow].start + 1) local finishSp = info.text:match('^%s*', lines[finishRow].start + 1) if startSp == finishSp then diff --git a/script/core/reference.lua b/script/core/reference.lua index 5f5831c6..067d2e23 100644 --- a/script/core/reference.lua +++ b/script/core/reference.lua @@ -52,13 +52,13 @@ local accept = { ['doc.alias.name'] = true, } -return function (uri, offset) +return function (uri, position) local ast = files.getState(uri) if not ast then return nil end - local source = findSource(ast, offset, accept) + local source = findSource(ast, position, accept) if not source then return nil end diff --git a/script/core/type-formatting.lua b/script/core/type-formatting.lua index a225d9d7..12272f11 100644 --- a/script/core/type-formatting.lua +++ b/script/core/type-formatting.lua @@ -5,7 +5,7 @@ local guide = require "parser.guide" local function insertIndentation(uri, offset, edits) local lines = files.getLines(uri) local text = files.getOriginText(uri) - local row = guide.positionOf(lines, offset) + local row = guide.positionOf(offset) local line = lines[row] local indent = text:sub(line.start, line.finish):match '^%s*' for _, edit in ipairs(edits) do diff --git a/script/files.lua b/script/files.lua index ecaaa5a5..0e62a740 100644 --- a/script/files.lua +++ b/script/files.lua @@ -744,7 +744,7 @@ function m.position(uri, offset, leftOrRight) lines = m.getOriginLines(uri) text = m.getOriginText(uri) end - local row, col = guide.positionOf(lines, offset) + local row, col = guide.positionOf(offset) local start, finish = guide.lineRange(lines, row, true) start = start + 1 if col <= finish - start + 1 then diff --git a/script/parser/guide.lua b/script/parser/guide.lua index e5e9ead1..941fc7b1 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -548,24 +548,24 @@ function m.getRange(source) return start, finish end ---- 判断source是否包含offset -function m.isContain(source, offset) +--- 判断source是否包含position +function m.isContain(source, position) local start, finish = m.getStartFinish(source) if not start then return false end - return start <= offset and finish >= offset + return start <= position and finish >= position end ---- 判断offset在source的影响范围内 +--- 判断position在source的影响范围内 --- --- 主要针对赋值等语句时,key包含value -function m.isInRange(source, offset) +function m.isInRange(source, position) local start, finish = m.getRange(source) if not start then return false end - return start <= offset and finish >= offset + return start <= position and finish >= position end function m.isBetween(source, tStart, tFinish) @@ -597,8 +597,8 @@ local function addChilds(list, obj) f(obj, list) end ---- 遍历所有包含offset的source -function m.eachSourceContain(ast, offset, callback) +--- 遍历所有包含position的source +function m.eachSourceContain(ast, position, callback) local list = { ast } local mark = {} while true do @@ -610,8 +610,8 @@ function m.eachSourceContain(ast, offset, callback) list[len] = nil if not mark[obj] then mark[obj] = true - if m.isInRange(obj, offset) then - if m.isContain(obj, offset) then + if m.isInRange(obj, position) then + if m.isContain(obj, position) then local res = callback(obj) if res ~= nil then return res @@ -737,64 +737,24 @@ function m.eachSpecialOf(ast, name, callback) end end ---- 获取光标偏移对应的坐标。 ---- 如果在换行符的右侧,则认为在新的一行。 ---- 第一行的行号是1不是0。 ----@param lines table ----@return integer {name = 'row'} ----@return integer {name = 'col'} -function m.positionOf(lines, offset) - if offset <= 0 then - return 1, 0 - end - local lastLine = lines[#lines] - if offset >= lastLine.finish then - return #lines, lastLine.finish - lastLine.start - end - local min = 1 - local max = #lines - for _ = 1, 100 do - if max <= min then - local line = lines[min] - return min, offset - line.start - end - local row = (max - min) // 2 + min - local line = lines[row] - if offset < line.start then - max = row - 1 - elseif offset >= line.finish then - min = row + 1 - else - return row, offset - line.start - end - end - error('Stack overflow!') +--- 将 position 拆分成行号与列号 +--- +--- 第一行是0 +---@param position integer +---@return integer row +---@return integer col +function m.positionOf(position) + return position // 10000, position % 10000 end ---- 获取坐标对应的光标偏移。 ---- 一定会落在当前行的换行符左侧。 ---- 第一行的行号是1不是0。 ----@param lines table +--- 将行列合并为 position +--- +--- 第一行是0 ---@param row integer ---@param col integer ----@return integer {name = 'offset'} -function m.offsetOf(lines, row, col) - if row < 1 then - return 0 - end - if row > #lines then - local lastLine = lines[#lines] - return lastLine.finish - end - local line = lines[row] - local len = line.range - line.start - if col < 0 then - return line.start - elseif col > len then - return line.range - else - return line.start + col - end +---@return integer +function m.offsetOf(row, col) + return row * 10000 + col end function m.lineContent(lines, text, row, ignoreNL) diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 26341571..533aa9db 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -635,7 +635,7 @@ function parseType(parent) result.finish = getFinish() result.firstFinish = result.finish - local row = guide.positionOf(Lines, result.finish) + local row = guide.positionOf(result.finish) local function pushResume() local comments @@ -1178,8 +1178,8 @@ end local function isTailComment(lns, text, binded, doc) local lastDoc = binded[#binded] - local lastDocStartRow = guide.positionOf(lns, lastDoc.originalComment.start) - local lastDocStartLineData = guide.lineData(lns, lastDocStartRow) + local lastDocStartRow = guide.positionOf(lastDoc.originalComment.start) + local lastDocStartLineData = guide.lineData(lastDocStartRow) if haveCodeBeforeDocInCurLine(text, lastDocStartLineData, lastDoc.originalComment.start) then return true end @@ -1191,8 +1191,8 @@ local function isNextLine(lns, text, binded, doc) return false end local lastDoc = binded[#binded] - local lastRow = guide.positionOf(lns, lastDoc.finish) - local newRow = guide.positionOf(lns, doc.start) + local lastRow = guide.positionOf(lastDoc.finish) + local newRow = guide.positionOf(doc.start) return newRow - lastRow == 1 end @@ -1332,7 +1332,7 @@ local function bindDoc(sources, lns, binded) doc.bindSources = bindSources end bindGeneric(binded) - local row = guide.positionOf(lns, lastDoc.finish) + local row = guide.positionOf(lastDoc.finish) local cstart, cfinish = guide.lineRange(lns, row) local nstart, nfinish = guide.lineRange(lns, row + 1) bindDocsBetween(sources, binded, bindSources, cstart, cfinish) diff --git a/script/vm/getDocs.lua b/script/vm/getDocs.lua index c0205654..5fcf9478 100644 --- a/script/vm/getDocs.lua +++ b/script/vm/getDocs.lua @@ -186,7 +186,7 @@ local function makeDiagRange(uri, doc, results) names[name] = true end end - local row = guide.positionOf(lines, doc.start) + local row = guide.positionOf(doc.start) if doc.mode == 'disable-next-line' then if lines[row+1] then results[#results+1] = { diff --git a/test/basic/noder.lua b/test/basic/noder.lua index 4c0a1620..87b34e12 100644 --- a/test/basic/noder.lua +++ b/test/basic/noder.lua @@ -33,7 +33,7 @@ local function TEST(script) files.removeAll() local newScript, catched = catch(script, '?') files.setText('', newScript) - local source = getSource(catched[1][1]) + local source = getSource(catched['?'][1][1]) assert(source) local result = { id = noder.getID(source), diff --git a/test/catch.lua b/test/catch.lua index 910c368f..09b55929 100644 --- a/test/catch.lua +++ b/test/catch.lua @@ -1,3 +1,22 @@ +local mt = {} + +local function catchedTable() + return setmetatable({}, mt) +end + +function mt.__add(a, b) + if not a or not b then + return a or b + end + local t = catchedTable() + for _, v in ipairs(a) do + t[#t+1] = v + end + for _, v in ipairs(b) do + t[#t+1] = v + end + return t +end local function getLine(offset, lns) for i = 0, #lns do @@ -20,7 +39,7 @@ end ---@param script string ---@param sep string return function (script, sep) - local pattern = ('()<%%%s.-%%%s>()'):format(sep, sep) + local pattern = ('()<(%s).-%s>()'):format(sep, sep) local lns = {} lns[0] = 0 for pos in script:gmatch '()\n' do @@ -33,7 +52,7 @@ return function (script, sep) local list = {} local cuted = 0 local lastLine = 0 - for a, b in script:gmatch(pattern) do + for a, char, b in script:gmatch(pattern) do codes[#codes+1] = script:sub(pos, a - 1) codes[#codes+1] = script:sub(a + 2, b - 3) pos = b @@ -51,7 +70,10 @@ return function (script, sep) end local right = getPosition(b - 3, lns) - cuted cuted = cuted + 2 - list[#list+1] = { left, right } + if not list[char] then + list[char] = catchedTable() + end + list[char][#list[char]+1] = { left, right } end codes[#codes+1] = script:sub(pos) return table.concat(codes), list diff --git a/test/references/init.lua b/test/references/init.lua index 2fba92e5..a14f0a02 100644 --- a/test/references/init.lua +++ b/test/references/init.lua @@ -1,19 +1,6 @@ local core = require 'core.reference' local files = require 'files' - -local function catch_target(script) - local list = {} - local cur = 1 - while true do - local start, finish = script:find('<[!?].-[!?]>', cur) - if not start then - break - end - list[#list+1] = { start + 2, finish - 2 } - cur = finish + 1 - end - return list -end +local catch = require 'catch' local function founded(targets, results) if #targets ~= #results then @@ -33,14 +20,12 @@ end function TEST(script) files.removeAll() - local expect = catch_target(script) - local start = script:find('<[?~]') - local finish = script:find('[?~]>') - local pos = (start + finish) // 2 + 1 - local new_script = script:gsub('<[!?~]', ' '):gsub('[!?~]>', ' ') - files.setText('', new_script) + local newScript, catched = catch(script, '[!?~]') + files.setText('', newScript) - local results = core('', pos) + local input = catched['?'] + catched['~'] + local expect = catched['!'] + catched['?'] + catched['~'] + local results = core('', input[1][1]) if results then local positions = {} for i, result in ipairs(results) do -- cgit v1.2.3 From 6fddbbf0b34729327670ac1687d88b38739e12a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Tue, 14 Sep 2021 21:04:50 +0800 Subject: update --- script/parser/newparser.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index e1d98d87..16bcd6a0 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -1589,7 +1589,7 @@ local function parseSimple(node, funcName) field = field } if field then - field.parent = node + field.parent = getfield field.type = 'field' else pushError { @@ -1619,7 +1619,7 @@ local function parseSimple(node, funcName) method = method } if method then - method.parent = node + method.parent = getmethod method.type = 'method' else pushError { @@ -3462,9 +3462,9 @@ local function parseLua() pushChunk(main) createLocal{ type = 'local', - start = 0, - finish = 0, - effect = 0, + start = -1, + finish = -1, + effect = -1, parent = main, tag = '_ENV', special= '_G', -- cgit v1.2.3 From 8880b7d63931469c0b7bfb69004f342236ce2811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 15 Sep 2021 16:11:30 +0800 Subject: cleanup --- script/core/code-action.lua | 2 +- script/core/completion.lua | 2 +- script/core/diagnostics/newfield-call.lua | 4 +-- script/core/diagnostics/newline-call.lua | 4 +-- script/core/keyword.lua | 4 +-- script/core/type-formatting.lua | 2 +- script/files.lua | 2 +- script/parser/guide.lua | 4 +-- script/parser/luadoc.lua | 42 ++++++++++++++----------------- script/parser/newparser.lua | 7 +++++- script/vm/getDocs.lua | 2 +- test/example/guide.txt | 4 +-- 12 files changed, 40 insertions(+), 39 deletions(-) diff --git a/script/core/code-action.lua b/script/core/code-action.lua index 1bac9359..922ebff3 100644 --- a/script/core/code-action.lua +++ b/script/core/code-action.lua @@ -57,7 +57,7 @@ end local function disableDiagnostic(uri, code, start, results) local lines = files.getLines(uri) - local row = guide.positionOf(start) + local row = guide.rowColOf(start) results[#results+1] = { title = lang.script('ACTION_DISABLE_DIAG', code), kind = 'quickfix', diff --git a/script/core/completion.lua b/script/core/completion.lua index 59dc19f3..1b64bef1 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -176,7 +176,7 @@ local function getSnip(source) if vm.isMetaFile(uri) then goto CONTINUE end - local row = guide.positionOf(def.start) + local row = guide.rowColOf(def.start) local firstRow = lines[row] local lastRow = lines[math.min(row + context - 1, #lines)] local snip = text:sub(firstRow.start, lastRow.finish) diff --git a/script/core/diagnostics/newfield-call.lua b/script/core/diagnostics/newfield-call.lua index 61d52dd2..83d205ca 100644 --- a/script/core/diagnostics/newfield-call.lua +++ b/script/core/diagnostics/newfield-call.lua @@ -27,8 +27,8 @@ return function (uri, callback) local func = call.node local args = call.args if args then - local funcLine = guide.positionOf(func.finish) - local argsLine = guide.positionOf(args.start) + local funcLine = guide.rowColOf(func.finish) + local argsLine = guide.rowColOf(args.start) if argsLine > funcLine then callback { start = call.start, diff --git a/script/core/diagnostics/newline-call.lua b/script/core/diagnostics/newline-call.lua index 69bf948f..1c31fa8d 100644 --- a/script/core/diagnostics/newline-call.lua +++ b/script/core/diagnostics/newline-call.lua @@ -26,8 +26,8 @@ return function (uri, callback) return end - local nodeRow = guide.positionOf(node.finish) - local argRow = guide.positionOf(args.start) + local nodeRow = guide.rowColOf(node.finish) + local argRow = guide.rowColOf(args.start) if nodeRow == argRow then return end diff --git a/script/core/keyword.lua b/script/core/keyword.lua index 4b43efe5..8e041f1c 100644 --- a/script/core/keyword.lua +++ b/script/core/keyword.lua @@ -275,8 +275,8 @@ until $1" if first == 'end' or first == 'else' or first == 'elseif' then - local startRow = guide.positionOf(info.start) - local finishRow = guide.positionOf(pos) + local startRow = guide.rowColOf(info.start) + local finishRow = guide.rowColOf(pos) local startSp = info.text:match('^%s*', lines[startRow].start + 1) local finishSp = info.text:match('^%s*', lines[finishRow].start + 1) if startSp == finishSp then diff --git a/script/core/type-formatting.lua b/script/core/type-formatting.lua index 12272f11..157a446d 100644 --- a/script/core/type-formatting.lua +++ b/script/core/type-formatting.lua @@ -5,7 +5,7 @@ local guide = require "parser.guide" local function insertIndentation(uri, offset, edits) local lines = files.getLines(uri) local text = files.getOriginText(uri) - local row = guide.positionOf(offset) + local row = guide.rowColOf(offset) local line = lines[row] local indent = text:sub(line.start, line.finish):match '^%s*' for _, edit in ipairs(edits) do diff --git a/script/files.lua b/script/files.lua index 0e62a740..98d9b83c 100644 --- a/script/files.lua +++ b/script/files.lua @@ -744,7 +744,7 @@ function m.position(uri, offset, leftOrRight) lines = m.getOriginLines(uri) text = m.getOriginText(uri) end - local row, col = guide.positionOf(offset) + local row, col = guide.rowColOf(offset) local start, finish = guide.lineRange(lines, row, true) start = start + 1 if col <= finish - start + 1 then diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 941fc7b1..14e19094 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -743,7 +743,7 @@ end ---@param position integer ---@return integer row ---@return integer col -function m.positionOf(position) +function m.rowColOf(position) return position // 10000, position % 10000 end @@ -753,7 +753,7 @@ end ---@param row integer ---@param col integer ---@return integer -function m.offsetOf(row, col) +function m.positionOf(row, col) return row * 10000 + col end diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 533aa9db..548539a9 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -1,11 +1,10 @@ local m = require 'lpeglabel' local re = require 'parser.relabel' -local lines = require 'parser.lines' local guide = require 'parser.guide' local grammar = require 'parser.grammar' local TokenTypes, TokenStarts, TokenFinishs, TokenContents -local Ci, Offset, pushError, Ct, NextComment, Lines +local Ci, Offset, pushError, NextComment local parseType local Parser = re.compile([[ Main <- (Token / Sp)* @@ -635,7 +634,7 @@ function parseType(parent) result.finish = getFinish() result.firstFinish = result.finish - local row = guide.positionOf(result.finish) + local row = guide.rowColOf(result.finish) local function pushResume() local comments @@ -644,8 +643,9 @@ function parseType(parent) if not nextComm then return false end - local line = Lines[row + i + 1] - if not line or line.finish < nextComm.start then + local nextCommRow = guide.rowColOf(nextComm.start) + local currentRow = row + i + 1 + if currentRow > nextCommRow then return false end if nextComm.text:sub(1, 2) == '-@' then @@ -1176,9 +1176,9 @@ local function haveCodeBeforeDocInCurLine(text, lineData, docStart) return text:sub(lineData.start + 1, docStart - 1):find '[%w_]' end -local function isTailComment(lns, text, binded, doc) +local function isTailComment(text, binded) local lastDoc = binded[#binded] - local lastDocStartRow = guide.positionOf(lastDoc.originalComment.start) + local lastDocStartRow = guide.rowColOf(lastDoc.originalComment.start) local lastDocStartLineData = guide.lineData(lastDocStartRow) if haveCodeBeforeDocInCurLine(text, lastDocStartLineData, lastDoc.originalComment.start) then return true @@ -1186,13 +1186,13 @@ local function isTailComment(lns, text, binded, doc) return false end -local function isNextLine(lns, text, binded, doc) +local function isNextLine(binded, doc) if not binded then return false end local lastDoc = binded[#binded] - local lastRow = guide.positionOf(lastDoc.finish) - local newRow = guide.positionOf(doc.start) + local lastRow = guide.rowColOf(lastDoc.finish) + local newRow = guide.rowColOf(doc.start) return newRow - lastRow == 1 end @@ -1318,7 +1318,7 @@ local function bindClassAndFields(binded) end end -local function bindDoc(sources, lns, binded) +local function bindDoc(sources, binded) if not binded then return end @@ -1332,12 +1332,10 @@ local function bindDoc(sources, lns, binded) doc.bindSources = bindSources end bindGeneric(binded) - local row = guide.positionOf(lastDoc.finish) - local cstart, cfinish = guide.lineRange(lns, row) - local nstart, nfinish = guide.lineRange(lns, row + 1) - bindDocsBetween(sources, binded, bindSources, cstart, cfinish) + local row = guide.rowColOf(lastDoc.finish) + bindDocsBetween(sources, binded, bindSources, guide.positionOf(row, 0), lastDoc.start) if #bindSources == 0 then - bindDocsBetween(sources, binded, bindSources, nstart, nfinish) + bindDocsBetween(sources, binded, bindSources, guide.positionOf(row + 1, 0), guide.positionOf(row + 2, 0)) end bindParamAndReturnIndex(binded) bindClassAndFields(binded) @@ -1361,18 +1359,18 @@ local function bindDocs(state) end) local binded for _, doc in ipairs(state.ast.docs) do - if not isNextLine(Lines, text, binded, doc) then - bindDoc(sources, Lines, binded) + if not isNextLine(binded, doc) then + bindDoc(sources, binded) binded = {} state.ast.docs.groups[#state.ast.docs.groups+1] = binded end binded[#binded+1] = doc - if isTailComment(Lines, text, binded, doc) then - bindDoc(sources, Lines, binded) + if isTailComment(text, binded) then + bindDoc(sources, binded) binded = nil end end - bindDoc(sources, Lines, binded) + bindDoc(sources, binded) end return function (state) @@ -1389,8 +1387,6 @@ return function (state) pushError = state.pushError - Lines = lines(state.lua) - local ci = 1 NextComment = function (offset, peek) local comment = comments[ci + (offset or 0)] diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index 16bcd6a0..0137397d 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -361,6 +361,7 @@ local function skipNL() Line = Line + 1 LineOffset = Tokens[Index] + #token Index = Index + 2 + State.lines[Line] = LineOffset return true end return false @@ -392,8 +393,11 @@ local function resolveLongString(finishMark) local result, count = stringResult : gsub('\r\n', '\n') : gsub('[\r\n]', '\n') - Line = Line + count LineOffset = lastLN + start + for i = Line + 1, Line + count do + State.lines[i] = LineOffset + end + Line = Line + count stringResult = result end fastForwardToken(finishOffset + #finishMark) @@ -3503,6 +3507,7 @@ local function initState(lua, version, options) errs = {}, diags = {}, comms = {}, + lines = {}, options = options or {}, } if version == 'Lua 5.1' or version == 'LuaJIT' then diff --git a/script/vm/getDocs.lua b/script/vm/getDocs.lua index 5fcf9478..218dc048 100644 --- a/script/vm/getDocs.lua +++ b/script/vm/getDocs.lua @@ -186,7 +186,7 @@ local function makeDiagRange(uri, doc, results) names[name] = true end end - local row = guide.positionOf(doc.start) + local row = guide.rowColOf(doc.start) if doc.mode == 'disable-next-line' then if lines[row+1] then results[#results+1] = { diff --git a/test/example/guide.txt b/test/example/guide.txt index da8d5c32..cff05faf 100644 --- a/test/example/guide.txt +++ b/test/example/guide.txt @@ -586,7 +586,7 @@ end ---@param lines table ---@return integer {name = 'row'} ---@return integer {name = 'col'} -function m.positionOf(lines, offset) +function m.rowColOf(lines, offset) if offset < 1 then return 0, 0 end @@ -619,7 +619,7 @@ end ---@param row integer ---@param col integer ---@return integer {name = 'offset'} -function m.offsetOf(lines, row, col) +function m.positionOf(lines, row, col) if row < 1 then return 0 end -- cgit v1.2.3 From 33eff2cb98efe8380513b1cc2712baab2be3c940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 15 Sep 2021 16:35:06 +0800 Subject: update --- script/parser/guide.lua | 4 ---- script/parser/luadoc.lua | 21 ++++++++------------- script/parser/newparser.lua | 23 +++++++++++++++++++++-- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 14e19094..16ee3e30 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -781,10 +781,6 @@ function m.lineRange(lines, row, ignoreNL) end end -function m.lineData(lines, row) - return lines[row] -end - local isSetMap = { ['setglobal'] = true, ['local'] = true, diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 548539a9..10694918 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -4,7 +4,7 @@ local guide = require 'parser.guide' local grammar = require 'parser.grammar' local TokenTypes, TokenStarts, TokenFinishs, TokenContents -local Ci, Offset, pushError, NextComment +local Ci, Offset, pushError, NextComment, Lines local parseType local Parser = re.compile([[ Main <- (Token / Sp)* @@ -1171,19 +1171,13 @@ local function buildLuaDoc(comment) } end ----当前行在注释doc前是否有代码 -local function haveCodeBeforeDocInCurLine(text, lineData, docStart) - return text:sub(lineData.start + 1, docStart - 1):find '[%w_]' -end - local function isTailComment(text, binded) - local lastDoc = binded[#binded] - local lastDocStartRow = guide.rowColOf(lastDoc.originalComment.start) - local lastDocStartLineData = guide.lineData(lastDocStartRow) - if haveCodeBeforeDocInCurLine(text, lastDocStartLineData, lastDoc.originalComment.start) then - return true - end - return false + local lastDoc = binded[#binded] + local left = lastDoc.originalComment.start + local row, col = guide.rowColOf(left) + local lineStart = Lines[row] or 0 + local hasCodeBefore = text:sub(lineStart, lineStart + col):find '[%w_]' + return hasCodeBefore end local function isNextLine(binded, doc) @@ -1386,6 +1380,7 @@ return function (state) } pushError = state.pushError + Lines = state.lines local ci = 1 NextComment = function (offset, peek) diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index 0137397d..201ca0aa 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -488,13 +488,19 @@ local function skipComment(isAction) local token = Tokens[Index + 1] if token == '--' or (token == '//' and isAction) then - local left = getPosition(Tokens[Index], 'left') + local start = Tokens[Index] + local left = getPosition(start, 'left') if token == '//' then pushCommentHeadError(left) end Index = Index + 2 local longComment = parseLongString() if longComment then + longComment.type = 'comment.long' + longComment.text = longComment[1] + longComment[1] = nil + longComment[2] = nil + State.comms[#State.comms+1] = longComment return true end while true do @@ -504,13 +510,26 @@ local function skipComment(isAction) end Index = Index + 2 end + State.comms[#State.comms+1] = { + type = 'comment.shot', + start = left, + finish = getPosition(Tokens[Index], 'right'), + text = ssub(start, Tokens[Index] or #Lua), + } return true end if token == '/*' then - local left = getPosition(Tokens[Index], 'left') + local start = Tokens[Index] + local left = getPosition(start, 'left') Index = Index + 2 local result, right = resolveLongString '*/' pushLongCommentError(left, right) + State.comms[#State.comms+1] = { + type = 'comment.long', + start = left, + finish = right, + text = result, + } return true end return false -- cgit v1.2.3 From c90f0680d1892eec6f02f8ea1970ead54ffa69f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 15 Sep 2021 16:59:24 +0800 Subject: update --- script/parser/luadoc.lua | 111 ++++++++++++++++++++++---------------------- script/parser/newparser.lua | 2 +- 2 files changed, 56 insertions(+), 57 deletions(-) diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 10694918..3a50f0b8 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -120,7 +120,6 @@ local function trim(str) end local function parseTokens(text, offset) - Ct = offset Ci = 0 Offset = offset TokenTypes = {} @@ -183,7 +182,7 @@ local function parseName(tp, parent) local class = { type = tp, start = getStart(), - finish = getFinish(), + finish = getFinish() + 1, parent = parent, [1] = nameText, } @@ -243,12 +242,12 @@ local function parseClass(parent) pushError { type = 'LUADOC_MISS_CLASS_NAME', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return nil end result.start = getStart() - result.finish = getFinish() + result.finish = getFinish() + 1 if not peekToken() then return result end @@ -256,7 +255,7 @@ local function parseClass(parent) pushError { type = 'LUADOC_MISS_EXTENDS_SYMBOL', start = result.finish + 1, - finish = getStart() - 1, + finish = getStart(), } return result end @@ -270,12 +269,12 @@ local function parseClass(parent) pushError { type = 'LUADOC_MISS_CLASS_EXTENDS_NAME', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return result end result.extends[#result.extends+1] = extend - result.finish = getFinish() + result.finish = getFinish() + 1 if not checkToken('symbol', ',', 1) then break end @@ -292,7 +291,7 @@ local function parseTypeUnitArray(parent, node) local result = { type = 'doc.type.array', start = node.start, - finish = getFinish(), + finish = getFinish() + 1, node = node, parent = parent, } @@ -326,7 +325,7 @@ local function parseTypeUnitTable(parent, node) nextSymbolOrError('>') node.parent = result; - result.finish = getFinish() + result.finish = getFinish() + 1 result.tkey = key result.tvalue = value @@ -357,7 +356,7 @@ local function parseTypeUnitFunction() local vararg = { type = 'doc.type.name', start = getStart(), - finish = getFinish(), + finish = getFinish() + 1, parent = arg, [1] = '...', } @@ -365,14 +364,14 @@ local function parseTypeUnitFunction() if not arg.start then arg.start = arg.name.start end - arg.finish = getFinish() + arg.finish = getFinish() + 1 else arg.name = parseName('doc.type.name', arg) if not arg.name then pushError { type = 'LUADOC_MISS_ARG_NAME', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } break end @@ -383,7 +382,7 @@ local function parseTypeUnitFunction() nextToken() arg.optional = true end - arg.finish = getFinish() + arg.finish = getFinish() + 1 if not nextSymbolOrError(':') then break end @@ -391,7 +390,7 @@ local function parseTypeUnitFunction() if not arg.extends then break end - arg.finish = getFinish() + arg.finish = getFinish() + 1 end typeUnit.args[#typeUnit.args+1] = arg if checkToken('symbol', ',', 1) then @@ -420,7 +419,7 @@ local function parseTypeUnitFunction() end end end - typeUnit.finish = getFinish() + typeUnit.finish = getFinish() + 1 return typeUnit end @@ -448,7 +447,7 @@ local function parseTypeUnitLiteralTable() pushError { type = 'LUADOC_MISS_FIELD_NAME', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } break end @@ -459,7 +458,7 @@ local function parseTypeUnitLiteralTable() nextToken() field.optional = true end - field.finish = getFinish() + field.finish = getFinish() + 1 if not nextSymbolOrError(':') then break end @@ -467,7 +466,7 @@ local function parseTypeUnitLiteralTable() if not field.extends then break end - field.finish = getFinish() + field.finish = getFinish() + 1 end typeUnit.fields[#typeUnit.fields+1] = field @@ -478,7 +477,7 @@ local function parseTypeUnitLiteralTable() break end end - typeUnit.finish = getFinish() + typeUnit.finish = getFinish() + 1 return typeUnit end @@ -494,7 +493,7 @@ local function parseTypeUnit(parent, content) result = { type = 'doc.type.name', start = getStart(), - finish = getFinish(), + finish = getFinish() + 1, [1] = content, } end @@ -534,14 +533,14 @@ local function parseResume(parent) pushError { type = 'LUADOC_MISS_STRING', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return nil end local _, str = nextToken() result[1] = str result.start = getStart() - result.finish = getFinish() + result.finish = getFinish() + 1 return result end @@ -594,7 +593,7 @@ function parseType(parent) local typeEnum = { type = 'doc.type.enum', start = getStart(), - finish = getFinish(), + finish = getFinish() + 1, parent = result, [1] = content, } @@ -617,7 +616,7 @@ function parseType(parent) local vararg = { type = 'doc.type.name', start = getStart(), - finish = getFinish(), + finish = getFinish() + 1, parent = result, [1] = content, } @@ -631,7 +630,7 @@ function parseType(parent) end nextToken() end - result.finish = getFinish() + result.finish = getFinish() + 1 result.firstFinish = result.finish local row = guide.rowColOf(result.finish) @@ -655,7 +654,7 @@ function parseType(parent) NextComment(i) row = row + i + 1 local finishPos = nextComm.text:find('#', 3) or #nextComm.text - parseTokens(nextComm.text:sub(3, finishPos), nextComm.start + 1) + parseTokens(nextComm.text:sub(3, finishPos), nextComm.start + 3) local resume = parseResume(result) if resume then if comments then @@ -699,7 +698,7 @@ function parseType(parent) pushError { type = 'LUADOC_MISS_TYPE_NAME', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return nil end @@ -715,7 +714,7 @@ local function parseAlias() pushError { type = 'LUADOC_MISS_ALIAS_NAME', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return nil end @@ -725,11 +724,11 @@ local function parseAlias() pushError { type = 'LUADOC_MISS_ALIAS_EXTENDS', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return nil end - result.finish = getFinish() + result.finish = getFinish() + 1 return result end @@ -742,7 +741,7 @@ local function parseParam() pushError { type = 'LUADOC_MISS_PARAM_NAME', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return nil end @@ -751,17 +750,17 @@ local function parseParam() result.optional = true end result.start = result.param.start - result.finish = getFinish() + result.finish = getFinish() + 1 result.extends = parseType(result) if not result.extends then pushError { type = 'LUADOC_MISS_PARAM_EXTENDS', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return result end - result.finish = getFinish() + result.finish = getFinish() + 1 result.firstFinish = result.extends.firstFinish return result end @@ -793,7 +792,7 @@ local function parseReturn() if #result.returns == 0 then return nil end - result.finish = getFinish() + result.finish = getFinish() + 1 return result end @@ -820,7 +819,7 @@ local function parseField() pushError { type = 'LUADOC_MISS_FIELD_NAME', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return nil end @@ -836,11 +835,11 @@ local function parseField() pushError { type = 'LUADOC_MISS_FIELD_EXTENDS', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return nil end - result.finish = getFinish() + result.finish = getFinish() + 1 return result end @@ -859,7 +858,7 @@ local function parseGeneric() pushError { type = 'LUADOC_MISS_GENERIC_NAME', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return nil end @@ -871,14 +870,14 @@ local function parseGeneric() nextToken() object.extends = parseType(object) end - object.finish = getFinish() + object.finish = getFinish() + 1 result.generics[#result.generics+1] = object if not checkToken('symbol', ',', 1) then break end nextToken() end - result.finish = getFinish() + result.finish = getFinish() + 1 return result end @@ -891,7 +890,7 @@ local function parseVararg() pushError { type = 'LUADOC_MISS_VARARG_TYPE', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return end @@ -906,7 +905,7 @@ local function parseOverload() pushError { type = 'LUADOC_MISS_FUN_AFTER_OVERLOAD', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return nil end @@ -928,7 +927,7 @@ local function parseDeprecated() return { type = 'doc.deprecated', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } end @@ -936,7 +935,7 @@ local function parseMeta() return { type = 'doc.meta', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } end @@ -951,7 +950,7 @@ local function parseVersion() pushError { type = 'LUADOC_MISS_VERSION', start = getStart(), - finish = getFinish(), + finish = getFinish() + 1, } break end @@ -974,12 +973,12 @@ local function parseVersion() pushError { type = 'LUADOC_MISS_VERSION', start = getStart(), - finish = getFinish(), + finish = getFinish() + 1, } break end version.version = tonumber(text) or text - version.finish = getFinish() + version.finish = getFinish() + 1 result.versions[#result.versions+1] = version if not checkToken('symbol', ',', 1) then break @@ -989,7 +988,7 @@ local function parseVersion() if #result.versions == 0 then return nil end - result.finish = getFinish() + result.finish = getFinish() + 1 return result end @@ -1006,7 +1005,7 @@ local function parseSee() if checkToken('symbol', '#', 1) then nextToken() result.field = parseName('doc.see.field', result) - result.finish = getFinish() + result.finish = getFinish() + 1 end return result end @@ -1020,13 +1019,13 @@ local function parseDiagnostic() pushError { type = 'LUADOC_MISS_DIAG_MODE', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return nil end result.mode = mode result.start = getStart() - result.finish = getFinish() + result.finish = getFinish() + 1 if mode ~= 'disable-next-line' and mode ~= 'disable-line' and mode ~= 'disable' @@ -1047,7 +1046,7 @@ local function parseDiagnostic() pushError { type = 'LUADOC_MISS_DIAG_NAME', start = getFinish(), - finish = getFinish(), + finish = getFinish() + 1, } return result end @@ -1059,7 +1058,7 @@ local function parseDiagnostic() end end - result.finish = getFinish() + result.finish = getFinish() + 1 return result end @@ -1073,7 +1072,7 @@ local function convertTokens() pushError { type = 'LUADOC_MISS_CATE_NAME', start = getStart(), - finish = getFinish(), + finish = getFinish() + 1, } return nil end @@ -1143,7 +1142,7 @@ local function buildLuaDoc(comment) local doc = text:sub(startPos + 1) - parseTokens(doc, comment.start + startPos - 1) + parseTokens(doc, comment.start + startPos + 1) local result = convertTokens() if result then result.range = comment.finish diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index 201ca0aa..9034480e 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -514,7 +514,7 @@ local function skipComment(isAction) type = 'comment.shot', start = left, finish = getPosition(Tokens[Index], 'right'), - text = ssub(start, Tokens[Index] or #Lua), + text = ssub(Lua, start + 2, Tokens[Index] and (Tokens[Index] - 1) or #Lua), } return true end -- cgit v1.2.3 From 281031ba5c41ebe34bd6c8634f1436fe1341fcaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 15 Sep 2021 20:01:34 +0800 Subject: update --- test/catch.lua | 108 ++++++++++++++++++++++++----------------------- test/references/init.lua | 2 +- 2 files changed, 57 insertions(+), 53 deletions(-) diff --git a/test/catch.lua b/test/catch.lua index 09b55929..849be09d 100644 --- a/test/catch.lua +++ b/test/catch.lua @@ -1,3 +1,5 @@ +local m = require 'lpeglabel' + local mt = {} local function catchedTable() @@ -18,63 +20,65 @@ function mt.__add(a, b) return t end -local function getLine(offset, lns) - for i = 0, #lns do - if offset >= lns[i] - and offset < lns[i+1] then - return i - end - end -end - -local function getPosition(offset, lns) - for i = 0, #lns do - if offset >= lns[i] - and offset < lns[i+1] then - return 10000 * i + offset - lns[i] - end - end +local function parseTokens(script, seps) + local parser = m.P { + m.Ct(m.V 'Token'^0), + Token = m.Cp() * (m.V 'Mark' + m.V 'Nl' + m.V 'Text'), + Mark = m.Cc 'ML' * m.P '<' * m.C(m.S(seps)) + + m.Cc 'MR' * m.C(m.S(seps)) * m.P '>', + Nl = m.Cc 'NL' * m.C(m.P '\r\n' + m.S '\r\n'), + Text = m.Cc 'TX' * m.C((1 - m.V 'Nl' - m.V 'Mark')^1), + } + local results = parser:match(script) + return results end ---@param script string ----@param sep string -return function (script, sep) - local pattern = ('()<(%s).-%s>()'):format(sep, sep) - local lns = {} - lns[0] = 0 - for pos in script:gmatch '()\n' do - lns[#lns+1] = pos - end - lns[#lns+1] = math.maxinteger - local codes = {} - local pos = 1 - ---@type integer[] - local list = {} - local cuted = 0 - local lastLine = 0 - for a, char, b in script:gmatch(pattern) do - codes[#codes+1] = script:sub(pos, a - 1) - codes[#codes+1] = script:sub(a + 2, b - 3) - pos = b - local line1 = getLine(a + 1, lns) - if line1 ~= lastLine then - cuted = 0 - lastLine = line1 +---@param seps string +return function (script, seps) + local tokens = parseTokens(script, seps) + local newBuf = {} + local result = {} + local marks = {} + + local lineOffset = 1 + local line = 0 + local skipOffset = 0 + for i = 1, #tokens, 3 do + local offset = tokens[i + 0] + local mode = tokens[i + 1] + local text = tokens[i + 2] + if mode == 'TX' then + newBuf[#newBuf+1] = text end - cuted = cuted + 2 - local left = getPosition(a + 1, lns) - cuted - local line2 = getLine(b - 3, lns) - if line2 ~= lastLine then - cuted = 0 - lastLine = line2 + if mode == 'NL' then + newBuf[#newBuf+1] = text + line = line + 1 + lineOffset = offset + #text - skipOffset end - local right = getPosition(b - 3, lns) - cuted - cuted = cuted + 2 - if not list[char] then - list[char] = catchedTable() + if mode == 'ML' then + marks[#marks+1] = { + char = text, + position = line * 10000 + offset - skipOffset - lineOffset, + } + skipOffset = skipOffset + 1 + #text + end + if mode == 'MR' then + for j = #marks, 1, -1 do + local mark = marks[j] + if mark.char == text then + local position = line * 10000 + offset - skipOffset - lineOffset + if not result[text] then + result[text] = catchedTable() + end + result[text][#result[text]+1] = { mark.position, position } + table.remove(marks, j) + break + end + end + skipOffset = skipOffset + 1 + #text end - list[char][#list[char]+1] = { left, right } end - codes[#codes+1] = script:sub(pos) - return table.concat(codes), list + + return table.concat(newBuf), result end diff --git a/test/references/init.lua b/test/references/init.lua index a14f0a02..78e9aabf 100644 --- a/test/references/init.lua +++ b/test/references/init.lua @@ -20,7 +20,7 @@ end function TEST(script) files.removeAll() - local newScript, catched = catch(script, '[!?~]') + local newScript, catched = catch(script, '!?~') files.setText('', newScript) local input = catched['?'] + catched['~'] -- cgit v1.2.3 From e70f82c0534c8973b3ad809a5ad72919412a832b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 15 Sep 2021 20:24:38 +0800 Subject: update --- script/parser/newparser.lua | 5 ++++- test/references/init.lua | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index 9034480e..9e8e5b94 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -1405,7 +1405,10 @@ local function parseExpList(mini) end local nextToken = peekWord() if isKeyWord(nextToken) - and nextToken ~= 'function' then + and nextToken ~= 'function' + and nextToken ~= 'true' + and nextToken ~= 'false' + and nextToken ~= 'nil' then break end end diff --git a/test/references/init.lua b/test/references/init.lua index 78e9aabf..351c80b6 100644 --- a/test/references/init.lua +++ b/test/references/init.lua @@ -24,7 +24,7 @@ function TEST(script) files.setText('', newScript) local input = catched['?'] + catched['~'] - local expect = catched['!'] + catched['?'] + catched['~'] + local expect = catched['!'] + catched['?'] local results = core('', input[1][1]) if results then local positions = {} -- cgit v1.2.3 From c3fc3c4631c8f69cb7250d8e2accd9ac0d8a0fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 15 Sep 2021 20:31:07 +0800 Subject: update --- test/definition/init.lua | 37 +++++++------------------------------ 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/test/definition/init.lua b/test/definition/init.lua index 85bcd5d5..992744d5 100644 --- a/test/definition/init.lua +++ b/test/definition/init.lua @@ -1,23 +1,10 @@ local core = require 'core.definition' local files = require 'files' local vm = require 'vm' +local catch = require 'catch' rawset(_G, 'TEST', true) -local function catch_target(script) - local list = {} - local cur = 1 - while true do - local start, finish = script:find('', cur) - if not start then - break - end - list[#list+1] = { start + 2, finish - 2 } - cur = finish + 1 - end - return list -end - local function founded(targets, results) if #targets ~= #results then return false @@ -36,15 +23,11 @@ end function TEST(script) files.removeAll() - script = script:gsub('\n', '\r\n') - local target = catch_target(script) - local start = script:find('', 1, true) - local pos = (start + finish) // 2 + 1 - local new_script = script:gsub('<[!?]', ' '):gsub('[!?]>', ' ') - files.setText('', new_script) + local newScript, catched = catch(script, '!?') - local results = core('', pos) + files.setText('', newScript) + + local results = core('', catched['?'][1][1]) if results then local positions = {} for i, result in ipairs(results) do @@ -52,15 +35,9 @@ function TEST(script) positions[i] = { result.target.start, result.target.finish } end end - if not founded(target, positions) then - core('', pos) - end - assert(founded(target, positions)) + assert(founded(catched['!'], positions)) else - if #target ~= 0 then - core('', pos) - end - assert(#target == 0) + assert(#catched['!'] == 0) end end -- cgit v1.2.3 From 03444fe030383163b35fcd8c557bccd31aeebe5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 15 Sep 2021 21:40:16 +0800 Subject: update --- script/parser/guide.lua | 2 +- script/parser/luadoc.lua | 2 +- script/parser/newparser.lua | 6 ++++++ test/definition/init.lua | 4 ++-- test/definition/table.lua | 2 +- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 16ee3e30..be1305a3 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -92,7 +92,7 @@ local childMap = { ['main'] = {'#', 'docs'}, ['repeat'] = {'#', 'filter'}, ['while'] = {'filter', '#'}, - ['in'] = {'keys', '#'}, + ['in'] = {'keys', 'exps', '#'}, ['loop'] = {'loc', 'max', 'step', '#'}, ['if'] = {'#'}, ['ifblock'] = {'filter', '#'}, diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 3a50f0b8..314e8e51 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -1238,7 +1238,7 @@ local function bindDocsBetween(sources, binded, bindSources, start, finish) for i = index, max do local src = sources[i] if src and src.start >= start then - if src.start > finish then + if src.start >= finish then break end -- 遇到table后中断,处理以下情况: diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index 9e8e5b94..0e12ab45 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -1905,6 +1905,9 @@ local function resolveName(node) loc.ref = {} end loc.ref[#loc.ref+1] = node + if loc.special then + addSpecial(loc.special, node) + end else node.type = 'getglobal' local env = getLocal(State.ENVMode, node.start) @@ -2517,6 +2520,9 @@ end local function bindValue(n, v, index, lastValue, isLocal, isSet) if isLocal then n.effect = lastRightPosition() + if v and v.special then + addSpecial(v.special, n) + end elseif isSet then n.type = GetToSetMap[n.type] or n.type if n.type == 'setlocal' then diff --git a/test/definition/init.lua b/test/definition/init.lua index 992744d5..2e87b0c2 100644 --- a/test/definition/init.lua +++ b/test/definition/init.lua @@ -35,9 +35,9 @@ function TEST(script) positions[i] = { result.target.start, result.target.finish } end end - assert(founded(catched['!'], positions)) + assert(founded(catched['!'] or {}, positions)) else - assert(#catched['!'] == 0) + assert(catched['!'] == nil) end end diff --git a/test/definition/table.lua b/test/definition/table.lua index d63cc655..61e8746d 100644 --- a/test/definition/table.lua +++ b/test/definition/table.lua @@ -54,7 +54,7 @@ t[]() TEST [[ local t t[] = 1 -t[]() +t[ ]() ]] TEST [[ -- cgit v1.2.3 From c3093ad8a0b6cded8f0ec5eab75469df3231a59e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 16 Sep 2021 20:01:22 +0800 Subject: stash --- script/core/noder.lua | 56 +++++++++++++++++++++++++++++++++++++++++++++++++-- test.lua | 2 +- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/script/core/noder.lua b/script/core/noder.lua index 3fd316eb..80d1774c 100644 --- a/script/core/noder.lua +++ b/script/core/noder.lua @@ -379,7 +379,7 @@ local getKeyMap = util.switch() end) : case 'generic.closure' : call(function (source) - return 'gc:' .. source.call.start, nil + return 'gc:' .. source.call.finish, nil end) : case 'generic.value' : call(function (source) @@ -388,7 +388,7 @@ local getKeyMap = util.switch() tail = URI_CHAR .. guide.getUri(source.closure.call) end return sformat('gv:%s|%s%s' - , source.closure.call.start + , source.closure.call.finish , getKey(source.proto) , tail ) @@ -1231,6 +1231,58 @@ compileNodeMap = util.switch() end end end) + : case 'in' + : call(function (noders, id, source) + local keys = source.keys + local exps = source.exps + if not keys or not exps then + return + end + local node = exps[1] + local param1 = exps[2] + local param2 = exps[3] + local nodeID = getID(node) + local param1ID = getID(param1) + local param2ID = getID(param2) + if node.type == 'call' then + if not param1ID then + param1ID = sformat('%s%s%s' + , nodeID + , RETURN_INDEX + , 2 + ) + if not param2ID then + param2ID = sformat('%s%s%s' + , nodeID + , RETURN_INDEX + , 3 + ) + end + end + end + local call = { + type = 'dummy', + _id = 'c:' .. source.keyword[3], + finish = source.finish, + node = { + type = 'dummy', + _id = nodeID, + }, + args = { + [1] = { + type = 'dummy', + _id = param1ID, + }, + [2] = { + type = 'dummy', + _id = param2ID, + } + } + } + for i = 1, #keys do + compileCallReturn(noders, call, getID(keys[i]), i) + end + end) : case 'main' : call(function (noders, id, source) if source.returns then diff --git a/test.lua b/test.lua index d2e2c38a..9e3e3125 100644 --- a/test.lua +++ b/test.lua @@ -10,7 +10,7 @@ ROOT = fs.path(rootPath) TEST = true DEVELOP = true --FOOTPRINT = true ---TRACE = true +TRACE = true LOGPATH = LOGPATH or (ROOT .. '/log') METAPATH = METAPATH or (ROOT .. '/meta') -- cgit v1.2.3 From 5256606b6f0a76beb5bc062eae3c0b93f7e11f59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 16 Sep 2021 20:52:19 +0800 Subject: stash --- script/core/noder.lua | 60 ++++++++++++++++++++++----------------------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/script/core/noder.lua b/script/core/noder.lua index 80d1774c..749dcba6 100644 --- a/script/core/noder.lua +++ b/script/core/noder.lua @@ -379,7 +379,7 @@ local getKeyMap = util.switch() end) : case 'generic.closure' : call(function (source) - return 'gc:' .. source.call.finish, nil + return 'gc:' .. source.call.start, nil end) : case 'generic.value' : call(function (source) @@ -388,7 +388,7 @@ local getKeyMap = util.switch() tail = URI_CHAR .. guide.getUri(source.closure.call) end return sformat('gv:%s|%s%s' - , source.closure.call.finish + , source.closure.call.start , getKey(source.proto) , tail ) @@ -1241,43 +1241,35 @@ compileNodeMap = util.switch() local node = exps[1] local param1 = exps[2] local param2 = exps[3] - local nodeID = getID(node) - local param1ID = getID(param1) - local param2ID = getID(param2) if node.type == 'call' then - if not param1ID then - param1ID = sformat('%s%s%s' - , nodeID - , RETURN_INDEX - , 2 - ) - if not param2ID then - param2ID = sformat('%s%s%s' - , nodeID - , RETURN_INDEX - , 3 - ) + if not param1 then + param1 = { + type = 'select', + sindex = 2, + start = node.start, + finish = node.finish, + vararg = node, + } + compileCallReturn(noders, node, getID(param1), 2) + if not param2 then + param2 = { + type = 'select', + sindex = 2, + start = node.start, + finish = node.finish, + vararg = node, + } + compileCallReturn(noders, node, getID(param2), 3) end end end local call = { - type = 'dummy', - _id = 'c:' .. source.keyword[3], - finish = source.finish, - node = { - type = 'dummy', - _id = nodeID, - }, - args = { - [1] = { - type = 'dummy', - _id = param1ID, - }, - [2] = { - type = 'dummy', - _id = param2ID, - } - } + type = 'call', + dummy = true, + start = source.keyword[3], + finish = source.keyword[6], + node = node, + args = { param1, param2 } } for i = 1, #keys do compileCallReturn(noders, call, getID(keys[i]), i) -- cgit v1.2.3 From e1c72093b28cd08bc4a1b4a26dffd395651ca072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 16 Sep 2021 21:44:24 +0800 Subject: fix --- script/core/noder.lua | 2 ++ script/parser/luadoc.lua | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/script/core/noder.lua b/script/core/noder.lua index 749dcba6..3aad105e 100644 --- a/script/core/noder.lua +++ b/script/core/noder.lua @@ -1245,6 +1245,7 @@ compileNodeMap = util.switch() if not param1 then param1 = { type = 'select', + dummy = true, sindex = 2, start = node.start, finish = node.finish, @@ -1254,6 +1255,7 @@ compileNodeMap = util.switch() if not param2 then param2 = { type = 'select', + dummy = true, sindex = 2, start = node.start, finish = node.finish, diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 314e8e51..040bf4bb 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -552,7 +552,6 @@ function parseType(parent) enums = {}, resumes = {}, } - result.start = getStart() while true do local tp, content = peekToken() if not tp then @@ -630,6 +629,9 @@ function parseType(parent) end nextToken() end + if not result.start then + result.start = getFinish() + 1 + end result.finish = getFinish() + 1 result.firstFinish = result.finish @@ -697,7 +699,7 @@ function parseType(parent) if #result.types == 0 and #result.enums == 0 and #result.resumes == 0 then pushError { type = 'LUADOC_MISS_TYPE_NAME', - start = getFinish(), + start = getFinish() + 1, finish = getFinish() + 1, } return nil -- cgit v1.2.3 From cf9de80f4fa38e7a74ae115948cd7bb00ba984e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 16 Sep 2021 21:57:45 +0800 Subject: fix --- script/core/noder.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/core/noder.lua b/script/core/noder.lua index 3aad105e..52ab7731 100644 --- a/script/core/noder.lua +++ b/script/core/noder.lua @@ -1256,7 +1256,7 @@ compileNodeMap = util.switch() param2 = { type = 'select', dummy = true, - sindex = 2, + sindex = 3, start = node.start, finish = node.finish, vararg = node, -- cgit v1.2.3 From f2559d2f42f8357c49b13b5df3a72bf5d7418797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 16 Sep 2021 22:02:56 +0800 Subject: fix --- script/parser/luadoc.lua | 112 +++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 040bf4bb..5cf32a54 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -160,7 +160,7 @@ local function getFinish() if Ci == 0 then return Offset end - return TokenFinishs[Ci] + Offset + return TokenFinishs[Ci] + Offset + 1 end local function try(callback) @@ -182,7 +182,7 @@ local function parseName(tp, parent) local class = { type = tp, start = getStart(), - finish = getFinish() + 1, + finish = getFinish(), parent = parent, [1] = nameText, } @@ -242,12 +242,12 @@ local function parseClass(parent) pushError { type = 'LUADOC_MISS_CLASS_NAME', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } return nil end result.start = getStart() - result.finish = getFinish() + 1 + result.finish = getFinish() if not peekToken() then return result end @@ -269,12 +269,12 @@ local function parseClass(parent) pushError { type = 'LUADOC_MISS_CLASS_EXTENDS_NAME', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } return result end result.extends[#result.extends+1] = extend - result.finish = getFinish() + 1 + result.finish = getFinish() if not checkToken('symbol', ',', 1) then break end @@ -291,7 +291,7 @@ local function parseTypeUnitArray(parent, node) local result = { type = 'doc.type.array', start = node.start, - finish = getFinish() + 1, + finish = getFinish(), node = node, parent = parent, } @@ -325,7 +325,7 @@ local function parseTypeUnitTable(parent, node) nextSymbolOrError('>') node.parent = result; - result.finish = getFinish() + 1 + result.finish = getFinish() result.tkey = key result.tvalue = value @@ -356,7 +356,7 @@ local function parseTypeUnitFunction() local vararg = { type = 'doc.type.name', start = getStart(), - finish = getFinish() + 1, + finish = getFinish(), parent = arg, [1] = '...', } @@ -364,14 +364,14 @@ local function parseTypeUnitFunction() if not arg.start then arg.start = arg.name.start end - arg.finish = getFinish() + 1 + arg.finish = getFinish() else arg.name = parseName('doc.type.name', arg) if not arg.name then pushError { type = 'LUADOC_MISS_ARG_NAME', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } break end @@ -382,7 +382,7 @@ local function parseTypeUnitFunction() nextToken() arg.optional = true end - arg.finish = getFinish() + 1 + arg.finish = getFinish() if not nextSymbolOrError(':') then break end @@ -390,7 +390,7 @@ local function parseTypeUnitFunction() if not arg.extends then break end - arg.finish = getFinish() + 1 + arg.finish = getFinish() end typeUnit.args[#typeUnit.args+1] = arg if checkToken('symbol', ',', 1) then @@ -419,7 +419,7 @@ local function parseTypeUnitFunction() end end end - typeUnit.finish = getFinish() + 1 + typeUnit.finish = getFinish() return typeUnit end @@ -447,7 +447,7 @@ local function parseTypeUnitLiteralTable() pushError { type = 'LUADOC_MISS_FIELD_NAME', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } break end @@ -458,7 +458,7 @@ local function parseTypeUnitLiteralTable() nextToken() field.optional = true end - field.finish = getFinish() + 1 + field.finish = getFinish() if not nextSymbolOrError(':') then break end @@ -466,7 +466,7 @@ local function parseTypeUnitLiteralTable() if not field.extends then break end - field.finish = getFinish() + 1 + field.finish = getFinish() end typeUnit.fields[#typeUnit.fields+1] = field @@ -477,7 +477,7 @@ local function parseTypeUnitLiteralTable() break end end - typeUnit.finish = getFinish() + 1 + typeUnit.finish = getFinish() return typeUnit end @@ -493,7 +493,7 @@ local function parseTypeUnit(parent, content) result = { type = 'doc.type.name', start = getStart(), - finish = getFinish() + 1, + finish = getFinish(), [1] = content, } end @@ -533,14 +533,14 @@ local function parseResume(parent) pushError { type = 'LUADOC_MISS_STRING', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } return nil end local _, str = nextToken() result[1] = str result.start = getStart() - result.finish = getFinish() + 1 + result.finish = getFinish() return result end @@ -592,7 +592,7 @@ function parseType(parent) local typeEnum = { type = 'doc.type.enum', start = getStart(), - finish = getFinish() + 1, + finish = getFinish(), parent = result, [1] = content, } @@ -615,7 +615,7 @@ function parseType(parent) local vararg = { type = 'doc.type.name', start = getStart(), - finish = getFinish() + 1, + finish = getFinish(), parent = result, [1] = content, } @@ -630,9 +630,9 @@ function parseType(parent) nextToken() end if not result.start then - result.start = getFinish() + 1 + result.start = getFinish() end - result.finish = getFinish() + 1 + result.finish = getFinish() result.firstFinish = result.finish local row = guide.rowColOf(result.finish) @@ -699,8 +699,8 @@ function parseType(parent) if #result.types == 0 and #result.enums == 0 and #result.resumes == 0 then pushError { type = 'LUADOC_MISS_TYPE_NAME', - start = getFinish() + 1, - finish = getFinish() + 1, + start = getFinish(), + finish = getFinish(), } return nil end @@ -716,7 +716,7 @@ local function parseAlias() pushError { type = 'LUADOC_MISS_ALIAS_NAME', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } return nil end @@ -726,11 +726,11 @@ local function parseAlias() pushError { type = 'LUADOC_MISS_ALIAS_EXTENDS', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } return nil end - result.finish = getFinish() + 1 + result.finish = getFinish() return result end @@ -743,7 +743,7 @@ local function parseParam() pushError { type = 'LUADOC_MISS_PARAM_NAME', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } return nil end @@ -752,17 +752,17 @@ local function parseParam() result.optional = true end result.start = result.param.start - result.finish = getFinish() + 1 + result.finish = getFinish() result.extends = parseType(result) if not result.extends then pushError { type = 'LUADOC_MISS_PARAM_EXTENDS', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } return result end - result.finish = getFinish() + 1 + result.finish = getFinish() result.firstFinish = result.extends.firstFinish return result end @@ -794,7 +794,7 @@ local function parseReturn() if #result.returns == 0 then return nil end - result.finish = getFinish() + 1 + result.finish = getFinish() return result end @@ -821,7 +821,7 @@ local function parseField() pushError { type = 'LUADOC_MISS_FIELD_NAME', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } return nil end @@ -837,11 +837,11 @@ local function parseField() pushError { type = 'LUADOC_MISS_FIELD_EXTENDS', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } return nil end - result.finish = getFinish() + 1 + result.finish = getFinish() return result end @@ -860,7 +860,7 @@ local function parseGeneric() pushError { type = 'LUADOC_MISS_GENERIC_NAME', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } return nil end @@ -872,14 +872,14 @@ local function parseGeneric() nextToken() object.extends = parseType(object) end - object.finish = getFinish() + 1 + object.finish = getFinish() result.generics[#result.generics+1] = object if not checkToken('symbol', ',', 1) then break end nextToken() end - result.finish = getFinish() + 1 + result.finish = getFinish() return result end @@ -892,7 +892,7 @@ local function parseVararg() pushError { type = 'LUADOC_MISS_VARARG_TYPE', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } return end @@ -907,7 +907,7 @@ local function parseOverload() pushError { type = 'LUADOC_MISS_FUN_AFTER_OVERLOAD', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } return nil end @@ -929,7 +929,7 @@ local function parseDeprecated() return { type = 'doc.deprecated', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } end @@ -937,7 +937,7 @@ local function parseMeta() return { type = 'doc.meta', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } end @@ -951,8 +951,8 @@ local function parseVersion() if not tp then pushError { type = 'LUADOC_MISS_VERSION', - start = getStart(), - finish = getFinish() + 1, + start = getFinish(), + finish = getFinish(), } break end @@ -975,12 +975,12 @@ local function parseVersion() pushError { type = 'LUADOC_MISS_VERSION', start = getStart(), - finish = getFinish() + 1, + finish = getFinish(), } break end version.version = tonumber(text) or text - version.finish = getFinish() + 1 + version.finish = getFinish() result.versions[#result.versions+1] = version if not checkToken('symbol', ',', 1) then break @@ -990,7 +990,7 @@ local function parseVersion() if #result.versions == 0 then return nil end - result.finish = getFinish() + 1 + result.finish = getFinish() return result end @@ -1007,7 +1007,7 @@ local function parseSee() if checkToken('symbol', '#', 1) then nextToken() result.field = parseName('doc.see.field', result) - result.finish = getFinish() + 1 + result.finish = getFinish() end return result end @@ -1021,13 +1021,13 @@ local function parseDiagnostic() pushError { type = 'LUADOC_MISS_DIAG_MODE', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } return nil end result.mode = mode result.start = getStart() - result.finish = getFinish() + 1 + result.finish = getFinish() if mode ~= 'disable-next-line' and mode ~= 'disable-line' and mode ~= 'disable' @@ -1048,7 +1048,7 @@ local function parseDiagnostic() pushError { type = 'LUADOC_MISS_DIAG_NAME', start = getFinish(), - finish = getFinish() + 1, + finish = getFinish(), } return result end @@ -1060,7 +1060,7 @@ local function parseDiagnostic() end end - result.finish = getFinish() + 1 + result.finish = getFinish() return result end @@ -1074,7 +1074,7 @@ local function convertTokens() pushError { type = 'LUADOC_MISS_CATE_NAME', start = getStart(), - finish = getFinish() + 1, + finish = getFinish(), } return nil end -- cgit v1.2.3 From 31e9a5235cd17c8a61d2a0a732212cd68135bed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 17 Sep 2021 15:13:50 +0800 Subject: update --- script/parser/newparser.lua | 29 +++++++++++++++++++---------- test.lua | 2 +- test/hover/init.lua | 12 ++++-------- test/type_inference/init.lua | 9 +++------ 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index 0e12ab45..9721526c 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -2340,17 +2340,26 @@ function parseExp(asAction, level) if uop then skipSpace() local child = parseExp(asAction, uopLevel) - exp = { - type = 'unary', - op = uop, - start = uop.start, - finish = child and child.finish or uop.finish, - [1] = child, - } - if child then - child.parent = exp + -- 预计算负数 + if uop.type == '-' + and child + and (child.type == 'number' or child.type == 'integer') then + child.start = uop.start + child[1] = - child[1] + exp = child else - missExp() + exp = { + type = 'unary', + op = uop, + start = uop.start, + finish = child and child.finish or uop.finish, + [1] = child, + } + if child then + child.parent = exp + else + missExp() + end end else exp = parseExpUnit() diff --git a/test.lua b/test.lua index 9e3e3125..d2e2c38a 100644 --- a/test.lua +++ b/test.lua @@ -10,7 +10,7 @@ ROOT = fs.path(rootPath) TEST = true DEVELOP = true --FOOTPRINT = true -TRACE = true +--TRACE = true LOGPATH = LOGPATH or (ROOT .. '/log') METAPATH = METAPATH or (ROOT .. '/meta') diff --git a/test/hover/init.lua b/test/hover/init.lua index 3f07ea30..c16e466d 100644 --- a/test/hover/init.lua +++ b/test/hover/init.lua @@ -1,7 +1,6 @@ local core = require 'core.hover' -local findSource = require 'core.find-source' -local getLabel = require 'core.hover.label' local files = require 'files' +local catch = require 'catch' rawset(_G, 'TEST', true) @@ -23,12 +22,9 @@ local accept = { function TEST(script) return function (expect) files.removeAll() - local start = script:find('', 1, true) - local pos = (start + finish) // 2 + 1 - local new_script = script:gsub('<[!?]', ' '):gsub('[!?]>', ' ') - files.setText('', new_script) - local hover = core.byUri('', pos) + local newScript, catched = catch(script, '?') + files.setText('', newScript) + local hover = core.byUri('', catched['?'][1][1]) assert(hover) expect = expect:gsub('^[\r\n]*(.-)[\r\n]*$', '%1'):gsub('\r\n', '\n') local label = tostring(hover):match('```lua[\r\n]*(.-)[\r\n]*```'):gsub('\r\n', '\n') diff --git a/test/type_inference/init.lua b/test/type_inference/init.lua index a20a96e9..286d47cb 100644 --- a/test/type_inference/init.lua +++ b/test/type_inference/init.lua @@ -1,8 +1,8 @@ local files = require 'files' -local vm = require 'vm' local guide = require 'parser.guide' local infer = require 'core.infer' local config = require 'config' +local catch = require 'catch' rawset(_G, 'TEST', true) @@ -24,12 +24,9 @@ end function TEST(wanted) return function (script) files.removeAll() - local start = script:find('', 1, true) - local pos = (start + finish) // 2 + 1 - local newScript = script:gsub('<[!?]', ' '):gsub('[!?]>', ' ') + local newScript, catched = catch(script, '?') files.setText('', newScript) - local source = getSource(pos) + local source = getSource(catched['?'][1][1]) assert(source) local result = infer.searchAndViewInfers(source) if wanted ~= result then -- cgit v1.2.3 From b944681c831b47c93b5b1f9a398f26ad3ca03c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 17 Sep 2021 15:17:55 +0800 Subject: update test --- test/completion/common.lua | 384 +++++++++++++++++++++---------------------- test/completion/continue.lua | 10 +- test/completion/init.lua | 15 +- 3 files changed, 205 insertions(+), 204 deletions(-) diff --git a/test/completion/common.lua b/test/completion/common.lua index 2efa63ad..66cc6fe4 100644 --- a/test/completion/common.lua +++ b/test/completion/common.lua @@ -8,7 +8,7 @@ config.set('Lua.completion.showWord', 'Enable') TEST [[ local zabcde -za$ +za ]] { { @@ -20,7 +20,7 @@ za$ TEST [[ local zabcdefg local zabcde -zabcde$ +zabcde ]] { { @@ -35,7 +35,7 @@ zabcde$ TEST [[ local zabcdefg -za$ +za local zabcde ]] { @@ -51,7 +51,7 @@ local zabcde TEST [[ local zabcde -zace$ +zace ]] { { @@ -63,7 +63,7 @@ zace$ TEST [[ ZABC = x local zabc -zac$ +zac ]] { { @@ -77,7 +77,7 @@ zac$ } TEST [[ -ass$ +ass ]] { { @@ -92,7 +92,7 @@ ass$ TEST [[ local assert = 1 -ass$ +ass ]] { { @@ -103,7 +103,7 @@ ass$ TEST [[ local assert = 1 -_G.ass$ +_G.ass ]] { { @@ -119,7 +119,7 @@ _G.ass$ TEST [[ local function ffff(a, b) end -ff$ +ff ]] { { @@ -134,7 +134,7 @@ ff$ TEST [[ local zabc = 1 -z$ +z ]] { { @@ -145,7 +145,7 @@ z$ TEST [[ local zabc = 1.0 -z$ +z ]] { { @@ -158,7 +158,7 @@ TEST [[ local t = { abc = 1, } -t.ab$ +t.ab ]] { { @@ -172,7 +172,7 @@ local t = { abc = 1, } local n = t.abc -t.ab$ +t.ab ]] { { @@ -187,7 +187,7 @@ mt.ggg = 1 function mt:get(a, b) return 1 end -mt:g$ +mt:g ]] { { @@ -205,7 +205,7 @@ mt:g$ } TEST [[ -loc$ +loc ]] { { @@ -220,7 +220,7 @@ loc$ IgnoreFunction = true TEST [[ -do$ +do ]] { { @@ -234,7 +234,7 @@ do$ } TEST [[ -while true d$ +while true d ]] { { @@ -248,18 +248,18 @@ while true d$ } TEST [[ -results$ +results ]] (nil) TEST [[ -result$ +result local results ]] (EXISTS) TEST [[ -local a$ +local a local function f(fff) fff = ast @@ -280,7 +280,7 @@ end TEST [[ t.a = {} t.b = {} -t.$ +t. ]] { { @@ -296,7 +296,7 @@ t.$ TEST [[ t.a = {} t.b = {} -t. $ +t. ]] { { @@ -314,7 +314,7 @@ TEST [[ t.a = {} function t:b() end -t:$ +t: ]] { { @@ -331,7 +331,7 @@ TEST [[ local t = { a = {}, } -t.$ +t. xxx() ]] { @@ -342,14 +342,14 @@ xxx() } TEST [[ -(''):$ +(''): ]] (EXISTS) TEST [[ local zzz -return 'aa' .. zz$ +return 'aa' .. zz ]] { { @@ -358,9 +358,9 @@ return 'aa' .. zz$ }, } -TEST 'local s = "a:$"' (nil) +TEST 'local s = "a:"' (nil) -TEST 'debug.$' +TEST 'debug.' (EXISTS) IgnoreFunction = true @@ -371,7 +371,7 @@ local xxxx = { } local t = { - x$ + x } ]] { @@ -392,7 +392,7 @@ local t = { TEST [[ print(ff2) local faa -local f$ +local f print(fff) ]] { @@ -419,7 +419,7 @@ print(fff) } TEST [[ -local function f(ff$) +local function f(ff) print(fff) end ]] @@ -431,12 +431,12 @@ end } TEST [[ -collectgarbage($) +collectgarbage() ]] (EXISTS) TEST [[ -collectgarbage('$') +collectgarbage('') ]] { { @@ -514,7 +514,7 @@ collectgarbage('$') } TEST [[ -io.read($) +io.read() ]] { { @@ -536,18 +536,18 @@ io.read($) } TEST [[ -io.open('', $) +io.open('', ) ]] (EXISTS) TEST [[ -local function f(a, $) +local function f(a, ) end ]] (nil) TEST [[ -self.results.list[#$] +self.results.list[#] ]] { { @@ -562,7 +562,7 @@ self.results.list[#$] } TEST [[ -self.results.list[#$] +self.results.list[#] local n = 1 ]] { @@ -578,7 +578,7 @@ local n = 1 } TEST [[ -self.results.list[#$] = 1 +self.results.list[#] = 1 ]] { { @@ -593,7 +593,7 @@ self.results.list[#$] = 1 } TEST [[ -self.results.list[#self.re$] +self.results.list[#self.re] ]] { { @@ -612,7 +612,7 @@ self.results.list[#self.re$] } TEST [[ -fff[#ff$] +fff[#ff] ]] { { @@ -631,7 +631,7 @@ fff[#ff$] } TEST [[ -local _ = fff.kkk[#$] +local _ = fff.kkk[#] ]] { { @@ -646,7 +646,7 @@ local _ = fff.kkk[#$] } TEST [[ -fff.kkk[#$].yy +fff.kkk[#].yy ]] { { @@ -665,7 +665,7 @@ local t = { a = 1, } -t . $ +t . ]] (EXISTS) @@ -674,7 +674,7 @@ local t = { a = 1, } -t . $ b +t . b ]] (EXISTS) @@ -683,7 +683,7 @@ local t = { a = 1, } -t $ +t ]] (nil) @@ -692,13 +692,13 @@ local t = { a = 1, } -t $. +t . ]] (nil) TEST [[ local xxxx -xxxx$ +xxxx ]] { { @@ -710,7 +710,7 @@ xxxx$ TEST [[ local xxxx local XXXX -xxxx$ +xxxx ]] { { @@ -727,7 +727,7 @@ TEST [[ local t = { xxxxx = 1, } -xx$ +xx ]] { { @@ -738,7 +738,7 @@ xx$ TEST [[ local index -tbl[inde$] +tbl[inde] ]] { { @@ -753,7 +753,7 @@ return function () a = {}, b = {}, } - t.$ + t. end ]] { @@ -769,7 +769,7 @@ end TEST [[ local ast = 1 -local t = 'as$' +local t = 'as' local ask = 1 ]] (EXISTS) @@ -777,7 +777,7 @@ local ask = 1 TEST [[ local add -function f(ad$) +function f(ad) local _ = add end ]] @@ -789,25 +789,25 @@ end } TEST [[ -function table.i$ +function table.i ]] (EXISTS) TEST [[ do - xx.$ + xx. end ]] (nil) TEST [[ -print(io.$) +print(io.) ]] (EXISTS) require 'config'.set('Lua.runtime.version', 'Lua 5.4') --TEST [[ ---local $ +--local --]] --{ -- { @@ -821,7 +821,7 @@ require 'config'.set('Lua.runtime.version', 'Lua 5.4') --} -- --TEST [[ ---local --]] --{ -- { @@ -835,7 +835,7 @@ local mt = {} mt.__index = mt local t = setmetatable({}, mt) -t.$ +t. ]] { { @@ -848,7 +848,7 @@ TEST [[ local elseaaa ELSE = 1 if a then -else$ +else ]] { { @@ -877,7 +877,7 @@ Cared['insertText'] = true IgnoreFunction = false TEST [[ local xpcal -xpcal$ +xpcal ]] { { @@ -900,7 +900,7 @@ TEST [[ function mt:f(a, b, c) end -mt:f$ +mt:f ]] { { @@ -911,12 +911,12 @@ mt:f$ { label = 'f(a, b, c)', kind = define.CompletionItemKind.Snippet, - insertText = 'f(${1:a: any}, ${2:b: any}, ${3:c: any})', + insertText = 'f({1:a: any}, {2:b: any}, {3:c: any})', }, } TEST [[ -function$ +function ]] { { @@ -927,14 +927,14 @@ function$ label = 'function ()', kind = define.CompletionItemKind.Snippet, insertText = "\z -function $1($2)\ -\t$0\ +function 1(2)\ +\t0\ end", }, } TEST [[ -local t = function$ +local t = function ]] { { @@ -945,8 +945,8 @@ local t = function$ label = 'function ()', kind = define.CompletionItemKind.Snippet, insertText = "\z -function ($1)\ -\t$0\ +function (1)\ +\t0\ end", }, } @@ -956,7 +956,7 @@ IgnoreFunction = true TEST [[ local function f() if a then - else$ + else end ]] { @@ -979,7 +979,7 @@ local t = { ['a.b.c'] = {} } -t.$ +t. ]] { { @@ -1005,7 +1005,7 @@ local t = { ['a.b.c'] = {} } -t. $ +t. ]] { { @@ -1031,7 +1031,7 @@ local t = { ['a.b.c'] = {} } -t['$'] +t[''] ]] { { @@ -1048,7 +1048,7 @@ t['$'] TEST [[ _ENV['z.b.c'] = {} -z$ +z ]] { { @@ -1063,18 +1063,18 @@ z$ } TEST [[ -io.close(1, $) +io.close(1, ) ]] (nil) TEST [[ -io$ +io ]] (EXISTS) IgnoreFunction = false TEST [[ -loadstring$ +loadstring ]] { { @@ -1090,7 +1090,7 @@ loadstring$ } --TEST [[ ---bit32$ +--bit32 --]] --{ -- { @@ -1103,7 +1103,7 @@ loadstring$ TEST [[ function loadstring() end -loadstring$ +loadstring ]] { { @@ -1127,7 +1127,7 @@ loadstring$ } TEST [[ -debug.setcsta$ +debug.setcsta ]] { { @@ -1143,12 +1143,12 @@ debug.setcsta$ } TEST [[ ----@$ +---@ ]] (EXISTS) TEST [[ ----@cl$ +---@cl ]] { { @@ -1159,7 +1159,7 @@ TEST [[ TEST [[ ---@class ZABC ----@class ZBBC : Z$ +---@class ZBBC : Z ]] { { @@ -1170,14 +1170,14 @@ TEST [[ TEST [[ ---@class ZABC ----@class ZBBC : $ +---@class ZBBC : ]] (EXISTS) TEST [[ ---@class zabc local abcd ----@type za$ +---@type za ]] { { @@ -1189,14 +1189,14 @@ local abcd TEST [[ ---@class abc local abcd ----@type $ +---@type ]] (EXISTS) TEST [[ ---@class zabc local abcd ----@type zxxx|z$ +---@type zxxx|z ]] { { @@ -1207,7 +1207,7 @@ local abcd TEST [[ ---@alias zabc zabb ----@type za$ +---@type za ]] { { @@ -1218,7 +1218,7 @@ TEST [[ TEST [[ ---@class ZClass ----@param x ZC$ +---@param x ZC ]] { { @@ -1229,7 +1229,7 @@ TEST [[ Cared['insertText'] = true TEST [[ ----@param $ +---@param function f(a, b, c) end ]] @@ -1238,9 +1238,9 @@ end label = 'a, b, c', kind = define.CompletionItemKind.Snippet, insertText = [[ -a ${1:any} ----@param b ${2:any} ----@param c ${3:any}]] +a {1:any} +---@param b {2:any} +---@param c {3:any}]] }, { label = 'a', @@ -1257,7 +1257,7 @@ a ${1:any} } TEST [[ ----@param $ +---@param function f(a, b, c) end function f2(a) end @@ -1267,9 +1267,9 @@ function f2(a) end label = 'a, b, c', kind = define.CompletionItemKind.Snippet, insertText = [[ -a ${1:any} ----@param b ${2:any} ----@param c ${3:any}]] +a {1:any} +---@param b {2:any} +---@param c {3:any}]] }, { label = 'a', @@ -1286,7 +1286,7 @@ a ${1:any} } TEST [[ ----@param aa$ +---@param aa function f(aaa, bbb, ccc) end ]] @@ -1299,7 +1299,7 @@ end TEST [[ local function f() - ---@param $ + ---@param function f(a, b, c) end end @@ -1309,9 +1309,9 @@ end label = 'a, b, c', kind = define.CompletionItemKind.Snippet, insertText = [[ -a ${1:any} ----@param b ${2:any} ----@param c ${3:any}]] +a {1:any} +---@param b {2:any} +---@param c {3:any}]] }, { label = 'a', @@ -1328,7 +1328,7 @@ a ${1:any} } TEST [[ ----@param $ +---@param function mt:f(a, b, c, ...) end ]] @@ -1337,9 +1337,9 @@ end label = 'a, b, c', kind = define.CompletionItemKind.Snippet, insertText = [[ -a ${1:any} ----@param b ${2:any} ----@param c ${3:any}]], +a {1:any} +---@param b {2:any} +---@param c {3:any}]], }, { label = 'self', @@ -1360,7 +1360,7 @@ a ${1:any} } TEST [[ ----@param aaa $ +---@param aaa function f(aaa, bbb, ccc) end ]] @@ -1369,7 +1369,7 @@ end TEST [[ ---@param xyz Class ---@param xxx Class -function f(x$) +function f(x) ]] { { @@ -1389,7 +1389,7 @@ function f(x$) TEST [[ ---@param xyz Class ---@param xxx Class -function f($ +function f( ]] { { @@ -1409,7 +1409,7 @@ function f($ TEST [[ ---@param xyz Class ---@param xxx Class -function f($) +function f() ]] { { @@ -1428,7 +1428,7 @@ function f($) TEST [[ local function f() - ---@t$ + ---@t end ]] { @@ -1443,7 +1443,7 @@ TEST [[ ---@field name string ---@field id integer local mt = {} -mt.$ +mt. ]] { { @@ -1461,7 +1461,7 @@ TEST [[ function f(y, x) end -f(1, $) +f(1, ) ]] { { @@ -1483,7 +1483,7 @@ TEST [[ function f(y, x) end -f(1,$) +f(1,) ]] { { @@ -1505,7 +1505,7 @@ TEST [[ function f(x) end -f($) +f() ]] { { @@ -1528,7 +1528,7 @@ TEST [[ function f(x) end -f($) +f() ]] { { @@ -1550,7 +1550,7 @@ TEST [[ function f(x) end -f('$') +f('') ]] { { @@ -1586,7 +1586,7 @@ TEST [[ local function f(x) end -f($) +f() ]] { { @@ -1619,7 +1619,7 @@ end ---comment 3 ---| '3' -f($) +f() ]] { { @@ -1638,7 +1638,7 @@ function f(x) end f(function () - $ + end) ]] (nil) @@ -1652,7 +1652,7 @@ TEST [[ ---@return string local function zzzzz(list, sep, i, j) end -zzz$ +zzz ]] { { @@ -1672,7 +1672,7 @@ Cared['description'] = true TEST [[ --- abc zzz = 1 -zz$ +zz ]] { { @@ -1695,7 +1695,7 @@ TEST [[ ---| "'选项2'" # 注释2 function f(x) end -f($) +f() ]] { { @@ -1711,7 +1711,7 @@ f($) } TEST [[ -utf8.charpatter$ +utf8.charpatter ]] { { @@ -1726,7 +1726,7 @@ TEST [[ ---@type "'a'"|"'b'"|"'c'" local x -print(x == $) +print(x == ) ]] { { @@ -1747,7 +1747,7 @@ TEST [[ ---@type "'a'"|"'b'"|"'c'" local x -x = $ +x = ]] { { @@ -1768,7 +1768,7 @@ TEST [[ ---@type "'a'"|"'b'"|"'c'" local x -print(x == '$') +print(x == '') ]] { { @@ -1792,7 +1792,7 @@ TEST [[ ---@type "'a'"|"'b'"|"'c'" local x -x = '$' +x = '' ]] { { @@ -1815,24 +1815,24 @@ x = '$' TEST [[ local t = type() -print(t == $) +print(t == ) ]] (EXISTS) TEST [[ -if type(arg) == '$' +if type(arg) == '' ]] (EXISTS) TEST [[ -if type(arg) == $ +if type(arg) == ]] (EXISTS) TEST [[ ---@type string local s -s.$ +s. ]] (EXISTS) @@ -1841,7 +1841,7 @@ TEST [[ local t local vvv = assert(t) -vvv$ +vvv ]] { { @@ -1857,21 +1857,21 @@ TEST [[ ---@param callback fun(x: number, y: number):string local function f(callback) end -f($) +f() ]] { { label = 'fun(x: number, y: number):string', kind = define.CompletionItemKind.Function, insertText = "\z -function (${1:x}, ${2:y})\ -\t$0\ +function ({1:x}, {2:y})\ +\t0\ end", }, } TEST [[ ----$ +--- local function f(a, b, c) return a + 1, b .. '', c[1] end @@ -1881,20 +1881,20 @@ end label = '@param;@return', kind = define.CompletionItemKind.Snippet, insertText = "\z -${1:comment}\ ----@param a ${2:number}\ ----@param b ${3:string}\ ----@param c ${4:table}\ ----@return ${5:number}\ ----@return ${6:string}\ ----@return ${7:any}", +{1:comment}\ +---@param a {2:number}\ +---@param b {3:string}\ +---@param c {4:table}\ +---@return {5:number}\ +---@return {6:string}\ +---@return {7:any}", }, } Cared['insertText'] = nil TEST [[ ---$ +-- ]] { { @@ -1918,7 +1918,7 @@ TEST [[ local function f(x) end f({ - $ + }) ]] { @@ -1942,7 +1942,7 @@ local function f(x) end f({ aaa = 1, - $ + }) ]] { @@ -1960,7 +1960,7 @@ TEST [[ ---@param x cc local function f(x) end -f({aaa = 1,$}) +f({aaa = 1,}) ]] { { @@ -1977,7 +1977,7 @@ TEST [[ ---@param x cc local function f(x) end -f({aaa $}) +f({aaa }) ]] (nil) @@ -1988,7 +1988,7 @@ TEST [[ ---@param x cc local function f(x) end -f({if$}) +f({if}) ]] { include = true, @@ -2008,7 +2008,7 @@ local function f(x) end f({ { - $ + } }) ]] @@ -2020,7 +2020,7 @@ local function f() end local s = f() -s.$ +s. ]] (EXISTS) @@ -2032,7 +2032,7 @@ TEST [[ ---@type cc local t -print(t.aa$) +print(t.aa) ]] { { @@ -2050,7 +2050,7 @@ TEST [[ ---@type table local x -x.a = $ +x.a = ]] { { @@ -2071,7 +2071,7 @@ TEST [[ ---@type table local x -x['a'] = $ +x['a'] = ]] { { @@ -2091,7 +2091,7 @@ x['a'] = $ TEST [[ ---@type table local x = { - a = $ + a = } ]] { @@ -2112,7 +2112,7 @@ local x = { TEST [[ ---@type table local x = { - ['a'] = $ + ['a'] = } ]] { @@ -2138,7 +2138,7 @@ local m function m.f() end -m.f$ +m.f ]]{ { label = "f()", @@ -2154,7 +2154,7 @@ m.f$ Cared['insertText'] = nil TEST [[ -if true then$ +if true then ]] { { @@ -2168,7 +2168,7 @@ if true then$ } TEST [[ -if true then$ +if true then end ]] { @@ -2179,7 +2179,7 @@ end } TEST [[ -if true then$ +if true then else ]] { @@ -2190,7 +2190,7 @@ else } TEST [[ -if true then$ +if true then elseif ]] { @@ -2202,7 +2202,7 @@ elseif TEST [[ do - if true then$ + if true then end ]] { @@ -2226,7 +2226,7 @@ local function f(x, ...) end f(1, { - $ + }) ]] { @@ -2250,7 +2250,7 @@ local function f(x, ...) end f(1, {}, {}, { - $ + }) ]] { @@ -2271,7 +2271,7 @@ TEST [[ ---@type C local t = { - $ + } ]] @@ -2293,7 +2293,7 @@ TEST [[ ---@type C local t = { - x$ + x } ]] @@ -2306,19 +2306,19 @@ local t = { } TEST [[ -if $ then +if then ]] (nil) TEST [[ -elseif $ then +elseif then ]] (nil) TEST [[ ---@type iolib local t = { - $ + ]] (EXISTS) @@ -2329,7 +2329,7 @@ TEST [[ ---@param t A function api(t) end -api({$}) +api({}) ]] (EXISTS) @@ -2340,14 +2340,14 @@ TEST [[ ---@param t A function m:api(t) end -m:api({$}) +m:api({}) ]] (EXISTS) TEST [[ ---@class AAA.BBB ----@type AAA.$ +---@type AAA. ]] { { @@ -2365,7 +2365,7 @@ Cared['insertText'] = true TEST [[ ---@overload fun(a: any, b: any) local function zzzz(a) end -zzzz$ +zzzz ]] { { @@ -2376,7 +2376,7 @@ zzzz$ { label = 'zzzz(a)', kind = define.CompletionItemKind.Snippet, - insertText = 'zzzz(${1:a: any})', + insertText = 'zzzz({1:a: any})', }, { label = 'zzzz(a, b)', @@ -2386,7 +2386,7 @@ zzzz$ { label = 'zzzz(a, b)', kind = define.CompletionItemKind.Snippet, - insertText = 'zzzz(${1:a: any}, ${2:b: any})', + insertText = 'zzzz({1:a: any}, {2:b: any})', }, } Cared['insertText'] = false @@ -2406,13 +2406,13 @@ local tarray local b = tdirect -- type . here, shows "world" -- Inferred by index -local c = tarray[1].$ -- type . here, no auto completion +local c = tarray[1]. -- type . here, no auto completion ]] (EXISTS) TEST [[ local function f() - if type() == '$' then + if type() == '' then end end ]] @@ -2425,7 +2425,7 @@ GGG = 1 GGG = function () end -GGG$ +GGG ]] { { @@ -2446,7 +2446,7 @@ local t = {} t.GGG = function () end -t.GGG$ +t.GGG ]] { { @@ -2463,14 +2463,14 @@ TEST [[ ---@param f fun(a: any, b: any):boolean local function f(f) end -f(fun$) +f(fun) ]] { { label = 'fun(a: any, b: any):boolean', kind = define.CompletionItemKind.Function, textEdit = { - newText = 'function (${1:a}, ${2:b})\n\t$0\nend', + newText = 'function ({1:a}, {2:b})\n\t0\nend', start = 68, finish = 70, } @@ -2489,7 +2489,7 @@ TEST [[ ---@type {[1]: number} local t -t.$ +t. ]] { { @@ -2514,7 +2514,7 @@ TEST [[ ---@type {[1]: number} local t -t.$ +t. ]] { { @@ -2543,7 +2543,7 @@ TEST [[ local function f(x) end -local r = f('$') +local r = f('') ]] { { @@ -2570,7 +2570,7 @@ TEST [[ ---@type fun(x: "'aaa'"|"'bbb'") local f -f('$') +f('') ]] { { @@ -2598,7 +2598,7 @@ TEST [[ ---@field on fun() local c -c:$ +c: ]] { { @@ -2612,7 +2612,7 @@ TEST [[ ---@field on fun(x: "'aaa'"|"'bbb'") local c -c:on($) +c:on() ]] (EXISTS) @@ -2621,7 +2621,7 @@ TEST [[ ---@field on fun(x: "'aaa'"|"'bbb'") local c -c:on('$') +c:on('') ]] (EXISTS) @@ -2632,7 +2632,7 @@ function m.f() end m.f() -m.$ +m. ]] { [1] = EXISTS, @@ -2647,7 +2647,7 @@ function class1:method1() end ---@class class2 : class1 class2 = {} -class2:$ +class2: ]] { diff --git a/test/completion/continue.lua b/test/completion/continue.lua index 4159ea7a..63f970e9 100644 --- a/test/completion/continue.lua +++ b/test/completion/continue.lua @@ -9,7 +9,7 @@ ContinueTyping = true TEST [[ local zabcde -za$ +za ]] { { @@ -20,7 +20,7 @@ za$ TEST [[ -- zabcde -io.z$ +io.z ]] { { @@ -32,7 +32,7 @@ io.z$ TEST [[ -- provider -pro$ +pro ]] { { @@ -45,7 +45,7 @@ TEST [[ ---@param n '"abcdefg"' local function f(n) end -f 'abc$' +f 'abc' ]] { { @@ -59,7 +59,7 @@ TEST [[ ---@type '"abcdefg"' local t -if t == 'abc$' +if t == 'abc' ]] { { diff --git a/test/completion/init.lua b/test/completion/init.lua index 24c8932f..051c288c 100644 --- a/test/completion/init.lua +++ b/test/completion/init.lua @@ -1,5 +1,6 @@ local core = require 'core.completion' local files = require 'files' +local catch = require 'catch' EXISTS = {'EXISTS'} @@ -64,17 +65,17 @@ ContinueTyping = false function TEST(script) return function (expect) files.removeAll() - local pos = script:find('$', 1, true) - 1 - local new_script = script:gsub('%$', '') + local newScript, catched = catch(script, '?') - files.setText('', new_script) + files.setText('', newScript) core.clearCache() + local inputPos = catched['?'][1][1] if ContinueTyping then - local triggerCharacter = script:sub(pos - 1, pos - 1) - core.completion('', pos - 1, triggerCharacter) + local triggerCharacter = script:sub(inputPos - 1, inputPos - 1) + core.completion('', inputPos, triggerCharacter) end - local triggerCharacter = script:sub(pos, pos) - local result = core.completion('', pos, triggerCharacter) + local triggerCharacter = script:sub(inputPos, inputPos) + local result = core.completion('', inputPos, triggerCharacter) if not expect then assert(result == nil) return -- cgit v1.2.3 From bb5709481e7378901e8687beb7caac7521d48122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 17 Sep 2021 16:45:17 +0800 Subject: cleanup --- script/core/completion.lua | 380 +++++++++++++++++++++++---------------------- script/parser/guide.lua | 9 ++ 2 files changed, 200 insertions(+), 189 deletions(-) diff --git a/script/core/completion.lua b/script/core/completion.lua index 1b64bef1..83c26da5 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -53,17 +53,17 @@ local function trim(str) return str:match '^%s*(%S+)%s*$' end -local function findNearestSource(ast, offset) +local function findNearestSource(state, position) local source - guide.eachSourceContain(ast.ast, offset, function (src) + guide.eachSourceContain(state.ast, position, function (src) source = src end) return source end -local function findNearestTableField(ast, offset) +local function findNearestTableField(state, position) local source - guide.eachSourceContain(ast.ast, offset, function (src) + guide.eachSourceContain(state.ast, position, function (src) if src.type == 'table' or src.type == 'tablefield' or src.type == 'tableindex' @@ -74,8 +74,8 @@ local function findNearestTableField(ast, offset) return source end -local function findParent(ast, text, offset) - for i = offset, 1, -1 do +local function findParent(state, text, position) + for i = position, 1, -1 do local char = text:sub(i, i) if lookBackward.isSpace(char) then goto CONTINUE @@ -96,7 +96,7 @@ local function findParent(ast, text, offset) if not anyPos then return nil, nil end - local parent = guide.eachSourceContain(ast.ast, anyPos, function (source) + local parent = guide.eachSourceContain(state.ast, anyPos, function (source) if source.finish == anyPos then return source end @@ -109,9 +109,9 @@ local function findParent(ast, text, offset) return nil, nil end -local function findParentInStringIndex(ast, text, offset) +local function findParentInStringIndex(state, text, position) local near, nearStart - guide.eachSourceContain(ast.ast, offset, function (source) + guide.eachSourceContain(state.ast, position, function (source) local start = guide.getStartFinish(source) if not start then return @@ -222,8 +222,8 @@ local function buildFunction(results, source, value, oop, data) end end -local function buildInsertRequire(ast, targetUri, stemName) - local uri = guide.getUri(ast.ast) +local function buildInsertRequire(state, targetUri, stemName) + local uri = guide.getUri(state.ast) local lines = files.getLines(uri) local text = files.getText(uri) local start = 1 @@ -252,8 +252,8 @@ local function buildInsertRequire(ast, targetUri, stemName) } end -local function isSameSource(ast, source, pos) - if guide.getUri(source) ~= guide.getUri(ast.ast) then +local function isSameSource(state, source, pos) + if guide.getUri(source) ~= guide.getUri(state.ast) then return false end if source.type == 'field' @@ -283,10 +283,10 @@ local function getParams(func, oop) return '(' .. table.concat(args, ', ') .. ')' end -local function checkLocal(ast, word, offset, results) - local locals = guide.getVisibleLocals(ast.ast, offset) +local function checkLocal(state, word, position, results) + local locals = guide.getVisibleLocals(state.ast, position) for name, source in util.sortPairs(locals) do - if isSameSource(ast, source, offset) then + if isSameSource(state, source, position) then goto CONTINUE end if not matchKey(word, name) then @@ -330,13 +330,13 @@ local function checkLocal(ast, word, offset, results) end end -local function checkModule(ast, word, offset, results) +local function checkModule(state, word, position, results) if not config.get 'Lua.completion.autoRequire' then return end - local locals = guide.getVisibleLocals(ast.ast, offset) + local locals = guide.getVisibleLocals(state.ast, position) for uri in files.eachFile() do - if uri == guide.getUri(ast.ast) then + if uri == guide.getUri(state.ast) then goto CONTINUE end local path = furi.decode(uri) @@ -347,11 +347,11 @@ local function checkModule(ast, word, offset, results) and not config.get 'Lua.diagnostics.globals'[stemName] and stemName:match '^[%a_][%w_]*$' and matchKey(word, stemName) then - local targetAst = files.getState(uri) - if not targetAst then + local targetState = files.getState(uri) + if not targetState then goto CONTINUE end - local targetReturns = targetAst.ast.returns + local targetReturns = targetState.ast.returns if not targetReturns then goto CONTINUE end @@ -377,7 +377,7 @@ local function checkModule(ast, word, offset, results) command = 'lua.autoRequire:' .. sp:get_id(), arguments = { { - uri = guide.getUri(ast.ast), + uri = guide.getUri(state.ast), target = uri, name = stemName, }, @@ -393,7 +393,7 @@ local function checkModule(ast, word, offset, results) return { detail = buildDetail(targetSource), description = md, - --additionalTextEdits = buildInsertRequire(ast, originUri, stemName), + --additionalTextEdits = buildInsertRequire(state, originUri, stemName), } end) } @@ -402,7 +402,7 @@ local function checkModule(ast, word, offset, results) end end -local function checkFieldFromFieldToIndex(name, src, parent, word, start, offset) +local function checkFieldFromFieldToIndex(name, src, parent, word, start, position) if name:match '^[%a_][%w_]*$' then return nil end @@ -411,9 +411,9 @@ local function checkFieldFromFieldToIndex(name, src, parent, word, start, offset local text = files.getText(uri) local wordStart if word == '' then - wordStart = text:match('()%S', start + 1) or (offset + 1) + wordStart = text:match('()%S', start + 1) or (position + 1) else - wordStart = offset - #word + 1 + wordStart = position - #word + 1 end local newText if vm.getKeyType(src) == 'string' then @@ -423,7 +423,7 @@ local function checkFieldFromFieldToIndex(name, src, parent, word, start, offset end textEdit = { start = wordStart, - finish = offset, + finish = position, newText = newText, } local nxt = parent.next @@ -457,7 +457,7 @@ local function checkFieldFromFieldToIndex(name, src, parent, word, start, offset return textEdit, additionalTextEdits end -local function checkFieldThen(name, src, word, start, offset, parent, oop, results) +local function checkFieldThen(name, src, word, start, position, parent, oop, results) local value = searcher.getObjectValue(src) or src local kind = define.CompletionItemKind.Field if value.type == 'function' @@ -494,11 +494,11 @@ local function checkFieldThen(name, src, word, start, offset, parent, oop, resul local str = parent.next.index textEdit = { start = str.start + #str[2], - finish = offset, + finish = position, newText = name, } else - textEdit, additionalTextEdits = checkFieldFromFieldToIndex(name, src, parent, word, start, offset) + textEdit, additionalTextEdits = checkFieldFromFieldToIndex(name, src, parent, word, start, position) end results[#results+1] = { label = name, @@ -515,7 +515,7 @@ local function checkFieldThen(name, src, word, start, offset, parent, oop, resul } end -local function checkFieldOfRefs(refs, ast, word, start, offset, parent, oop, results, locals, isGlobal) +local function checkFieldOfRefs(refs, state, word, start, position, parent, oop, results, locals, isGlobal) local fields = {} local funcs = {} local count = 0 @@ -524,7 +524,7 @@ local function checkFieldOfRefs(refs, ast, word, start, offset, parent, oop, res if not name then goto CONTINUE end - if isSameSource(ast, src, start) then + if isSameSource(state, src, start) then goto CONTINUE end if isGlobal and locals and locals[name] then @@ -573,29 +573,29 @@ local function checkFieldOfRefs(refs, ast, word, start, offset, parent, oop, res end for name, src in util.sortPairs(fields) do if src then - checkFieldThen(name, src, word, start, offset, parent, oop, results) + checkFieldThen(name, src, word, start, position, parent, oop, results) end end end -local function checkGlobal(ast, word, start, offset, parent, oop, results) - local locals = guide.getVisibleLocals(ast.ast, offset) +local function checkGlobal(state, word, start, position, parent, oop, results) + local locals = guide.getVisibleLocals(state.ast, position) local globals = vm.getGlobalSets '*' - checkFieldOfRefs(globals, ast, word, start, offset, parent, oop, results, locals, 'global') + checkFieldOfRefs(globals, state, word, start, position, parent, oop, results, locals, 'global') end -local function checkField(ast, word, start, offset, parent, oop, results) +local function checkField(state, word, start, position, parent, oop, results) if parent.tag == '_ENV' or parent.special == '_G' then local globals = vm.getGlobalSets '*' - checkFieldOfRefs(globals, ast, word, start, offset, parent, oop, results) + checkFieldOfRefs(globals, state, word, start, position, parent, oop, results) else local refs = vm.getRefs(parent, '*') - checkFieldOfRefs(refs, ast, word, start, offset, parent, oop, results) + checkFieldOfRefs(refs, state, word, start, position, parent, oop, results) end end -local function checkTableField(ast, word, start, results) - local source = guide.eachSourceContain(ast.ast, start, function (source) +local function checkTableField(state, word, start, results) + local source = guide.eachSourceContain(state.ast, start, function (source) if source.start == start and source.parent and source.parent.type == 'table' then @@ -606,7 +606,7 @@ local function checkTableField(ast, word, start, results) return end local used = {} - guide.eachSourceType(ast.ast, 'tablefield', function (src) + guide.eachSourceType(state.ast, 'tablefield', function (src) if not src.field then return end @@ -623,7 +623,7 @@ local function checkTableField(ast, word, start, results) end) end -local function checkCommon(myUri, word, text, offset, results) +local function checkCommon(myUri, word, text, position, results) local showWord = config.get 'Lua.completion.showWord' if showWord == 'Disable' then return @@ -695,7 +695,7 @@ local function checkCommon(myUri, word, text, offset, results) if #results >= 100 then break end - if #str >= 3 and not used[str] and pos - 1 ~= offset then + if #str >= 3 and not used[str] and pos - 1 ~= position then used[str] = true if matchKey(word, str) then results[#results+1] = { @@ -710,26 +710,26 @@ local function checkCommon(myUri, word, text, offset, results) end end -local function isInString(ast, offset) - return guide.eachSourceContain(ast.ast, offset, function (source) +local function isInString(state, position) + return guide.eachSourceContain(state.ast, position, function (source) if source.type == 'string' then return true end end) end -local function checkKeyWord(ast, text, start, offset, word, hasSpace, afterLocal, results) +local function checkKeyWord(state, text, start, position, word, hasSpace, afterLocal, results) local snipType = config.get 'Lua.completion.keywordSnippet' - local symbol = lookBackward.findSymbol(text, start - 1) + local symbol = lookBackward.findSymbol(text, guide.offsetOf(state, start - 1)) local isExp = symbol == '(' or symbol == ',' or symbol == '=' local info = { hasSpace = hasSpace, isExp = isExp, text = text, start = start, - uri = guide.getUri(ast.ast), - offset = offset, - ast = ast, + uri = guide.getUri(state.ast), + position = position, + state = state, } for _, data in ipairs(keyWordMap) do local key = data[1] @@ -789,9 +789,9 @@ local function checkKeyWord(ast, text, start, offset, word, hasSpace, afterLocal end end -local function checkProvideLocal(ast, word, start, results) +local function checkProvideLocal(state, word, start, results) local block - guide.eachSourceContain(ast.ast, start, function (source) + guide.eachSourceContain(state.ast, start, function (source) if source.type == 'function' or source.type == 'main' then block = source @@ -825,8 +825,8 @@ local function checkProvideLocal(ast, word, start, results) end) end -local function checkFunctionArgByDocParam(ast, word, start, results) - local func = guide.eachSourceContain(ast.ast, start, function (source) +local function checkFunctionArgByDocParam(state, word, start, results) + local func = guide.eachSourceContain(state.ast, start, function (source) if source.type == 'function' then return source end @@ -876,10 +876,10 @@ local function isAfterLocal(text, start) return word == 'local' end -local function checkUri(ast, text, offset, results) +local function checkUri(state, text, position, results) local collect = {} - local myUri = guide.getUri(ast.ast) - guide.eachSourceContain(ast.ast, offset, function (source) + local myUri = guide.getUri(state.ast) + guide.eachSourceContain(state.ast, position, function (source) if source.type ~= 'string' then return end @@ -910,7 +910,7 @@ local function checkUri(ast, text, offset, results) collect[info.expect] = { textEdit = { start = source.start + #source[2], - finish = offset, + finish = position, newText = info.expect, } } @@ -996,8 +996,8 @@ local function checkUri(ast, text, offset, results) end end -local function checkLenPlusOne(ast, text, offset, results) - guide.eachSourceContain(ast.ast, offset, function (source) +local function checkLenPlusOne(state, text, position, results) + guide.eachSourceContain(state.ast, position, function (source) if source.type == 'getindex' or source.type == 'setindex' then local _, pos = text:find('%s*%[%s*%#', source.node.finish) @@ -1005,7 +1005,7 @@ local function checkLenPlusOne(ast, text, offset, results) return end local nodeText = text:sub(source.node.start, source.node.finish) - local writingText = trim(text:sub(pos + 1, offset - 1)) or '' + local writingText = trim(text:sub(pos + 1, position - 1)) or '' if not matchKey(writingText, nodeText) then return end @@ -1084,7 +1084,7 @@ local function mergeEnums(a, b, source) end end -local function checkTypingEnum(ast, text, offset, defs, str, results) +local function checkTypingEnum(state, text, position, defs, str, results) local enums = {} for _, def in ipairs(defs) do if def.type == 'doc.type.enum' @@ -1106,21 +1106,21 @@ local function checkTypingEnum(ast, text, offset, defs, str, results) end end -local function checkEqualEnumLeft(ast, text, offset, source, results) +local function checkEqualEnumLeft(state, text, position, source, results) if not source then return end - local str = guide.eachSourceContain(ast.ast, offset, function (src) + local str = guide.eachSourceContain(state.ast, position, function (src) if src.type == 'string' then return src end end) local defs = vm.getDefs(source) - checkTypingEnum(ast, text, offset, defs, str, results) + checkTypingEnum(state, text, position, defs, str, results) end -local function checkEqualEnum(ast, text, offset, results) - local start = lookBackward.findTargetSymbol(text, offset, '=') +local function checkEqualEnum(state, text, position, results) + local start = lookBackward.findTargetSymbol(text, guide.offsetOf(state, position), '=') if not start then return end @@ -1131,7 +1131,7 @@ local function checkEqualEnum(ast, text, offset, results) eqOrNeq = true end start = lookBackward.skipSpace(text, start - 1) - local source = findNearestSource(ast, start) + local source = findNearestSource(state, start) if not source then return end @@ -1141,11 +1141,11 @@ local function checkEqualEnum(ast, text, offset, results) if source.type == 'call' and not eqOrNeq then return end - checkEqualEnumLeft(ast, text, offset, source, results) + checkEqualEnumLeft(state, text, position, source, results) end -local function checkEqualEnumInString(ast, text, offset, results) - local source = findNearestSource(ast, offset) +local function checkEqualEnumInString(state, text, position, results) + local source = findNearestSource(state, position) local parent = source.parent if parent.type == 'binary' then if source ~= parent[2] then @@ -1157,118 +1157,118 @@ local function checkEqualEnumInString(ast, text, offset, results) if parent.op.type ~= '==' and parent.op.type ~= '~=' then return end - checkEqualEnumLeft(ast, text, offset, parent[1], results) + checkEqualEnumLeft(state, text, position, parent[1], results) end if parent.type == 'local' then - checkEqualEnumLeft(ast, text, offset, parent, results) + checkEqualEnumLeft(state, text, position, parent, results) end if parent.type == 'setlocal' or parent.type == 'setglobal' or parent.type == 'setfield' or parent.type == 'setindex' then - checkEqualEnumLeft(ast, text, offset, parent.node, results) + checkEqualEnumLeft(state, text, position, parent.node, results) end end -local function isFuncArg(ast, offset) - return guide.eachSourceContain(ast.ast, offset, function (source) +local function isFuncArg(state, position) + return guide.eachSourceContain(state.ast, position, function (source) if source.type == 'funcargs' then return true end end) end -local function trySpecial(ast, text, offset, results) - if isInString(ast, offset) then - checkUri(ast, text, offset, results) - checkEqualEnumInString(ast, text, offset, results) +local function trySpecial(state, text, position, results) + if isInString(state, position) then + checkUri(state, text, position, results) + checkEqualEnumInString(state, text, position, results) return end -- x[#x+1] - checkLenPlusOne(ast, text, offset, results) + checkLenPlusOne(state, text, position, results) -- type(o) == - checkEqualEnum(ast, text, offset, results) + checkEqualEnum(state, text, position, results) end -local function tryIndex(ast, text, offset, results) - local parent, oop = findParentInStringIndex(ast, text, offset) +local function tryIndex(state, text, position, results) + local parent, oop = findParentInStringIndex(state, text, position) if not parent then return end local word = parent.next.index[1] - checkField(ast, word, offset, offset, parent, oop, results) + checkField(state, word, position, position, parent, oop, results) end -local function tryWord(ast, text, offset, triggerCharacter, results) - local finish = lookBackward.skipSpace(text, offset) - local word, start = lookBackward.findWord(text, offset) +local function tryWord(state, text, position, triggerCharacter, results) + local finish = lookBackward.skipSpace(text, guide.offsetOf(state, position)) + local word, start = lookBackward.findWord(text, guide.offsetOf(state, position)) if not word then if triggerCharacter == nil then word = '' - start = offset + 1 + start = position + 1 else return nil end end - local hasSpace = triggerCharacter ~= nil and finish ~= offset - if isInString(ast, offset) then + local hasSpace = triggerCharacter ~= nil and finish ~= position + if isInString(state, position) then if not hasSpace then if #results == 0 then - checkCommon(ast.uri, word, text, offset, results) + checkCommon(state.uri, word, text, position, results) end end else - local parent, oop = findParent(ast, text, start - 1) + local parent, oop = findParent(state, text, start - 1) if parent then if not hasSpace then - checkField(ast, word, start, offset, parent, oop, results) + checkField(state, word, start, position, parent, oop, results) end - elseif isFuncArg(ast, offset) then - checkProvideLocal(ast, word, start, results) - checkFunctionArgByDocParam(ast, word, start, results) + elseif isFuncArg(state, position) then + checkProvideLocal(state, word, start, results) + checkFunctionArgByDocParam(state, word, start, results) else local afterLocal = isAfterLocal(text, start) - local stop = checkKeyWord(ast, text, start, offset, word, hasSpace, afterLocal, results) + local stop = checkKeyWord(state, text, start, position, word, hasSpace, afterLocal, results) if stop then return end if not hasSpace then if afterLocal then - checkProvideLocal(ast, word, start, results) + checkProvideLocal(state, word, start, results) else - checkLocal(ast, word, start, results) - checkTableField(ast, word, start, results) - local env = guide.getENV(ast.ast, start) - checkGlobal(ast, word, start, offset, env, false, results) - checkModule(ast, word, start, results) + checkLocal(state, word, start, results) + checkTableField(state, word, start, results) + local env = guide.getENV(state.ast, start) + checkGlobal(state, word, start, position, env, false, results) + checkModule(state, word, start, results) end end end if not hasSpace then - checkCommon(ast.uri, word, text, offset, results) + checkCommon(state.uri, word, text, position, results) end end end -local function trySymbol(ast, text, offset, results) - local symbol, start = lookBackward.findSymbol(text, offset) +local function trySymbol(state, text, position, results) + local symbol, start = lookBackward.findSymbol(text, guide.offsetOf(state, position)) if not symbol then return nil end - if isInString(ast, offset) then + if isInString(state, position) then return nil end if symbol == '.' or symbol == ':' then - local parent, oop = findParent(ast, text, start) + local parent, oop = findParent(state, text, start) if parent then tracy.ZoneBeginN 'completion.trySymbol' - checkField(ast, '', start, offset, parent, oop, results) + checkField(state, '', start, position, parent, oop, results) tracy.ZoneEnd() end end if symbol == '(' then - checkFunctionArgByDocParam(ast, '', start, results) + checkFunctionArgByDocParam(state, '', start, results) end end @@ -1354,9 +1354,9 @@ local function getCallEnumsAndFuncs(source, index, oop) end end -local function findCall(ast, text, offset) +local function findCall(state, text, position) local call - guide.eachSourceContain(ast.ast, offset, function (src) + guide.eachSourceContain(state.ast, position, function (src) if src.type == 'call' then if not call or call.start < src.start then call = src @@ -1366,13 +1366,13 @@ local function findCall(ast, text, offset) return call end -local function getCallArgInfo(call, text, offset) +local function getCallArgInfo(call, text, position) if not call.args then return 1, nil, nil end local oop = call.node.type == 'getmethod' for index, arg in ipairs(call.args) do - if arg.start <= offset and arg.finish >= offset then + if arg.start <= position and arg.finish >= position then return index, arg, oop end end @@ -1391,7 +1391,7 @@ local function getFuncParamByCallIndex(func, index) return func.args[index] end -local function checkTableLiteralField(ast, text, offset, tbl, fields, results) +local function checkTableLiteralField(state, text, position, tbl, fields, results) local mark = {} for _, field in ipairs(tbl) do if field.type == 'tablefield' @@ -1407,9 +1407,9 @@ local function checkTableLiteralField(ast, text, offset, tbl, fields, results) return guide.getKeyName(a) < guide.getKeyName(b) end) -- {$} - local left = lookBackward.findWord(text, offset) + local left = lookBackward.findWord(text, guide.offsetOf(state, position)) if not left then - local pos = lookBackward.findAnyPos(text, offset) + local pos = lookBackward.findAnyPos(text, guide.offsetOf(state, position)) local char = text:sub(pos, pos) if char == '{' or char == ',' or char == ';' then left = '' @@ -1435,8 +1435,8 @@ local function checkTableLiteralField(ast, text, offset, tbl, fields, results) end end -local function checkTableLiteralFieldByCall(ast, text, offset, call, defs, index, results) - local source = findNearestTableField(ast, offset) +local function checkTableLiteralFieldByCall(state, text, position, call, defs, index, results) + local source = findNearestTableField(state, position) if not source then return end @@ -1469,16 +1469,16 @@ local function checkTableLiteralFieldByCall(ast, text, offset, call, defs, index end ::CONTINUE:: end - checkTableLiteralField(ast, text, offset, tbl, fields, results) + checkTableLiteralField(state, text, position, tbl, fields, results) end -local function tryCallArg(ast, text, offset, results) - local call = findCall(ast, text, offset) +local function tryCallArg(state, text, position, results) + local call = findCall(state, text, position) if not call then return end local myResults = {} - local argIndex, arg, oop = getCallArgInfo(call, text, offset) + local argIndex, arg, oop = getCallArgInfo(call, text, position) if arg and arg.type == 'function' then return end @@ -1493,12 +1493,12 @@ local function tryCallArg(ast, text, offset, results) for _, enum in ipairs(myResults) do results[#results+1] = enum end - checkTableLiteralFieldByCall(ast, text, offset, call, defs, argIndex, results) + checkTableLiteralFieldByCall(state, text, position, call, defs, argIndex, results) end -local function tryTable(ast, text, offset, results) - offset = lookBackward.skipSpace(text, offset) - local source = findNearestTableField(ast, offset) +local function tryTable(state, text, position, results) + position = lookBackward.skipSpace(text, guide.offsetOf(state, position)) + local source = findNearestTableField(state, position) if not source then return end @@ -1521,21 +1521,21 @@ local function tryTable(ast, text, offset, results) fields[#fields+1] = field end end - checkTableLiteralField(ast, text, offset, tbl, fields, results) + checkTableLiteralField(state, text, position, tbl, fields, results) end -local function getComment(ast, offset) - for _, comm in ipairs(ast.comms) do - if offset >= comm.start - 2 and offset <= comm.finish then +local function getComment(state, position) + for _, comm in ipairs(state.comms) do + if position >= comm.start - 2 and position <= comm.finish then return comm end end return nil end -local function getLuaDoc(ast, offset) - for _, doc in ipairs(ast.ast.docs) do - if offset >= doc.start and offset <= doc.range then +local function getLuaDoc(state, position) + for _, doc in ipairs(state.ast.docs) do + if position >= doc.start and position <= doc.range then return doc end end @@ -1568,28 +1568,28 @@ local function tryLuaDocCate(word, results) end end -local function getLuaDocByContain(ast, offset) +local function getLuaDocByContain(state, position) local result local range = math.huge - guide.eachSourceContain(ast.ast.docs, offset, function (src) + guide.eachSourceContain(state.ast.docs, position, function (src) if not src.start then return end - if range >= offset - src.start - and offset <= src.finish then - range = offset - src.start + if range >= position - src.start + and position <= src.finish then + range = position - src.start result = src end end) return result end -local function getLuaDocByErr(ast, text, start, offset) +local function getLuaDocByErr(state, text, start, position) local targetError - for _, err in ipairs(ast.errs) do - if err.finish <= offset + for _, err in ipairs(state.errs) do + if err.finish <= position and err.start >= start then - if not text:sub(err.finish + 1, offset):find '%S' then + if not text:sub(err.finish + 1, position):find '%S' then targetError = err break end @@ -1599,8 +1599,8 @@ local function getLuaDocByErr(ast, text, start, offset) return nil end local targetDoc - for i = #ast.ast.docs, 1, -1 do - local doc = ast.ast.docs[i] + for i = #state.ast.docs, 1, -1 do + local doc = state.ast.docs[i] if doc.finish <= targetError.start then targetDoc = doc break @@ -1609,7 +1609,7 @@ local function getLuaDocByErr(ast, text, start, offset) return targetError, targetDoc end -local function tryLuaDocBySource(ast, offset, source, results) +local function tryLuaDocBySource(state, position, source, results) if source.type == 'doc.extends.name' then if source.parent.type == 'doc.class' then for _, doc in ipairs(vm.getDocDefines '*') do @@ -1621,7 +1621,7 @@ local function tryLuaDocBySource(ast, offset, source, results) kind = define.CompletionItemKind.Class, textEdit = doc[1]:find '[^%w_]' and { start = source.start, - finish = offset, + finish = position, newText = doc[1], }, } @@ -1639,7 +1639,7 @@ local function tryLuaDocBySource(ast, offset, source, results) kind = define.CompletionItemKind.Class, textEdit = doc[1]:find '[^%w_]' and { start = source.start, - finish = offset, + finish = position, newText = doc[1], }, } @@ -1648,8 +1648,8 @@ local function tryLuaDocBySource(ast, offset, source, results) return true elseif source.type == 'doc.param.name' then local funcs = {} - guide.eachSourceBetween(ast.ast, offset, math.huge, function (src) - if src.type == 'function' and src.start > offset then + guide.eachSourceBetween(state.ast, position, math.huge, function (src) + if src.type == 'function' and src.start > position then funcs[#funcs+1] = src end end) @@ -1702,7 +1702,7 @@ local function tryLuaDocBySource(ast, offset, source, results) return false end -local function tryLuaDocByErr(ast, offset, err, docState, results) +local function tryLuaDocByErr(state, position, err, docState, results) if err.type == 'LUADOC_MISS_CLASS_EXTENDS_NAME' then for _, doc in ipairs(vm.getDocDefines '*') do if doc.type == 'doc.class.name' @@ -1724,8 +1724,8 @@ local function tryLuaDocByErr(ast, offset, err, docState, results) end elseif err.type == 'LUADOC_MISS_PARAM_NAME' then local funcs = {} - guide.eachSourceBetween(ast.ast, offset, math.huge, function (src) - if src.type == 'function' and src.start > offset then + guide.eachSourceBetween(state.ast, position, math.huge, function (src) + if src.type == 'function' and src.start > position then funcs[#funcs+1] = src end end) @@ -1851,8 +1851,8 @@ local function tryLuaDocOfFunction(doc, results) } end -local function tryLuaDoc(ast, text, offset, results) - local doc = getLuaDoc(ast, offset) +local function tryLuaDoc(state, text, position, results) + local doc = getLuaDoc(state, position) if not doc then return end @@ -1871,29 +1871,29 @@ local function tryLuaDoc(ast, text, offset, results) end end -- 根据输入中的source来补全 - local source = getLuaDocByContain(ast, offset) + local source = getLuaDocByContain(state, position) if source then - local suc = tryLuaDocBySource(ast, offset, source, results) + local suc = tryLuaDocBySource(state, position, source, results) if suc then return end end -- 根据附近的错误消息来补全 - local err, expectDoc = getLuaDocByErr(ast, text, doc.start, offset) + local err, expectDoc = getLuaDocByErr(state, text, doc.start, position) if err then - tryLuaDocByErr(ast, offset, err, expectDoc, results) + tryLuaDocByErr(state, position, err, expectDoc, results) return end end -local function tryComment(ast, text, offset, results) +local function tryComment(state, text, position, results) if #results > 0 then return end - local word = lookBackward.findWord(text, offset) - local doc = getLuaDoc(ast, offset) + local word = lookBackward.findWord(text, guide.offsetOf(state, position)) + local doc = getLuaDoc(state, position) if not word then - local comment = getComment(ast, offset) + local comment = getComment(state, position) if comment.type == 'comment.short' or comment.type == 'comment.cshort' then if comment.text == '' then @@ -1912,23 +1912,24 @@ local function tryComment(ast, text, offset, results) if doc and doc.type ~= 'doc.comment' then return end - checkCommon(ast.uri, word, text, offset, results) + checkCommon(state.uri, word, text, position, results) end -local function makeCache(uri, offset, results) +local function makeCache(uri, position, results) local cache = workspace.getCache 'completion' if not uri then cache.results = nil return end local text = files.getText(uri) - local word = lookBackward.findWord(text, offset) + local state = files.getState(uri) + local word = lookBackward.findWord(text, guide.offsetOf(state, position)) if not word or #word < 2 then cache.results = nil return end cache.results = results - cache.offset = offset + cache.position= position cache.word = word:lower() cache.length = #word end @@ -1950,13 +1951,14 @@ local function isValidCache(word, result) return false end -local function getCache(uri, offset) +local function getCache(uri, position) local cache = workspace.getCache 'completion' if not cache.results then return nil end local text = files.getText(uri) - local word = lookBackward.findWord(text, offset) + local state = files.getState(uri) + local word = lookBackward.findWord(text, guide.offsetOf(state, position)) if not word then return nil end @@ -1980,7 +1982,7 @@ local function getCache(uri, offset) end if results.enableCommon then - checkCommon(uri, word, text, offset, results) + checkCommon(uri, word, text, position, results) end return cache.results @@ -1991,36 +1993,36 @@ local function clearCache() cache.results = nil end -local function completion(uri, offset, triggerCharacter) +local function completion(uri, position, triggerCharacter) tracy.ZoneBeginN 'completion cache' - local results = getCache(uri, offset) + local results = getCache(uri, position) tracy.ZoneEnd() if results then return results end tracy.ZoneBeginN 'completion #1' - local ast = files.getState(uri) + local state = files.getState(uri) local text = files.getText(uri) results = {} clearStack() tracy.ZoneEnd() tracy.ZoneBeginN 'completion #2' - if ast then - if getComment(ast, offset) then - tryLuaDoc(ast, text, offset, results) - tryComment(ast, text, offset, results) + if state then + if getComment(state, position) then + tryLuaDoc(state, text, position, results) + tryComment(state, text, position, results) else - trySpecial(ast, text, offset, results) - tryCallArg(ast, text, offset, results) - tryTable(ast, text, offset, results) - tryWord(ast, text, offset, triggerCharacter, results) - tryIndex(ast, text, offset, results) - trySymbol(ast, text, offset, results) + trySpecial(state, text, position, results) + tryCallArg(state, text, position, results) + tryTable(state, text, position, results) + tryWord(state, text, position, triggerCharacter, results) + tryIndex(state, text, position, results) + trySymbol(state, text, position, results) end else - local word = lookBackward.findWord(text, offset) + local word = lookBackward.findWord(text, guide.offsetOf(state, position)) if word then - checkCommon(nil, word, text, offset, results) + checkCommon(nil, word, text, position, results) end end tracy.ZoneEnd() @@ -2031,7 +2033,7 @@ local function completion(uri, offset, triggerCharacter) end tracy.ZoneBeginN 'completion #3' - makeCache(uri, offset, results) + makeCache(uri, position, results) tracy.ZoneEnd() return results end diff --git a/script/parser/guide.lua b/script/parser/guide.lua index be1305a3..4915f206 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -757,6 +757,15 @@ function m.positionOf(row, col) return row * 10000 + col end +--- 返回全文光标位置 +---@param state any +---@param position integer +function m.offsetOf(state, position) + local lines = state.lines + local row, col = m.rowColOf(position) + return (lines[row] or 1) + col - 1 +end + function m.lineContent(lines, text, row, ignoreNL) local line = lines[row] if not line then -- cgit v1.2.3 From db328eeed2ab7b67a179bb14edfdd0ad03c63bb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 17 Sep 2021 17:54:55 +0800 Subject: update --- script/core/completion.lua | 63 +++++++++++++++++++++++++--------------------- script/parser/guide.lua | 28 ++++++++++++++++++++- 2 files changed, 62 insertions(+), 29 deletions(-) diff --git a/script/core/completion.lua b/script/core/completion.lua index 83c26da5..a3df659b 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -691,11 +691,14 @@ local function checkCommon(myUri, word, text, position, results) end end end - for str, pos in text:gmatch '([%a_][%w_]+)()' do + local state = files.getState(myUri) + for str, offset in text:gmatch '([%a_][%w_]+)()' do if #results >= 100 then break end - if #str >= 3 and not used[str] and pos - 1 ~= position then + if #str >= 3 + and not used[str] + and guide.offsetToPosition(state, offset) ~= position then used[str] = true if matchKey(word, str) then results[#results+1] = { @@ -720,7 +723,7 @@ end local function checkKeyWord(state, text, start, position, word, hasSpace, afterLocal, results) local snipType = config.get 'Lua.completion.keywordSnippet' - local symbol = lookBackward.findSymbol(text, guide.offsetOf(state, start - 1)) + local symbol = lookBackward.findSymbol(text, guide.positionToOffset(state, start - 1)) local isExp = symbol == '(' or symbol == ',' or symbol == '=' local info = { hasSpace = hasSpace, @@ -1120,7 +1123,7 @@ local function checkEqualEnumLeft(state, text, position, source, results) end local function checkEqualEnum(state, text, position, results) - local start = lookBackward.findTargetSymbol(text, guide.offsetOf(state, position), '=') + local start = lookBackward.findTargetSymbol(text, guide.positionToOffset(state, position), '=') if not start then return end @@ -1200,17 +1203,21 @@ local function tryIndex(state, text, position, results) end local function tryWord(state, text, position, triggerCharacter, results) - local finish = lookBackward.skipSpace(text, guide.offsetOf(state, position)) - local word, start = lookBackward.findWord(text, guide.offsetOf(state, position)) + local offset = guide.positionToOffset(state, position) + local finish = lookBackward.skipSpace(text, offset) + local word, start = lookBackward.findWord(text, offset) + local startPos if not word then if triggerCharacter == nil then word = '' - start = position + 1 + startPos = position + 1 else return nil end + else + startPos = guide.offsetToPosition(state, start) end - local hasSpace = triggerCharacter ~= nil and finish ~= position + local hasSpace = triggerCharacter ~= nil and finish ~= offset if isInString(state, position) then if not hasSpace then if #results == 0 then @@ -1218,29 +1225,29 @@ local function tryWord(state, text, position, triggerCharacter, results) end end else - local parent, oop = findParent(state, text, start - 1) + local parent, oop = findParent(state, text, startPos) if parent then if not hasSpace then - checkField(state, word, start, position, parent, oop, results) + checkField(state, word, startPos, position, parent, oop, results) end elseif isFuncArg(state, position) then - checkProvideLocal(state, word, start, results) - checkFunctionArgByDocParam(state, word, start, results) + checkProvideLocal(state, word, startPos, results) + checkFunctionArgByDocParam(state, word, startPos, results) else - local afterLocal = isAfterLocal(text, start) - local stop = checkKeyWord(state, text, start, position, word, hasSpace, afterLocal, results) + local afterLocal = isAfterLocal(text, startPos) + local stop = checkKeyWord(state, text, startPos, position, word, hasSpace, afterLocal, results) if stop then return end if not hasSpace then if afterLocal then - checkProvideLocal(state, word, start, results) + checkProvideLocal(state, word, startPos, results) else - checkLocal(state, word, start, results) - checkTableField(state, word, start, results) - local env = guide.getENV(state.ast, start) - checkGlobal(state, word, start, position, env, false, results) - checkModule(state, word, start, results) + checkLocal(state, word, startPos, results) + checkTableField(state, word, startPos, results) + local env = guide.getENV(state.ast, startPos) + checkGlobal(state, word, startPos, position, env, false, results) + checkModule(state, word, startPos, results) end end end @@ -1251,7 +1258,7 @@ local function tryWord(state, text, position, triggerCharacter, results) end local function trySymbol(state, text, position, results) - local symbol, start = lookBackward.findSymbol(text, guide.offsetOf(state, position)) + local symbol, start = lookBackward.findSymbol(text, guide.positionToOffset(state, position)) if not symbol then return nil end @@ -1407,9 +1414,9 @@ local function checkTableLiteralField(state, text, position, tbl, fields, result return guide.getKeyName(a) < guide.getKeyName(b) end) -- {$} - local left = lookBackward.findWord(text, guide.offsetOf(state, position)) + local left = lookBackward.findWord(text, guide.positionToOffset(state, position)) if not left then - local pos = lookBackward.findAnyPos(text, guide.offsetOf(state, position)) + local pos = lookBackward.findAnyPos(text, guide.positionToOffset(state, position)) local char = text:sub(pos, pos) if char == '{' or char == ',' or char == ';' then left = '' @@ -1497,7 +1504,7 @@ local function tryCallArg(state, text, position, results) end local function tryTable(state, text, position, results) - position = lookBackward.skipSpace(text, guide.offsetOf(state, position)) + position = lookBackward.skipSpace(text, guide.positionToOffset(state, position)) local source = findNearestTableField(state, position) if not source then return @@ -1890,7 +1897,7 @@ local function tryComment(state, text, position, results) if #results > 0 then return end - local word = lookBackward.findWord(text, guide.offsetOf(state, position)) + local word = lookBackward.findWord(text, guide.positionToOffset(state, position)) local doc = getLuaDoc(state, position) if not word then local comment = getComment(state, position) @@ -1923,7 +1930,7 @@ local function makeCache(uri, position, results) end local text = files.getText(uri) local state = files.getState(uri) - local word = lookBackward.findWord(text, guide.offsetOf(state, position)) + local word = lookBackward.findWord(text, guide.positionToOffset(state, position)) if not word or #word < 2 then cache.results = nil return @@ -1958,7 +1965,7 @@ local function getCache(uri, position) end local text = files.getText(uri) local state = files.getState(uri) - local word = lookBackward.findWord(text, guide.offsetOf(state, position)) + local word = lookBackward.findWord(text, guide.positionToOffset(state, position)) if not word then return nil end @@ -2020,7 +2027,7 @@ local function completion(uri, position, triggerCharacter) trySymbol(state, text, position, results) end else - local word = lookBackward.findWord(text, guide.offsetOf(state, position)) + local word = lookBackward.findWord(text, guide.positionToOffset(state, position)) if word then checkCommon(nil, word, text, position, results) end diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 4915f206..e2262cfd 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -760,12 +760,38 @@ end --- 返回全文光标位置 ---@param state any ---@param position integer -function m.offsetOf(state, position) +function m.positionToOffset(state, position) local lines = state.lines local row, col = m.rowColOf(position) return (lines[row] or 1) + col - 1 end +function m.offsetToPosition(state, offset) + local lines = state.lines + local left = 0 + local right = #lines + local row = 0 + while true do + row = (left + right) // 2 + if row == left then + if right ~= left then + if lines[right] <= offset then + row = right + end + end + break + end + local start = lines[row] + if start > offset then + right = row + else + left = row + end + end + local col = offset - (lines[row] or 1) + return m.positionOf(row, col) +end + function m.lineContent(lines, text, row, ignoreNL) local line = lines[row] if not line then -- cgit v1.2.3 From 84148fbedef3f3ae04552dcf3218e05027c17625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 17 Sep 2021 21:07:55 +0800 Subject: update --- script/core/completion.lua | 27 +++++++++++++++------------ script/core/keyword.lua | 8 +++----- script/core/look-backward.lua | 2 +- script/core/type-formatting.lua | 2 +- script/parser/guide.lua | 4 ++-- script/parser/newparser.lua | 4 +++- 6 files changed, 25 insertions(+), 22 deletions(-) diff --git a/script/core/completion.lua b/script/core/completion.lua index a3df659b..08d6f5f2 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -75,7 +75,8 @@ local function findNearestTableField(state, position) end local function findParent(state, text, position) - for i = position, 1, -1 do + local offset = guide.positionToOffset(state, position) + for i = offset, 1, -1 do local char = text:sub(i, i) if lookBackward.isSpace(char) then goto CONTINUE @@ -92,10 +93,11 @@ local function findParent(state, text, position) else return nil, nil end - local anyPos = lookBackward.findAnyPos(text, i-1) - if not anyPos then + local anyOffset = lookBackward.findAnyOffset(text, i-1) + if not anyOffset then return nil, nil end + local anyPos = guide.offsetToPosition(state, anyOffset) local parent = guide.eachSourceContain(state.ast, anyPos, function (source) if source.finish == anyPos then return source @@ -169,17 +171,18 @@ local function getSnip(source) if def ~= source and def.type == 'function' then local uri = guide.getUri(def) local text = files.getText(uri) - local lines = files.getLines(uri) + local state = files.getState(uri) + local lines = state.lines if not text then goto CONTINUE end if vm.isMetaFile(uri) then goto CONTINUE end - local row = guide.rowColOf(def.start) - local firstRow = lines[row] - local lastRow = lines[math.min(row + context - 1, #lines)] - local snip = text:sub(firstRow.start, lastRow.finish) + local firstRow = guide.rowColOf(def.start) + local lastRow = firstRow + context + local lastOffset = lines[lastRow] and (lines[lastRow] - 1) or #text + local snip = text:sub(lines[firstRow], lastOffset) return snip end ::CONTINUE:: @@ -698,7 +701,7 @@ local function checkCommon(myUri, word, text, position, results) end if #str >= 3 and not used[str] - and guide.offsetToPosition(state, offset) ~= position then + and guide.offsetToPosition(state, offset - 1) ~= position then used[str] = true if matchKey(word, str) then results[#results+1] = { @@ -723,7 +726,7 @@ end local function checkKeyWord(state, text, start, position, word, hasSpace, afterLocal, results) local snipType = config.get 'Lua.completion.keywordSnippet' - local symbol = lookBackward.findSymbol(text, guide.positionToOffset(state, start - 1)) + local symbol = lookBackward.findSymbol(text, guide.positionToOffset(state, start)) local isExp = symbol == '(' or symbol == ',' or symbol == '=' local info = { hasSpace = hasSpace, @@ -1215,7 +1218,7 @@ local function tryWord(state, text, position, triggerCharacter, results) return nil end else - startPos = guide.offsetToPosition(state, start) + startPos = guide.offsetToPosition(state, start - 1) end local hasSpace = triggerCharacter ~= nil and finish ~= offset if isInString(state, position) then @@ -1416,7 +1419,7 @@ local function checkTableLiteralField(state, text, position, tbl, fields, result -- {$} local left = lookBackward.findWord(text, guide.positionToOffset(state, position)) if not left then - local pos = lookBackward.findAnyPos(text, guide.positionToOffset(state, position)) + local pos = lookBackward.findAnyOffset(text, guide.positionToOffset(state, position)) local char = text:sub(pos, pos) if char == '{' or char == ',' or char == ';' then left = '' diff --git a/script/core/keyword.lua b/script/core/keyword.lua index 8e041f1c..0825f1bc 100644 --- a/script/core/keyword.lua +++ b/script/core/keyword.lua @@ -24,14 +24,12 @@ end", end return true end, function (info) - return guide.eachSourceContain(info.ast.ast, info.start, function (source) + return guide.eachSourceContain(info.state.ast, info.start, function (source) if source.type == 'while' or source.type == 'in' or source.type == 'loop' then - for i = 1, #source.keyword do - if info.start == source.keyword[i] then - return true - end + if source.finish - info.start <= 2 then + return true end end end) diff --git a/script/core/look-backward.lua b/script/core/look-backward.lua index ee89078f..2f90b768 100644 --- a/script/core/look-backward.lua +++ b/script/core/look-backward.lua @@ -77,7 +77,7 @@ function m.findTargetSymbol(text, offset, symbol) return nil end -function m.findAnyPos(text, offset) +function m.findAnyOffset(text, offset) for i = offset, 1, -1 do if not m.isSpace(text:sub(i, i)) then return i diff --git a/script/core/type-formatting.lua b/script/core/type-formatting.lua index 157a446d..d7bacbf8 100644 --- a/script/core/type-formatting.lua +++ b/script/core/type-formatting.lua @@ -27,7 +27,7 @@ local function findForward(text, offset, ...) end local function findBackward(text, offset, ...) - local pos = lookBackward.findAnyPos(text, offset) + local pos = lookBackward.findAnyOffset(text, offset) for _, symbol in ipairs { ... } do if text:sub(pos - #symbol + 1, pos) == symbol then return pos - #symbol + 1, symbol diff --git a/script/parser/guide.lua b/script/parser/guide.lua index e2262cfd..af623753 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -763,7 +763,7 @@ end function m.positionToOffset(state, position) local lines = state.lines local row, col = m.rowColOf(position) - return (lines[row] or 1) + col - 1 + return lines[row] + col - 1 end function m.offsetToPosition(state, offset) @@ -788,7 +788,7 @@ function m.offsetToPosition(state, offset) left = row end end - local col = offset - (lines[row] or 1) + local col = offset - lines[row] + 1 return m.positionOf(row, col) end diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index 9721526c..e0144dcd 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -3544,7 +3544,9 @@ local function initState(lua, version, options) errs = {}, diags = {}, comms = {}, - lines = {}, + lines = { + [0] = 1, + }, options = options or {}, } if version == 'Lua 5.1' or version == 'LuaJIT' then -- cgit v1.2.3 From 1167244d45c4010912261d03b54aacc7115c69ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 17 Sep 2021 21:18:32 +0800 Subject: update --- script/core/completion.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/script/core/completion.lua b/script/core/completion.lua index 08d6f5f2..8d861aeb 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -1268,17 +1268,18 @@ local function trySymbol(state, text, position, results) if isInString(state, position) then return nil end + local startPos = guide.offsetToPosition(state, start) if symbol == '.' or symbol == ':' then - local parent, oop = findParent(state, text, start) + local parent, oop = findParent(state, text, startPos) if parent then tracy.ZoneBeginN 'completion.trySymbol' - checkField(state, '', start, position, parent, oop, results) + checkField(state, '', startPos, position, parent, oop, results) tracy.ZoneEnd() end end if symbol == '(' then - checkFunctionArgByDocParam(state, '', start, results) + checkFunctionArgByDocParam(state, '', startPos, results) end end -- cgit v1.2.3 From a7fcbe21fa6e06c46875fd8abb6d2eacb1db844e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Sat, 18 Sep 2021 16:04:24 +0800 Subject: update --- script/core/completion.lua | 76 ++++++++++++++++++++++++++++------------------ script/core/keyword.lua | 15 +++++---- test/completion/common.lua | 64 +++++++++++++++++++------------------- 3 files changed, 87 insertions(+), 68 deletions(-) diff --git a/script/core/completion.lua b/script/core/completion.lua index 8d861aeb..e37dceed 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -405,19 +405,28 @@ local function checkModule(state, word, position, results) end end -local function checkFieldFromFieldToIndex(name, src, parent, word, start, position) +local function checkFieldFromFieldToIndex(name, src, parent, word, startPos, position) if name:match '^[%a_][%w_]*$' then return nil end local textEdit, additionalTextEdits - local uri = guide.getUri(parent) - local text = files.getText(uri) - local wordStart + local uri = guide.getUri(parent) + local text = files.getText(uri) + local state = files.getState(uri) + local startOffset = guide.positionToOffset(state, startPos) + local offset = guide.positionToOffset(state, position) + local wordStartOffset if word == '' then - wordStart = text:match('()%S', start + 1) or (position + 1) + wordStartOffset = text:match('()%S', startOffset + 1) + if wordStartOffset then + wordStartOffset = wordStartOffset - 1 + else + wordStartOffset = offset + end else - wordStart = position - #word + 1 + wordStartOffset = offset - #word end + local wordStartPos = guide.offsetToPosition(state, wordStartOffset) local newText if vm.getKeyType(src) == 'string' then newText = ('[%q]'):format(name) @@ -425,26 +434,28 @@ local function checkFieldFromFieldToIndex(name, src, parent, word, start, positi newText = ('[%s]'):format(name) end textEdit = { - start = wordStart, + start = wordStartPos, finish = position, newText = newText, } local nxt = parent.next if nxt then - local dotStart + local dotStart, dotFinish if nxt.type == 'setfield' or nxt.type == 'getfield' or nxt.type == 'tablefield' then dotStart = nxt.dot.start + dotFinish = nxt.dot.finish elseif nxt.type == 'setmethod' or nxt.type == 'getmethod' then dotStart = nxt.colon.start + dotFinish = nxt.colon.finish end if dotStart then additionalTextEdits = { { start = dotStart, - finish = dotStart, + finish = dotFinish, newText = '', } } @@ -460,7 +471,7 @@ local function checkFieldFromFieldToIndex(name, src, parent, word, start, positi return textEdit, additionalTextEdits end -local function checkFieldThen(name, src, word, start, position, parent, oop, results) +local function checkFieldThen(name, src, word, startPos, position, parent, oop, results) local value = searcher.getObjectValue(src) or src local kind = define.CompletionItemKind.Field if value.type == 'function' @@ -501,7 +512,7 @@ local function checkFieldThen(name, src, word, start, position, parent, oop, res newText = name, } else - textEdit, additionalTextEdits = checkFieldFromFieldToIndex(name, src, parent, word, start, position) + textEdit, additionalTextEdits = checkFieldFromFieldToIndex(name, src, parent, word, startPos, position) end results[#results+1] = { label = name, @@ -518,7 +529,7 @@ local function checkFieldThen(name, src, word, start, position, parent, oop, res } end -local function checkFieldOfRefs(refs, state, word, start, position, parent, oop, results, locals, isGlobal) +local function checkFieldOfRefs(refs, state, word, startPos, position, parent, oop, results, locals, isGlobal) local fields = {} local funcs = {} local count = 0 @@ -527,7 +538,7 @@ local function checkFieldOfRefs(refs, state, word, start, position, parent, oop, if not name then goto CONTINUE end - if isSameSource(state, src, start) then + if isSameSource(state, src, startPos) then goto CONTINUE end if isGlobal and locals and locals[name] then @@ -576,15 +587,15 @@ local function checkFieldOfRefs(refs, state, word, start, position, parent, oop, end for name, src in util.sortPairs(fields) do if src then - checkFieldThen(name, src, word, start, position, parent, oop, results) + checkFieldThen(name, src, word, startPos, position, parent, oop, results) end end end -local function checkGlobal(state, word, start, position, parent, oop, results) +local function checkGlobal(state, word, startPos, position, parent, oop, results) local locals = guide.getVisibleLocals(state.ast, position) local globals = vm.getGlobalSets '*' - checkFieldOfRefs(globals, state, word, start, position, parent, oop, results, locals, 'global') + checkFieldOfRefs(globals, state, word, startPos, position, parent, oop, results, locals, 'global') end local function checkField(state, word, start, position, parent, oop, results) @@ -876,9 +887,10 @@ local function checkFunctionArgByDocParam(state, word, start, results) end end -local function isAfterLocal(text, start) - local pos = lookBackward.skipSpace(text, start-1) - local word = lookBackward.findWord(text, pos) +local function isAfterLocal(state, text, startPos) + local offset = guide.positionToOffset(state, startPos) + local pos = lookBackward.skipSpace(text, offset) + local word = lookBackward.findWord(text, pos) return word == 'local' end @@ -1006,19 +1018,23 @@ local function checkLenPlusOne(state, text, position, results) guide.eachSourceContain(state.ast, position, function (source) if source.type == 'getindex' or source.type == 'setindex' then - local _, pos = text:find('%s*%[%s*%#', source.node.finish) - if not pos then + local finish = guide.positionToOffset(state, source.node.finish) + local _, offset = text:find('%s*%[%s*%#', finish) + if not offset then return end - local nodeText = text:sub(source.node.start, source.node.finish) - local writingText = trim(text:sub(pos + 1, position - 1)) or '' + local start = guide.positionToOffset(state, source.node.start) + 1 + local nodeText = text:sub(start, finish) + local writingText = trim(text:sub(offset + 1, guide.positionToOffset(state, position))) or '' if not matchKey(writingText, nodeText) then return end + local offsetPos = guide.offsetToPosition(state, offset) - 1 if source.parent == guide.getParentBlock(source) then + local sourceFinish = guide.positionToOffset(state, source.finish) -- state - local label = text:match('%#[ \t]*', pos) .. nodeText .. '+1' - local eq = text:find('^%s*%]?%s*%=', source.finish) + local label = text:match('%#[ \t]*', offset) .. nodeText .. '+1' + local eq = text:find('^%s*%]?%s*%=', sourceFinish) local newText = label .. ']' if not eq then newText = newText .. ' = ' @@ -1028,20 +1044,20 @@ local function checkLenPlusOne(state, text, position, results) match = nodeText, kind = define.CompletionItemKind.Snippet, textEdit = { - start = pos, + start = offsetPos, finish = source.finish, newText = newText, }, } else -- exp - local label = text:match('%#[ \t]*', pos) .. nodeText + local label = text:match('%#[ \t]*', offset) .. nodeText local newText = label .. ']' results[#results+1] = { label = label, kind = define.CompletionItemKind.Snippet, textEdit = { - start = pos, + start = offsetPos, finish = source.finish, newText = newText, }, @@ -1137,7 +1153,7 @@ local function checkEqualEnum(state, text, position, results) eqOrNeq = true end start = lookBackward.skipSpace(text, start - 1) - local source = findNearestSource(state, start) + local source = findNearestSource(state, guide.offsetToPosition(state, start)) if not source then return end @@ -1237,7 +1253,7 @@ local function tryWord(state, text, position, triggerCharacter, results) checkProvideLocal(state, word, startPos, results) checkFunctionArgByDocParam(state, word, startPos, results) else - local afterLocal = isAfterLocal(text, startPos) + local afterLocal = isAfterLocal(state, text, startPos) local stop = checkKeyWord(state, text, startPos, position, word, hasSpace, afterLocal, results) if stop then return diff --git a/script/core/keyword.lua b/script/core/keyword.lua index 0825f1bc..b0c75f7e 100644 --- a/script/core/keyword.lua +++ b/script/core/keyword.lua @@ -38,8 +38,9 @@ end", {'break'}, {'else'}, {'elseif', function (info, results) - if info.text:find('^%s*then', info.offset + 1) - or info.text:find('^%s*do', info.offset + 1) then + local offset = guide.positionToOffset(info.state, info.position) + if info.text:find('^%s*then', offset + 1) + or info.text:find('^%s*do', offset + 1) then return false end if info.hasSpace then @@ -153,8 +154,9 @@ end" end}, {'goto'}, {'if', function (info, results) - if info.text:find('^%s*then', info.offset + 1) - or info.text:find('^%s*do', info.offset + 1) then + local offset = guide.positionToOffset(info.state, info.position) + if info.text:find('^%s*then', offset + 1) + or info.text:find('^%s*do', offset + 1) then return false end if info.hasSpace then @@ -181,8 +183,9 @@ end" return true end}, {'in', function (info, results) - if info.text:find('^%s*then', info.offset + 1) - or info.text:find('^%s*do', info.offset + 1) then + local offset = guide.positionToOffset(info.state, info.position) + if info.text:find('^%s*then', offset + 1) + or info.text:find('^%s*do', offset + 1) then return false end if info.hasSpace then diff --git a/test/completion/common.lua b/test/completion/common.lua index 66cc6fe4..ff36ee0a 100644 --- a/test/completion/common.lua +++ b/test/completion/common.lua @@ -443,7 +443,7 @@ collectgarbage('') label = "'collect'", kind = define.CompletionItemKind.EnumMember, textEdit = { - start = 16, + start = 15, finish = 17, newText = "'collect'", }, @@ -452,7 +452,7 @@ collectgarbage('') label = "'stop'", kind = define.CompletionItemKind.EnumMember, textEdit = { - start = 16, + start = 15, finish = 17, newText = "'stop'", }, @@ -461,7 +461,7 @@ collectgarbage('') label = "'restart'", kind = define.CompletionItemKind.EnumMember, textEdit = { - start = 16, + start = 15, finish = 17, newText = "'restart'", }, @@ -470,7 +470,7 @@ collectgarbage('') label = "'count'", kind = define.CompletionItemKind.EnumMember, textEdit = { - start = 16, + start = 15, finish = 17, newText = "'count'", }, @@ -479,7 +479,7 @@ collectgarbage('') label = "'step'", kind = define.CompletionItemKind.EnumMember, textEdit = { - start = 16, + start = 15, finish = 17, newText = "'step'", }, @@ -488,7 +488,7 @@ collectgarbage('') label = "'isrunning'", kind = define.CompletionItemKind.EnumMember, textEdit = { - start = 16, + start = 15, finish = 17, newText = "'isrunning'", }, @@ -497,7 +497,7 @@ collectgarbage('') label = "'incremental'", kind = define.CompletionItemKind.EnumMember, textEdit = { - start = 16, + start = 15, finish = 17, newText = "'incremental'", }, @@ -506,7 +506,7 @@ collectgarbage('') label = "'generational'", kind = define.CompletionItemKind.EnumMember, textEdit = { - start = 16, + start = 15, finish = 17, newText = "'generational'", }, @@ -554,7 +554,7 @@ self.results.list[#] label = '#self.results.list+1', kind = define.CompletionItemKind.Snippet, textEdit = { - start = 19, + start = 18, finish = 20, newText = '#self.results.list+1] = ', }, @@ -570,7 +570,7 @@ local n = 1 label = '#self.results.list+1', kind = define.CompletionItemKind.Snippet, textEdit = { - start = 19, + start = 18, finish = 20, newText = '#self.results.list+1] = ', }, @@ -585,7 +585,7 @@ self.results.list[#] = 1 label = '#self.results.list+1', kind = define.CompletionItemKind.Snippet, textEdit = { - start = 19, + start = 18, finish = 20, newText = '#self.results.list+1]', }, @@ -600,7 +600,7 @@ self.results.list[#self.re] label = '#self.results.list+1', kind = define.CompletionItemKind.Snippet, textEdit = { - start = 19, + start = 18, finish = 27, newText = '#self.results.list+1] = ', }, @@ -619,7 +619,7 @@ fff[#ff] label = '#fff+1', kind = define.CompletionItemKind.Snippet, textEdit = { - start = 5, + start = 4, finish = 8, newText = '#fff+1] = ', }, @@ -638,7 +638,7 @@ local _ = fff.kkk[#] label = '#fff.kkk', kind = define.CompletionItemKind.Snippet, textEdit = { - start = 19, + start = 18, finish = 20, newText = '#fff.kkk]', }, @@ -653,7 +653,7 @@ fff.kkk[#].yy label = '#fff.kkk', kind = define.CompletionItemKind.Snippet, textEdit = { - start = 9, + start = 8, finish = 10, newText = '#fff.kkk]', }, @@ -911,7 +911,7 @@ mt:f { label = 'f(a, b, c)', kind = define.CompletionItemKind.Snippet, - insertText = 'f({1:a: any}, {2:b: any}, {3:c: any})', + insertText = 'f(${1:a: any}, ${2:b: any}, ${3:c: any})', }, } @@ -927,8 +927,8 @@ function label = 'function ()', kind = define.CompletionItemKind.Snippet, insertText = "\z -function 1(2)\ -\t0\ +function $1($2)\ +\t$0\ end", }, } @@ -945,8 +945,8 @@ local t = function label = 'function ()', kind = define.CompletionItemKind.Snippet, insertText = "\z -function (1)\ -\t0\ +function ($1)\ +\t$0\ end", }, } @@ -986,14 +986,14 @@ t. label = 'a.b.c', kind = define.CompletionItemKind.Field, textEdit = { - start = 37, - finish = 36, + start = 40002, + finish = 40002, newText = '["a.b.c"]', }, additionalTextEdits = { { - start = 36, - finish = 36, + start = 40001, + finish = 40002, newText = '', }, }, @@ -1012,14 +1012,14 @@ t. label = 'a.b.c', kind = define.CompletionItemKind.Field, textEdit = { - start = 40, - finish = 39, + start = 40005, + finish = 40005, newText = '["a.b.c"]', }, additionalTextEdits = { { - start = 36, - finish = 36, + start = 40001, + finish = 40002, newText = '', }, }, @@ -1038,8 +1038,8 @@ t[''] label = 'a.b.c', kind = define.CompletionItemKind.Field, textEdit = { - start = 38, - finish = 37, + start = 40003, + finish = 40003, newText = 'a.b.c', } } @@ -1055,8 +1055,8 @@ z label = 'z.b.c', kind = define.CompletionItemKind.Field, textEdit = { - start = 21, - finish = 21, + start = 20001, + finish = 20001, newText = '_ENV["z.b.c"]', }, }, -- cgit v1.2.3 From b45a90132438bb2d84b7376066e5ff409833a13f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Sat, 18 Sep 2021 17:28:21 +0800 Subject: update --- script/core/completion.lua | 4 ++-- script/parser/guide.lua | 2 +- script/parser/newparser.lua | 41 +++++++++++++++++++++++------------------ test/completion/common.lua | 2 +- 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/script/core/completion.lua b/script/core/completion.lua index e37dceed..51f1087e 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -1884,14 +1884,14 @@ local function tryLuaDoc(state, text, position, results) return end if doc.type == 'doc.comment' then - local line = text:sub(doc.start, doc.range) + local line = doc.originalComment.text -- 尝试 ---$ if line == '-' then tryLuaDocOfFunction(doc, results) return end -- 尝试 ---@$ - local cate = line:match('^-%s*@(%a*)$') + local cate = line:match('^-+%s*@(%a*)$') if cate then tryLuaDocCate(cate, results) return diff --git a/script/parser/guide.lua b/script/parser/guide.lua index af623753..4a0ca21f 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -781,7 +781,7 @@ function m.offsetToPosition(state, offset) end break end - local start = lines[row] + local start = lines[row] - 1 if start > offset then right = row else diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index e0144dcd..99518261 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -207,21 +207,7 @@ local LocalLimit = 200 local parseExp, parseAction -local function pushError(err) - local errs = State.errs - if err.finish < err.start then - err.finish = err.start - end - local last = errs[#errs] - if last then - if last.start <= err.start and last.finish >= err.finish then - return - end - end - err.level = err.level or 'error' - errs[#errs+1] = err - return err -end +local pushError local function addSpecial(name, obj) local root = State.ast @@ -3537,7 +3523,7 @@ local function initState(lua, version, options) Chunk = {} Tokens = tokens(lua) Index = 1 - State = { + local state = { version = version, lua = lua, ast = {}, @@ -3549,11 +3535,30 @@ local function initState(lua, version, options) }, options = options or {}, } + State = state if version == 'Lua 5.1' or version == 'LuaJIT' then - State.ENVMode = '@fenv' + state.ENVMode = '@fenv' else - State.ENVMode = '_ENV' + state.ENVMode = '_ENV' end + + pushError = function (err) + local errs = state.errs + if err.finish < err.start then + err.finish = err.start + end + local last = errs[#errs] + if last then + if last.start <= err.start and last.finish >= err.finish then + return + end + end + err.level = err.level or 'error' + errs[#errs+1] = err + return err + end + + state.pushError = pushError end return function (lua, mode, version, options) diff --git a/test/completion/common.lua b/test/completion/common.lua index ff36ee0a..f800fa9d 100644 --- a/test/completion/common.lua +++ b/test/completion/common.lua @@ -1055,7 +1055,7 @@ z label = 'z.b.c', kind = define.CompletionItemKind.Field, textEdit = { - start = 20001, + start = 20000, finish = 20001, newText = '_ENV["z.b.c"]', }, -- cgit v1.2.3 From bae4fa96a08158668d8b005f7885a774ad1c98fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Sat, 18 Sep 2021 17:51:43 +0800 Subject: update --- script/core/completion.lua | 6 +++--- script/parser/newparser.lua | 2 +- test/completion/common.lua | 46 ++++++++++++++++++++++----------------------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/script/core/completion.lua b/script/core/completion.lua index 51f1087e..46847540 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -842,8 +842,8 @@ local function checkProvideLocal(state, word, start, results) end) end -local function checkFunctionArgByDocParam(state, word, start, results) - local func = guide.eachSourceContain(state.ast, start, function (source) +local function checkFunctionArgByDocParam(state, word, startPos, results) + local func = guide.eachSourceContain(state.ast, startPos, function (source) if source.type == 'function' then return source end @@ -863,7 +863,7 @@ local function checkFunctionArgByDocParam(state, word, start, results) end local firstArg = func.args and func.args[1] if not firstArg - or firstArg.start <= start and firstArg.finish >= start then + or firstArg.start <= startPos and firstArg.finish >= startPos then local firstParam = params[1] if firstParam and matchKey(word, firstParam.param[1]) then local label = {} diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index 99518261..7955a5c3 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -2131,7 +2131,6 @@ local function parseFunction(isLocal, isAction) params.finish = lastRightPosition() params.parent = func func.args = params - func.finish = params.finish end skipSpace() if Tokens[Index + 1] == ')' then @@ -2143,6 +2142,7 @@ local function parseFunction(isLocal, isAction) Index = Index + 2 skipSpace() else + func.finish = lastRightPosition() if params then params.finish = func.finish end diff --git a/test/completion/common.lua b/test/completion/common.lua index f800fa9d..d0ca92da 100644 --- a/test/completion/common.lua +++ b/test/completion/common.lua @@ -1238,9 +1238,9 @@ end label = 'a, b, c', kind = define.CompletionItemKind.Snippet, insertText = [[ -a {1:any} ----@param b {2:any} ----@param c {3:any}]] +a ${1:any} +---@param b ${2:any} +---@param c ${3:any}]] }, { label = 'a', @@ -1267,9 +1267,9 @@ function f2(a) end label = 'a, b, c', kind = define.CompletionItemKind.Snippet, insertText = [[ -a {1:any} ----@param b {2:any} ----@param c {3:any}]] +a ${1:any} +---@param b ${2:any} +---@param c ${3:any}]] }, { label = 'a', @@ -1309,9 +1309,9 @@ end label = 'a, b, c', kind = define.CompletionItemKind.Snippet, insertText = [[ -a {1:any} ----@param b {2:any} ----@param c {3:any}]] +a ${1:any} +---@param b ${2:any} +---@param c ${3:any}]] }, { label = 'a', @@ -1337,9 +1337,9 @@ end label = 'a, b, c', kind = define.CompletionItemKind.Snippet, insertText = [[ -a {1:any} ----@param b {2:any} ----@param c {3:any}]], +a ${1:any} +---@param b ${2:any} +---@param c ${3:any}]], }, { label = 'self', @@ -1864,7 +1864,7 @@ f() label = 'fun(x: number, y: number):string', kind = define.CompletionItemKind.Function, insertText = "\z -function ({1:x}, {2:y})\ +function (${1:x}, ${2:y})\ \t0\ end", }, @@ -1881,13 +1881,13 @@ end label = '@param;@return', kind = define.CompletionItemKind.Snippet, insertText = "\z -{1:comment}\ ----@param a {2:number}\ ----@param b {3:string}\ ----@param c {4:table}\ ----@return {5:number}\ ----@return {6:string}\ ----@return {7:any}", +${1:comment}\ +---@param a ${2:number}\ +---@param b ${3:string}\ +---@param c ${4:table}\ +---@return ${5:number}\ +---@return ${6:string}\ +---@return ${7:any}", }, } @@ -2376,7 +2376,7 @@ zzzz { label = 'zzzz(a)', kind = define.CompletionItemKind.Snippet, - insertText = 'zzzz({1:a: any})', + insertText = 'zzzz(${1:a: any})', }, { label = 'zzzz(a, b)', @@ -2386,7 +2386,7 @@ zzzz { label = 'zzzz(a, b)', kind = define.CompletionItemKind.Snippet, - insertText = 'zzzz({1:a: any}, {2:b: any})', + insertText = 'zzzz(${1:a: any}, ${2:b: any})', }, } Cared['insertText'] = false @@ -2470,7 +2470,7 @@ f(fun) label = 'fun(a: any, b: any):boolean', kind = define.CompletionItemKind.Function, textEdit = { - newText = 'function ({1:a}, {2:b})\n\t0\nend', + newText = 'function (${1:a}, ${2:b})\n\t0\nend', start = 68, finish = 70, } -- cgit v1.2.3 From 621ee2b3e79dd452ddb3b96cf63a2bc2792b9254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 11:00:40 +0800 Subject: fix --- script/parser/luadoc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 5cf32a54..0463d7d2 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -646,7 +646,7 @@ function parseType(parent) end local nextCommRow = guide.rowColOf(nextComm.start) local currentRow = row + i + 1 - if currentRow > nextCommRow then + if currentRow < nextCommRow then return false end if nextComm.text:sub(1, 2) == '-@' then -- cgit v1.2.3 From a847377582e5f22244aa587f9d79a07f9db03780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 11:30:39 +0800 Subject: update --- script/core/keyword.lua | 13 +++++++------ script/parser/newparser.lua | 5 ++++- test/completion/common.lua | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/script/core/keyword.lua b/script/core/keyword.lua index b0c75f7e..295026d7 100644 --- a/script/core/keyword.lua +++ b/script/core/keyword.lua @@ -271,15 +271,16 @@ until $1" return false end}, {'then', function (info, results) - local lines = files.getLines(info.uri) - local pos, first = info.text:match('%S+%s+()(%S+)', info.start) + local startOffset = guide.positionToOffset(info.state, info.start) + local pos, first = info.text:match('%S+%s+()(%S+)', startOffset + 1) if first == 'end' or first == 'else' or first == 'elseif' then - local startRow = guide.rowColOf(info.start) - local finishRow = guide.rowColOf(pos) - local startSp = info.text:match('^%s*', lines[startRow].start + 1) - local finishSp = info.text:match('^%s*', lines[finishRow].start + 1) + local startRow = guide.rowColOf(info.start) + local finishPosition = guide.offsetToPosition(info.state, pos) + local finishRow = guide.rowColOf(finishPosition) + local startSp = info.text:match('^%s*', info.state.lines[startRow]) + local finishSp = info.text:match('^%s*', info.state.lines[finishRow]) if startSp == finishSp then return false end diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index 7955a5c3..de78fd6d 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -476,7 +476,9 @@ local function skipComment(isAction) or (token == '//' and isAction) then local start = Tokens[Index] local left = getPosition(start, 'left') + local chead = false if token == '//' then + chead = true pushCommentHeadError(left) end Index = Index + 2 @@ -497,7 +499,7 @@ local function skipComment(isAction) Index = Index + 2 end State.comms[#State.comms+1] = { - type = 'comment.shot', + type = chead and 'comment.cshort' or 'comment.short', start = left, finish = getPosition(Tokens[Index], 'right'), text = ssub(Lua, start + 2, Tokens[Index] and (Tokens[Index] - 1) or #Lua), @@ -1663,6 +1665,7 @@ local function parseSimple(node, funcName) call.finish = getPosition(Tokens[Index], 'right') Index = Index + 2 else + call.finish = lastRightPosition() missSymbol ')' end if args then diff --git a/test/completion/common.lua b/test/completion/common.lua index d0ca92da..2f37ef38 100644 --- a/test/completion/common.lua +++ b/test/completion/common.lua @@ -1865,7 +1865,7 @@ f() kind = define.CompletionItemKind.Function, insertText = "\z function (${1:x}, ${2:y})\ -\t0\ +\t$0\ end", }, } -- cgit v1.2.3 From 1ab04aca1e0a3ad9d76aa11fa4e8eefe9781624b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 14:31:13 +0800 Subject: update --- script/core/completion.lua | 3 +-- test/completion/common.lua | 42 +++++++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/script/core/completion.lua b/script/core/completion.lua index 46847540..6f9605e2 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -1524,7 +1524,6 @@ local function tryCallArg(state, text, position, results) end local function tryTable(state, text, position, results) - position = lookBackward.skipSpace(text, guide.positionToOffset(state, position)) local source = findNearestTableField(state, position) if not source then return @@ -1553,7 +1552,7 @@ end local function getComment(state, position) for _, comm in ipairs(state.comms) do - if position >= comm.start - 2 and position <= comm.finish then + if position > comm.start and position <= comm.finish then return comm end end diff --git a/test/completion/common.lua b/test/completion/common.lua index 2f37ef38..33cbdf4d 100644 --- a/test/completion/common.lua +++ b/test/completion/common.lua @@ -2354,8 +2354,8 @@ TEST [[ label = 'AAA.BBB', kind = define.CompletionItemKind.Class, textEdit = { - start = 29, - finish = 32, + start = 20009, + finish = 20013, newText = 'AAA.BBB', }, } @@ -2470,9 +2470,9 @@ f(fun) label = 'fun(a: any, b: any):boolean', kind = define.CompletionItemKind.Function, textEdit = { - newText = 'function (${1:a}, ${2:b})\n\t0\nend', - start = 68, - finish = 70, + newText = 'function (${1:a}, ${2:b})\n\t$0\nend', + start = 30002, + finish = 30005, } }, { @@ -2497,13 +2497,13 @@ t. kind = define.CompletionItemKind.Field, textEdit = { newText = '[1]', - start = 35, - finish = 34, + start = 30002, + finish = 30002, }, additionalTextEdits = { { - start = 34, - finish = 34, + start = 30001, + finish = 30002, newText = '', }, }, @@ -2522,13 +2522,13 @@ t. kind = define.CompletionItemKind.Field, textEdit = { newText = '[1]', - start = 35, - finish = 34, + start = 30002, + finish = 30002, }, additionalTextEdits = { { - start = 34, - finish = 34, + start = 30001, + finish = 30002, newText = '', }, }, @@ -2551,8 +2551,8 @@ local r = f('') kind = define.CompletionItemKind.EnumMember, textEdit = { newText = "'aaa'", - start = 103, - finish = 104, + start = 70012, + finish = 70014, }, }, { @@ -2560,8 +2560,8 @@ local r = f('') kind = define.CompletionItemKind.EnumMember, textEdit = { newText = "'bbb'", - start = 103, - finish = 104, + start = 70012, + finish = 70014, }, }, } @@ -2578,8 +2578,8 @@ f('') kind = define.CompletionItemKind.EnumMember, textEdit = { newText = "'aaa'", - start = 45, - finish = 46, + start = 30002, + finish = 30004, }, }, { @@ -2587,8 +2587,8 @@ f('') kind = define.CompletionItemKind.EnumMember, textEdit = { newText = "'bbb'", - start = 45, - finish = 46, + start = 30002, + finish = 30004, }, }, } -- cgit v1.2.3 From a11c1e47a1bbe1004333143431f901ab8ecde4dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 15:23:04 +0800 Subject: cleanup --- test/crossfile/allreferences.lua | 5 +-- test/crossfile/definition.lua | 79 +++++++++++++--------------------------- test/crossfile/references.lua | 66 +++++++-------------------------- 3 files changed, 41 insertions(+), 109 deletions(-) diff --git a/test/crossfile/allreferences.lua b/test/crossfile/allreferences.lua index 056fa416..67eb893c 100644 --- a/test/crossfile/allreferences.lua +++ b/test/crossfile/allreferences.lua @@ -9,10 +9,9 @@ TEST { { path = 'lib.lua', content = [[ - return <~function~> () - end + return () + end!> ]], - target = {22, 50}, }, } diff --git a/test/crossfile/definition.lua b/test/crossfile/definition.lua index 66e9b269..01bf0202 100644 --- a/test/crossfile/definition.lua +++ b/test/crossfile/definition.lua @@ -3,26 +3,10 @@ local furi = require 'file-uri' local core = require 'core.definition' local config = require 'config' local platform = require 'bee.platform' +local catch = require 'catch' rawset(_G, 'TEST', true) -local function catch_target(script, sep) - local list = {} - local cur = 1 - local cut = 0 - while true do - local start, finish = script:find(('<%%%s.-%%%s>'):format(sep, sep), cur) - if not start then - break - end - list[#list+1] = { start - cut, finish - 4 - cut } - cur = finish + 1 - cut = cut + 4 - end - local new_script = script:gsub(('<%%%s(.-)%%%s>'):format(sep, sep), '%1') - return new_script, list -end - local function founded(targets, results) if #targets ~= #results then return false @@ -50,32 +34,26 @@ function TEST(datas) local sourceUri for i, data in ipairs(datas) do local uri = furi.encode(data.path) - local new, list = catch_target(data.content, '!') - if new ~= data.content or data.target then - if data.target then - targetList[#targetList+1] = { - data.target[1], - data.target[2], - uri, - } - else - for _, position in ipairs(list) do - targetList[#targetList+1] = { - position[1], - position[2], - uri, - } - end - end - data.content = new + local newScript, catched = catch(data.content, '!?~') + for _, position in ipairs(catched['!'] or {}) do + targetList[#targetList+1] = { + position[1], + position[2], + uri, + } + end + for _, position in ipairs(catched['~'] or {}) do + targetList[#targetList+1] = { + position[1], + position[2], + uri, + } end - new, list = catch_target(data.content, '?') - if new ~= data.content then - sourceList = list + if catched['?'] or catched['~'] then + sourceList = catched['?'] or catched['~'] sourceUri = uri - data.content = new end - files.setText(uri, data.content) + files.setText(uri, newScript) end local sourcePos = (sourceList[1][1] + sourceList[1][2]) // 2 @@ -98,8 +76,7 @@ end TEST { { path = 'a.lua', - content = '', - target = {0, 0}, + content = '', }, { path = 'b.lua', @@ -110,8 +87,7 @@ TEST { TEST { { path = 'aaa/bbb.lua', - content = '', - target = {0, 0}, + content = '', }, { path = 'b.lua', @@ -122,8 +98,7 @@ TEST { TEST { { path = '@bbb.lua', - content = '', - target = {0, 0}, + content = '', }, { path = 'b.lua', @@ -134,8 +109,7 @@ TEST { TEST { { path = 'aaa/bbb.lua', - content = '', - target = {0, 0}, + content = '', }, { path = 'b.lua', @@ -150,8 +124,7 @@ TEST { }, { path = 'b.lua', - content = 'local = require "a"', - target = {7, 7}, + content = 'local <~t~> = require "a"', }, } @@ -176,8 +149,7 @@ TEST { }, { path = 'b.lua', - content = 'local = require "a"', - target = {7, 7}, + content = 'local <~t~> = require "a"', }, } @@ -245,9 +217,8 @@ TEST { { path = 'b.lua', content = [[ - local = require 'a' + local <~t~> = require 'a' ]], - target = {19, 19}, }, } diff --git a/test/crossfile/references.lua b/test/crossfile/references.lua index 6c28b34b..145792b5 100644 --- a/test/crossfile/references.lua +++ b/test/crossfile/references.lua @@ -1,6 +1,7 @@ local files = require 'files' local furi = require 'file-uri' local core = require 'core.reference' +local catch = require 'catch' rawset(_G, 'TEST', true) @@ -32,21 +33,6 @@ local function eq(a, b) return a == b end -local function catch_target(script, sep) - local list = {} - local cur = 1 - while true do - local start, finish = script:find(('<%%%s.-%%%s>'):format(sep, sep), cur) - if not start then - break - end - list[#list+1] = { start + 2, finish - 2 } - cur = finish + 1 - end - local new_script = script:gsub(('<%%%s(.-)%%%s>'):format(sep, sep), ' %1 ') - return new_script, list -end - local function founded(targets, results) if #targets ~= #results then return false @@ -74,37 +60,9 @@ function TEST(datas) local sourceUri for i, data in ipairs(datas) do local uri = furi.encode(data.path) - local new, list = catch_target(data.content, '!') - if new ~= data.content or data.target then - if data.target then - targetList[#targetList+1] = { - data.target[1], - data.target[2], - uri, - } - else - for _, position in ipairs(list) do - targetList[#targetList+1] = { - position[1], - position[2], - uri, - } - end - end - data.content = new - end - new, list = catch_target(data.content, '~') - if new ~= data.content then - sourceList = list - sourceUri = uri - data.content = new - end - new, list = catch_target(data.content, '?') - if new ~= data.content then - sourceList = list - sourceUri = uri - data.content = new - for _, position in ipairs(list) do + local newScript, catched = catch(data.content, '!?~') + if catched['!'] or catched['~'] then + for _, position in ipairs(catched['!'] + catched['~']) do targetList[#targetList+1] = { position[1], position[2], @@ -112,7 +70,11 @@ function TEST(datas) } end end - files.setText(uri, data.content) + if catched['?'] or catched['~'] then + sourceList = catched['?'] + catched['~'] + sourceUri = uri + end + files.setText(uri, newScript) end local sourcePos = (sourceList[1][1] + sourceList[1][2]) // 2 @@ -143,7 +105,7 @@ TEST { { path = 'a.lua', content = [[ - local = require 'lib' + local <~f~> = require 'lib' ]], }, } @@ -158,7 +120,7 @@ TEST { { path = 'b.lua', content = [[ - print() + print(<~ROOT~>) ]], }, } @@ -167,7 +129,7 @@ TEST { { path = 'a.lua', content = [[ - = 1 + <~ROOT~> = 1 ]], }, { @@ -183,7 +145,7 @@ TEST { path = 'a.lua', content = [[ local f = require 'lib' - local = f() + local <~o~> = f() ]], }, { @@ -212,7 +174,7 @@ TEST { ---@class A local mt - function mt.() + function mt.<~f~>() end ]] } -- cgit v1.2.3 From b7f7789e46ab8c67d25704be696a1523762b1d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 15:54:44 +0800 Subject: update --- script/parser/guide.lua | 5 +++-- script/parser/newparser.lua | 14 +++++++------- script/vm/getLinks.lua | 6 +++--- test/crossfile/allreferences.lua | 12 ++++++------ 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 4a0ca21f..fb5f3db4 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -725,10 +725,11 @@ end --- 获取指定的 special function m.eachSpecialOf(ast, name, callback) local root = m.getRoot(ast) - if not root.specials then + local state = root.state + if not state.specials then return end - local specials = root.specials[name] + local specials = state.specials[name] if not specials then return end diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index de78fd6d..9547a830 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -210,14 +210,13 @@ local parseExp, parseAction local pushError local function addSpecial(name, obj) - local root = State.ast - if not root.specials then - root.specials = {} + if not State.specials then + State.specials = {} end - if not root.specials[name] then - root.specials[name] = {} + if not State.specials[name] then + State.specials[name] = {} end - root.specials[name][#root.specials[name]+1] = obj + State.specials[name][#State.specials[name]+1] = obj obj.special = name end @@ -1739,7 +1738,7 @@ local function parseSimple(node, funcName) } call.args = args str.parent = args - node.parent = args + node.parent = call node = call elseif CharMapStrLH[token] then local str = parseLongString() @@ -3583,6 +3582,7 @@ return function (lua, mode, version, options) elseif mode == 'Action' then State.ast = parseAction() end + State.ast.state = State return State end diff --git a/script/vm/getLinks.lua b/script/vm/getLinks.lua index 161396f6..d2332504 100644 --- a/script/vm/getLinks.lua +++ b/script/vm/getLinks.lua @@ -6,12 +6,12 @@ local files = require 'files' local function getFileLinks(uri) local ws = require 'workspace' local links = {} - local ast = files.getState(uri) - if not ast then + local state = files.getState(uri) + if not state then return links end tracy.ZoneBeginN('getFileLinks') - guide.eachSpecialOf(ast.ast, 'require', function (source) + guide.eachSpecialOf(state.ast, 'require', function (source) local call = source.parent if not call or call.type ~= 'call' then return diff --git a/test/crossfile/allreferences.lua b/test/crossfile/allreferences.lua index 67eb893c..bddc159d 100644 --- a/test/crossfile/allreferences.lua +++ b/test/crossfile/allreferences.lua @@ -20,7 +20,7 @@ TEST { path = 'a.lua', content = [[ local m = {} - function m.() + function m.<~func~>() end return m ]], @@ -38,7 +38,7 @@ TEST { { path = 'a.lua', content = [[ - return + return <~function () end~> ]], }, { @@ -71,7 +71,7 @@ TEST { { path = 'a.lua', content = [[ - local function () + local function <~f~>() end return { @@ -125,7 +125,7 @@ TEST { local t = require 'a' local = t. - () + <~f~>() return { = , @@ -138,7 +138,7 @@ TEST { { path = 'a.lua', content = [[ - local function () + local function <~f~>() end return { @@ -201,7 +201,7 @@ TEST { { path = 'a.lua', content = [[ - local = require 'b' + local <~t~> = require 'b' return ]] }, -- cgit v1.2.3 From b66a9c9340d63e1a22ba7d5ccad8d9df244240d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 16:37:54 +0800 Subject: update --- script/parser/luadoc.lua | 10 +++++----- test/crossfile/hover.lua | 22 +++------------------- 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 0463d7d2..4a431e68 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -1,7 +1,7 @@ local m = require 'lpeglabel' local re = require 'parser.relabel' local guide = require 'parser.guide' -local grammar = require 'parser.grammar' +local parser = require 'parser.newparser' local TokenTypes, TokenStarts, TokenFinishs, TokenContents local Ci, Offset, pushError, NextComment, Lines @@ -1121,9 +1121,9 @@ local function trimTailComment(text) comment = text:sub(3) end if comment:find '^%s*[\'"[]' then - local result = grammar(nil, comment:gsub('^%s+', ''), 'string') - if result and result[1] then - comment = result[1][1] + local state = parser(comment:gsub('^%s+', ''), 'String') + if state and state.ast then + comment = state.ast[1] end end return comment @@ -1148,7 +1148,7 @@ local function buildLuaDoc(comment) local result = convertTokens() if result then result.range = comment.finish - local cstart = text:find('%S', (result.firstFinish or result.finish) - comment.start + 2) + local cstart = text:find('%S', (result.firstFinish or result.finish) - comment.start) if cstart and cstart < comment.finish then result.comment = { type = 'doc.tailcomment', diff --git a/test/crossfile/hover.lua b/test/crossfile/hover.lua index a877d226..1c46214c 100644 --- a/test/crossfile/hover.lua +++ b/test/crossfile/hover.lua @@ -2,6 +2,7 @@ local files = require 'files' local furi = require 'file-uri' local core = require 'core.hover' local config = require 'config' +local catch = require 'catch' rawset(_G, 'TEST', true) @@ -36,36 +37,19 @@ local function eq(a, b) return a == b end -local function catch_target(script, sep) - local list = {} - local cur = 1 - local cut = 0 - while true do - local start, finish = script:find(('<%%%s.-%%%s>'):format(sep, sep), cur) - if not start then - break - end - list[#list+1] = { start - cut, finish - 4 - cut } - cur = finish + 1 - cut = cut + 4 - end - local new_script = script:gsub(('<%%%s(.-)%%%s>'):format(sep, sep), '%1') - return new_script, list -end - function TEST(expect) files.removeAll() local targetScript = expect[1].content local targetUri = furi.encode(expect[1].path) - local sourceScript, sourceList = catch_target(expect[2].content, '?') + local sourceScript, sourceList = catch(expect[2].content, '?') local sourceUri = furi.encode(expect[2].path) files.setText(targetUri, targetScript) files.setText(sourceUri, sourceScript) - local sourcePos = (sourceList[1][1] + sourceList[1][2]) // 2 + local sourcePos = (sourceList['?'][1][1] + sourceList['?'][1][2]) // 2 local hover = core.byUri(sourceUri, sourcePos) assert(hover) hover = tostring(hover):gsub('\r\n', '\n') -- cgit v1.2.3 From a45e980f0d51c47229d18d0f859e718d203b472f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 16:54:15 +0800 Subject: update --- script/core/noder.lua | 5 +++- test/crossfile/completion.lua | 58 ++++++++++++++++++++++--------------------- test/crossfile/diagnostic.lua | 27 ++++---------------- 3 files changed, 39 insertions(+), 51 deletions(-) diff --git a/script/core/noder.lua b/script/core/noder.lua index 52ab7731..d6069833 100644 --- a/script/core/noder.lua +++ b/script/core/noder.lua @@ -1250,6 +1250,7 @@ compileNodeMap = util.switch() start = node.start, finish = node.finish, vararg = node, + parent = source, } compileCallReturn(noders, node, getID(param1), 2) if not param2 then @@ -1260,6 +1261,7 @@ compileNodeMap = util.switch() start = node.start, finish = node.finish, vararg = node, + parent = source, } compileCallReturn(noders, node, getID(param2), 3) end @@ -1271,7 +1273,8 @@ compileNodeMap = util.switch() start = source.keyword[3], finish = source.keyword[6], node = node, - args = { param1, param2 } + args = { param1, param2 }, + parent = source, } for i = 1, #keys do compileCallReturn(noders, call, getID(keys[i]), i) diff --git a/test/crossfile/completion.lua b/test/crossfile/completion.lua index d26398ca..9c5ed96e 100644 --- a/test/crossfile/completion.lua +++ b/test/crossfile/completion.lua @@ -4,6 +4,7 @@ local furi = require 'file-uri' local platform = require 'bee.platform' local util = require 'utility' local config = require 'config' +local catch = require 'catch' rawset(_G, 'TEST', true) @@ -88,8 +89,9 @@ function TEST(data) local uri = furi.encode(info.path) local script = info.content if info.main then - pos = script:find('$', 1, true) - 1 - script = script:gsub('%$', '') + local newScript, catched = catch(script, '?') + pos = catched['?'][1][1] + script = newScript mainUri = uri end files.setText(uri, script) @@ -139,7 +141,7 @@ TEST { }, { path = 'test.lua', - content = 'require "a$"', + content = 'require "a"', main = true, }, completion = { @@ -178,7 +180,7 @@ TEST { }, { path = 'test.lua', - content = 'require "A$"', + content = 'require "A"', main = true, }, completion = { @@ -201,7 +203,7 @@ TEST { }, { path = 'test.lua', - content = 'require "a$"', + content = 'require "a"', main = true, }, completion = { @@ -229,7 +231,7 @@ TEST { }, { path = 'test.lua', - content = 'require "abc$"', + content = 'require "abc"', main = true, }, completion = { @@ -257,7 +259,7 @@ TEST { }, { path = 'test.lua', - content = 'require "abc$"', + content = 'require "abc"', main = true, }, completion = { @@ -290,7 +292,7 @@ TEST { }, { path = 'test.lua', - content = 'require "abc.i$"', + content = 'require "abc.i"', main = true, }, completion = { @@ -315,7 +317,7 @@ TEST { }, { path = 'test.lua', - content = 'require "abc/i$"', + content = 'require "abc/i"', main = true, }, completion = { @@ -339,7 +341,7 @@ TEST { }, { path = 'test.lua', - content = 'require "core.co$"', + content = 'require "core.co"', main = true, }, completion = { @@ -362,7 +364,7 @@ TEST { }, { path = 'abc/test.lua', - content = 'require "x$"', + content = 'require "x"', main = true, }, completion = { @@ -397,7 +399,7 @@ TEST { }, { path = 'main.lua', - content = 'require "x$"', + content = 'require "x"', main = true, }, completion = { @@ -428,7 +430,7 @@ TEST { }, { path = 'main.lua', - content = 'require "x$"', + content = 'require "x"', main = true, }, completion = { @@ -457,7 +459,7 @@ TEST { path = 'b.lua', content = [[ local t = require 'a' - t.$ + t. ]], main = true, }, @@ -499,7 +501,7 @@ TEST { { path = 'b.lua', content = [[ - zab$ + zab ]], main = true, }, @@ -533,7 +535,7 @@ TEST { { path = 'b.lua', content = [[ - zab$ + zab ]], main = true, }, @@ -557,7 +559,7 @@ TEST { path = 'a.lua', content = [[ local japi = require 'jass.japi' - japi.xxxaaaax$ + japi.xxxaaaax ]], main = true, }, @@ -571,7 +573,7 @@ TEST { { path = 'xxxx.lua', content = [[ - require 'xx$' + require 'xx' ]], main = true, }, @@ -592,7 +594,7 @@ TEST { { path = 'main.lua', content = [[ - require 'xx$' + require 'xx' ]], main = true, }, @@ -613,7 +615,7 @@ TEST { { path = 'main.lua', content = [[ - require [=[xx$]=]' + require [=[xx]=]' ]], main = true, }, @@ -635,7 +637,7 @@ TEST { { path = 'main.lua', content = [[ - dofile 'ab$' + dofile 'ab' ]], main = true, }, @@ -656,7 +658,7 @@ TEST { { path = 'main.lua', content = [[ - dofile 'ab$' + dofile 'ab' ]], main = true, }, @@ -686,7 +688,7 @@ TEST { content = [[ local t = require 'a' local v = setmetatable({}, {__index = t}) - v.$ + v. ]] }, completion = { @@ -712,7 +714,7 @@ TEST { content = [[ local z = require 'a' - z$ + z ]], main = true, }, @@ -743,7 +745,7 @@ TEST { path = 'main.lua', main = true, content = [[ - myfun$ + myfun ]], }, completion = { @@ -774,7 +776,7 @@ TEST { path = 'main.lua', main = true, content = [[ - myfun$ + myfun ]], }, completion = { @@ -807,7 +809,7 @@ TEST { path = 'main.lua', main = true, content = [[ - A.$ + A. ]], }, completion = EXISTS, @@ -819,7 +821,7 @@ TEST { path = 'main.lua', main = true, content = [[ - require'$ + require' ]] }, completion = EXISTS diff --git a/test/crossfile/diagnostic.lua b/test/crossfile/diagnostic.lua index a430cb4e..adc2961f 100644 --- a/test/crossfile/diagnostic.lua +++ b/test/crossfile/diagnostic.lua @@ -3,28 +3,12 @@ local furi = require 'file-uri' local core = require 'core.diagnostics' local config = require 'config' local platform = require 'bee.platform' +local catch = require 'catch' config.get 'Lua.diagnostics.neededFileStatus'['deprecated'] = 'Any' rawset(_G, 'TEST', true) -local function catch_target(script, sep) - local list = {} - local cur = 1 - local cut = 0 - while true do - local start, finish = script:find(('<%%%s.-%%%s>'):format(sep, sep), cur) - if not start then - break - end - list[#list+1] = { start - cut, finish - 4 - cut } - cur = finish + 1 - cut = cut + 4 - end - local new_script = script:gsub(('<%%%s(.-)%%%s>'):format(sep, sep), '%1') - return new_script, list -end - local function founded(targets, results) if #targets ~= #results then return false @@ -48,19 +32,18 @@ function TEST(datas) files.removeAll() local targetList = {} - local sourceUri for _, data in ipairs(datas) do local uri = furi.encode(data.path) - local new, list = catch_target(data.content, '!') - for _, position in ipairs(list) do + local newScript, catched = catch(data.content, '!') + for _, position in ipairs(catched['!'] or {}) do targetList[#targetList+1] = { position[1], position[2], uri, } end - data.content = new - files.setText(uri, new) + data.content = newScript + files.setText(uri, newScript) end local result = {} -- cgit v1.2.3 From 32aa2dac835a0c74b82b19d83d9fd06be7a947ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 17:24:44 +0800 Subject: cleanup --- script/core/code-action.lua | 3 -- script/core/command/autoRequire.lua | 1 - script/core/command/removeSpace.lua | 1 - script/core/completion.lua | 1 - script/core/diagnostics/different-requires.lua | 2 +- script/core/diagnostics/init.lua | 2 +- script/core/diagnostics/newfield-call.lua | 1 - script/core/diagnostics/newline-call.lua | 3 +- script/core/diagnostics/trailing-space.lua | 36 ++++++++------- script/core/semantic-tokens.lua | 1 - script/core/type-formatting.lua | 1 - script/files.lua | 29 ------------ script/parser/guide.lua | 12 ----- script/vm/getDocs.lua | 1 - test/diagnostics/init.lua | 63 +++++++------------------- 15 files changed, 39 insertions(+), 118 deletions(-) diff --git a/script/core/code-action.lua b/script/core/code-action.lua index 922ebff3..ce71f4af 100644 --- a/script/core/code-action.lua +++ b/script/core/code-action.lua @@ -5,7 +5,6 @@ local sp = require 'bee.subprocess' local guide = require "parser.guide" local function checkDisableByLuaDocExits(uri, row, mode, code) - local lines = files.getLines(uri) local ast = files.getState(uri) local text = files.getOriginText(uri) local line = lines[row] @@ -41,7 +40,6 @@ local function checkDisableByLuaDocExits(uri, row, mode, code) end local function checkDisableByLuaDocInsert(uri, row, mode, code) - local lines = files.getLines(uri) local ast = files.getState(uri) local text = files.getOriginText(uri) -- 先看看上一行是不是已经有了 @@ -56,7 +54,6 @@ local function checkDisableByLuaDocInsert(uri, row, mode, code) end local function disableDiagnostic(uri, code, start, results) - local lines = files.getLines(uri) local row = guide.rowColOf(start) results[#results+1] = { title = lang.script('ACTION_DISABLE_DIAG', code), diff --git a/script/core/command/autoRequire.lua b/script/core/command/autoRequire.lua index 2cb6a8f8..e784a827 100644 --- a/script/core/command/autoRequire.lua +++ b/script/core/command/autoRequire.lua @@ -6,7 +6,6 @@ local client = require 'client' local lang = require 'language' local function findInsertOffset(uri) - local lines = files.getLines(uri) local text = files.getText(uri) local fmt = { pair = false, diff --git a/script/core/command/removeSpace.lua b/script/core/command/removeSpace.lua index b94f9788..34c74ce0 100644 --- a/script/core/command/removeSpace.lua +++ b/script/core/command/removeSpace.lua @@ -13,7 +13,6 @@ end return function (data) local uri = data.uri - local lines = files.getLines(uri) local text = files.getText(uri) local ast = files.getState(uri) if not lines then diff --git a/script/core/completion.lua b/script/core/completion.lua index 6f9605e2..e56ed3f8 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -227,7 +227,6 @@ end local function buildInsertRequire(state, targetUri, stemName) local uri = guide.getUri(state.ast) - local lines = files.getLines(uri) local text = files.getText(uri) local start = 1 for i = 1, #lines do diff --git a/script/core/diagnostics/different-requires.lua b/script/core/diagnostics/different-requires.lua index 909342f4..fd7415b6 100644 --- a/script/core/diagnostics/different-requires.lua +++ b/script/core/diagnostics/different-requires.lua @@ -12,7 +12,7 @@ return function (uri, callback) end local cache = vm.getCache 'different-requires' guide.eachSpecialOf(state.ast, 'require', function (source) - local call = source.next + local call = source.parent if not call or call.type ~= 'call' then return end diff --git a/script/core/diagnostics/init.lua b/script/core/diagnostics/init.lua index 09688f6e..63a1bcf0 100644 --- a/script/core/diagnostics/init.lua +++ b/script/core/diagnostics/init.lua @@ -44,7 +44,7 @@ local function check(uri, name, results) if vm.isDiagDisabledAt(uri, result.start, name) then return end - if result.start == 0 then + if result.start < 0 then return end if mark[result.start] then diff --git a/script/core/diagnostics/newfield-call.lua b/script/core/diagnostics/newfield-call.lua index 83d205ca..669ed2bb 100644 --- a/script/core/diagnostics/newfield-call.lua +++ b/script/core/diagnostics/newfield-call.lua @@ -8,7 +8,6 @@ return function (uri, callback) return end - local lines = files.getLines(uri) local text = files.getText(uri) guide.eachSourceType(ast.ast, 'table', function (source) diff --git a/script/core/diagnostics/newline-call.lua b/script/core/diagnostics/newline-call.lua index 1c31fa8d..b28310e3 100644 --- a/script/core/diagnostics/newline-call.lua +++ b/script/core/diagnostics/newline-call.lua @@ -4,9 +4,8 @@ local lang = require 'language' return function (uri, callback) local ast = files.getState(uri) - local lines = files.getLines(uri) local text = files.getText(uri) - if not ast or not lines then + if not ast then return end diff --git a/script/core/diagnostics/trailing-space.lua b/script/core/diagnostics/trailing-space.lua index 824eb83f..5c66b118 100644 --- a/script/core/diagnostics/trailing-space.lua +++ b/script/core/diagnostics/trailing-space.lua @@ -13,40 +13,44 @@ local function isInString(ast, offset) end return function (uri, callback) - local ast = files.getState(uri) - if not ast then + local state = files.getState(uri) + if not state then return end local text = files.getText(uri) - local lines = files.getLines(uri) - for i = 1, #lines do - local start = lines[i].start - local range = lines[i].range - local lastChar = text:sub(range, range) + local lines = state.lines + for i = 0, #lines do + local startPos = lines[i] + local startOffset = guide.positionToOffset(state, startPos) + local finishOffset = text:find('[\r\n]', startOffset) or (#text + 1) + local lastOffset = finishOffset - 1 + local lastChar = text:sub(lastOffset, lastOffset) if lastChar ~= ' ' and lastChar ~= '\t' then goto NEXT_LINE end - if isInString(ast.ast, range) then + local lastPos = guide.offsetToPosition(state, lastOffset) + if isInString(state.ast, lastPos) then goto NEXT_LINE end - local first = start - for n = range - 1, start, -1 do + local firstOffset = startOffset + for n = lastOffset - 1, startOffset, -1 do local char = text:sub(n, n) if char ~= ' ' and char ~= '\t' then - first = n + 1 + firstOffset = n + 1 break end end - if first == start then + local firstPos = guide.offsetToPosition(state, firstOffset) - 1 + if firstOffset == startOffset then callback { - start = first, - finish = range, + start = firstPos, + finish = lastPos, message = lang.script.DIAG_LINE_ONLY_SPACE, } else callback { - start = first, - finish = range, + start = firstPos, + finish = lastPos, message = lang.script.DIAG_LINE_POST_SPACE, } end diff --git a/script/core/semantic-tokens.lua b/script/core/semantic-tokens.lua index 96cbc5e1..238df862 100644 --- a/script/core/semantic-tokens.lua +++ b/script/core/semantic-tokens.lua @@ -214,7 +214,6 @@ end return function (uri, start, finish) local ast = files.getState(uri) - local lines = files.getLines(uri) local text = files.getText(uri) if not ast then return nil diff --git a/script/core/type-formatting.lua b/script/core/type-formatting.lua index d7bacbf8..cd2044bc 100644 --- a/script/core/type-formatting.lua +++ b/script/core/type-formatting.lua @@ -3,7 +3,6 @@ local lookBackward = require 'core.look-backward' local guide = require "parser.guide" local function insertIndentation(uri, offset, edits) - local lines = files.getLines(uri) local text = files.getOriginText(uri) local row = guide.rowColOf(offset) local line = lines[row] diff --git a/script/files.lua b/script/files.lua index 98d9b83c..a3595a4f 100644 --- a/script/files.lua +++ b/script/files.lua @@ -537,35 +537,6 @@ function m.getVisibles(uri) return visibles end ---- 获取文件行信息 ----@param uri uri ----@return table lines -function m.getLines(uri) - local file = m.fileMap[uri] - if not file then - return nil - end - local lines = m.linesMap[uri] - if not lines then - lines = parser.lines(file.text) - m.linesMap[uri] = lines - end - return lines -end - -function m.getOriginLines(uri) - local file = m.fileMap[uri] - if not file then - return nil - end - local lines = m.originLinesMap[uri] - if not lines then - lines = parser.lines(file.originText) - m.originLinesMap[uri] = lines - end - return lines -end - function m.getFile(uri) return m.fileMap[uri] or m.dllMap[uri] diff --git a/script/parser/guide.lua b/script/parser/guide.lua index fb5f3db4..cea56be8 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -805,18 +805,6 @@ function m.lineContent(lines, text, row, ignoreNL) end end -function m.lineRange(lines, row, ignoreNL) - local line = lines[row] - if not line then - return 0, 0 - end - if ignoreNL then - return line.start, line.range - else - return line.start, line.finish - end -end - local isSetMap = { ['setglobal'] = true, ['local'] = true, diff --git a/script/vm/getDocs.lua b/script/vm/getDocs.lua index 218dc048..7cac0935 100644 --- a/script/vm/getDocs.lua +++ b/script/vm/getDocs.lua @@ -177,7 +177,6 @@ function vm.isDeprecated(value, deep) end local function makeDiagRange(uri, doc, results) - local lines = files.getLines(uri) local names if doc.names then names = {} diff --git a/test/diagnostics/init.lua b/test/diagnostics/init.lua index 54ac73ef..840be836 100644 --- a/test/diagnostics/init.lua +++ b/test/diagnostics/init.lua @@ -2,36 +2,12 @@ local core = require 'core.diagnostics' local files = require 'files' local config = require 'config' local util = require 'utility' +local catch = require 'catch' config.get 'Lua.diagnostics.neededFileStatus'['deprecated'] = 'Any' rawset(_G, 'TEST', true) -local function catch_target(script, ...) - local list = {} - local function catch(buf) - local cur = 1 - local cut = 0 - while true do - local start, finish = buf:find('', cur) - if not start then - break - end - list[#list+1] = { start - cut, finish - 4 - cut } - cur = finish + 1 - cut = cut + 4 - end - end - catch(script) - if ... then - for _, buf in ipairs {...} do - catch(buf) - end - end - local new_script = script:gsub('', '%1') - return new_script, list -end - local function founded(targets, results) if #targets ~= #results then return false @@ -50,8 +26,8 @@ end function TEST(script, ...) files.removeAll() - local new_script, target = catch_target(script, ...) - files.setText('', new_script) + local newScript, catched = catch(script, '!') + files.setText('', newScript) files.open('') local datas = {} core('', function (results) @@ -65,11 +41,11 @@ function TEST(script, ...) end if results[1] then - if not founded(target, results) then - error(('%s\n%s'):format(util.dump(target), util.dump(results))) + if not founded(catched['!'], results) then + error(('%s\n%s'):format(util.dump(catched['!']), util.dump(results))) end else - assert(#target == 0) + assert(catched['!'] == nil) end end @@ -99,15 +75,11 @@ local = {} .a = 1 ]] -TEST([[ -local () end!> -]], -[[ -local function () -end ]] -) + TEST [[ local = @@ -118,21 +90,13 @@ local = ]] -TEST([[ +TEST [[ local -local () x() end!> -]], -[[ -local function x() -end -local function () - x() -end ]] -) TEST [[ local print, _G @@ -154,6 +118,11 @@ TEST [[ ]] +TEST [[ + + +]] + TEST [[ X = 1 ]] -- cgit v1.2.3 From c951f3472628bdccdbf13a6bd95bc36cc93523fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 17:41:25 +0800 Subject: update --- script/core/diagnostics/newline-call.lua | 12 ++++++----- script/core/diagnostics/redundant-value.lua | 32 ++++++++++++++--------------- script/files.lua | 6 ------ script/parser/newparser.lua | 16 +++++++++++---- test/diagnostics/init.lua | 2 +- 5 files changed, 36 insertions(+), 32 deletions(-) diff --git a/script/core/diagnostics/newline-call.lua b/script/core/diagnostics/newline-call.lua index b28310e3..dbb8c690 100644 --- a/script/core/diagnostics/newline-call.lua +++ b/script/core/diagnostics/newline-call.lua @@ -3,13 +3,13 @@ local guide = require 'parser.guide' local lang = require 'language' return function (uri, callback) - local ast = files.getState(uri) + local state = files.getState(uri) local text = files.getText(uri) - if not ast then + if not state then return end - guide.eachSourceType(ast.ast, 'call', function (source) + guide.eachSourceType(state.ast, 'call', function (source) local node = source.node local args = source.args if not args then @@ -20,8 +20,10 @@ return function (uri, callback) if not source.next then return end - if text:sub(args.start, args.start) ~= '(' - or text:sub(args.finish, args.finish) ~= ')' then + local startOffset = guide.positionToOffset(state, args.start) + 1 + local finishOffset = guide.positionToOffset(state, args.finish) + if text:sub(startOffset, startOffset) ~= '(' + or text:sub(finishOffset, finishOffset) ~= ')' then return end diff --git a/script/core/diagnostics/redundant-value.lua b/script/core/diagnostics/redundant-value.lua index d6cd97a7..4c913330 100644 --- a/script/core/diagnostics/redundant-value.lua +++ b/script/core/diagnostics/redundant-value.lua @@ -1,24 +1,24 @@ local files = require 'files' local define = require 'proto.define' local lang = require 'language' +local guide = require 'parser.guide' +local await = require 'await' -return function (uri, callback, code) - local ast = files.getState(uri) - if not ast then +return function (uri, callback) + local state = files.getState(uri) + if not state then return end - local diags = ast.diags[code] - if not diags then - return - end - - for _, info in ipairs(diags) do - callback { - start = info.start, - finish = info.finish, - tags = { define.DiagnosticTag.Unnecessary }, - message = lang.script('DIAG_OVER_MAX_VALUES', info.max, info.passed) - } - end + guide.eachSource(state.ast, function (src) + await.delay() + if src.redundant then + callback { + start = src.start, + finish = src.finish, + tags = { define.DiagnosticTag.Unnecessary }, + message = lang.script('DIAG_OVER_MAX_VALUES', src.redundant.max, src.redundant.passed) + } + end + end) end diff --git a/script/files.lua b/script/files.lua index a3595a4f..25f07ca2 100644 --- a/script/files.lua +++ b/script/files.lua @@ -35,8 +35,6 @@ m.assocMatcher = nil m.globalVersion = 0 m.fileCount = 0 m.astCount = 0 -m.linesMap = setmetatable({}, { __mode = 'v' }) -m.originLinesMap = setmetatable({}, { __mode = 'v' }) m.astMap = {} -- setmetatable({}, { __mode = 'v' }) --- 打开文件 @@ -160,8 +158,6 @@ function m.setText(uri, text, isTrust, instance) file.trusted = isTrust file.originText = text file.words = nil - m.linesMap[uri] = nil - m.originLinesMap[uri] = nil m.astMap[uri] = nil file.cache = {} file.cacheActiveTime = math.huge @@ -346,7 +342,6 @@ function m.removeAll() m.fileCount = m.fileCount - 1 m.fileMap[uri] = nil m.astMap[uri] = nil - m.linesMap[uri] = nil m.onWatch('remove', uri) end end @@ -366,7 +361,6 @@ function m.removeAllClosed() m.fileCount = m.fileCount - 1 m.fileMap[uri] = nil m.astMap[uri] = nil - m.linesMap[uri] = nil m.onWatch('remove', uri) end end diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index 9547a830..ba91cd10 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -2573,6 +2573,7 @@ local function parseMultiVars(n1, parser, isLocal) skipSpace() local v1, v2, vrest local isSet + local max = 1 if expectAssign() then v1, v2, vrest = parseSetValues() isSet = true @@ -2583,6 +2584,7 @@ local function parseMultiVars(n1, parser, isLocal) bindValue(n1, v1, 1, nil, isLocal, isSet) local lastValue = v1 if n2 then + max = 2 bindValue(n2, v2, 2, lastValue, isLocal, isSet) lastValue = v2 or lastValue pushActionIntoCurrentChunk(n2) @@ -2591,21 +2593,28 @@ local function parseMultiVars(n1, parser, isLocal) for i = 1, #nrest do local n = nrest[i] local v = vrest and vrest[i] - bindValue(n, v, i + 2, lastValue, isLocal, isSet) + max = i + 2 + bindValue(n, v, max, lastValue, isLocal, isSet) lastValue = v or lastValue pushActionIntoCurrentChunk(n) end end if v2 and not n2 then - v2.redundant = true + v2.redundant = { + max = max, + passed = 2, + } pushActionIntoCurrentChunk(v2) end if vrest then for i = 1, #vrest do local v = vrest[i] if not nrest or not nrest[i] then - v.redundant = true + v.redundant = { + max = max, + passed = v + 2, + } pushActionIntoCurrentChunk(v) end end @@ -3530,7 +3539,6 @@ local function initState(lua, version, options) lua = lua, ast = {}, errs = {}, - diags = {}, comms = {}, lines = { [0] = 1, diff --git a/test/diagnostics/init.lua b/test/diagnostics/init.lua index 840be836..5f69bdc9 100644 --- a/test/diagnostics/init.lua +++ b/test/diagnostics/init.lua @@ -41,7 +41,7 @@ function TEST(script, ...) end if results[1] then - if not founded(catched['!'], results) then + if not founded(catched['!'] or {}, results) then error(('%s\n%s'):format(util.dump(catched['!']), util.dump(results))) end else -- cgit v1.2.3 From f57367d3bcdc7229d1d9b3125f6fd4c60342ca50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 19:34:29 +0800 Subject: fix --- script/core/diagnostics/undefined-global.lua | 2 ++ script/core/noder.lua | 21 ++++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/script/core/diagnostics/undefined-global.lua b/script/core/diagnostics/undefined-global.lua index c7ddeac2..14754c16 100644 --- a/script/core/diagnostics/undefined-global.lua +++ b/script/core/diagnostics/undefined-global.lua @@ -5,6 +5,7 @@ local config = require 'config' local guide = require 'parser.guide' local noder = require 'core.noder' local collector = require 'core.collector' +local await = require 'await' local requireLike = { ['include'] = true, @@ -35,6 +36,7 @@ return function (uri, callback) if node.tag ~= '_ENV' then return end + await.delay() local id = 'def:' .. noder.getID(src) if not collector.has(id) then local message = lang.script('DIAG_UNDEF_GLOBAL', key) diff --git a/script/core/noder.lua b/script/core/noder.lua index d6069833..1107dcda 100644 --- a/script/core/noder.lua +++ b/script/core/noder.lua @@ -1583,11 +1583,6 @@ local partNodersMap = util.switch() m.compilePartNodes(noders, ref) end end - - local nxt = source.next - if nxt then - m.compilePartNodes(noders, nxt) - end end) : case 'setlocal' : case 'getlocal' @@ -1603,6 +1598,14 @@ local partNodersMap = util.switch() if parent.value == source then m.compilePartNodes(noders, parent) end + + if parent.type == 'call' then + local node = parent.node + if node.special == 'rawset' + or node.special == 'rawget' then + m.compilePartNodes(noders, parent) + end + end end) : case 'setfield' : case 'getfield' @@ -1634,6 +1637,14 @@ local partNodersMap = util.switch() if parent.value == source then m.compilePartNodes(noders, parent) end + + if parent.type == 'call' then + local node = parent.node + if node.special == 'rawset' + or node.special == 'rawget' then + m.compilePartNodes(noders, parent) + end + end end) : case 'label' : call(function (noders, source) -- cgit v1.2.3 From 9c79a00b41e1eff3a04a3daea6762ece89bb60eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 19:39:41 +0800 Subject: fix --- script/core/diagnostics/count-down-loop.lua | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/script/core/diagnostics/count-down-loop.lua b/script/core/diagnostics/count-down-loop.lua index 1a7dcf7d..49c48880 100644 --- a/script/core/diagnostics/count-down-loop.lua +++ b/script/core/diagnostics/count-down-loop.lua @@ -10,30 +10,39 @@ return function (uri, callback) end guide.eachSourceType(state.ast, 'loop', function (source) - if not source.loc or not source.loc.value then - return - end local maxNumer = source.max and tonumber(source.max[1]) if maxNumer ~= 1 then return end - local minNumber = source.loc and source.loc.value and tonumber(source.loc.value[1]) + local minNumber = source.init and tonumber(source.init[1]) if minNumber and minNumber <= 1 then return end if not source.step then callback { - start = source.loc.value.start, + start = source.init.start, finish = source.max.finish, - message = lang.script('DIAG_COUNT_DOWN_LOOP', ('%s, %s'):format(text:sub(source.loc.value.start, source.max.finish), '-1')) + message = lang.script('DIAG_COUNT_DOWN_LOOP' + , ('%s, %s'):format(text:sub( + guide.positionToOffset(state, source.init.start), + guide.positionToOffset(state, source.max.finish) + ) + , '-1') + ) } else local stepNumber = tonumber(source.step[1]) if stepNumber and stepNumber > 0 then callback { - start = source.loc.value.start, + start = source.init.start, finish = source.step.finish, - message = lang.script('DIAG_COUNT_DOWN_LOOP', ('%s, -%s'):format(text:sub(source.loc.value.start, source.max.finish), source.step[1])) + message = lang.script('DIAG_COUNT_DOWN_LOOP' + , ('%s, -%s'):format(text:sub( + guide.positionToOffset(state, source.init.start), + guide.positionToOffset(state, source.max.finish) + ) + , source.step[1]) + ) } end end -- cgit v1.2.3 From eda1918a82894137c58e19a7fdb1301e3c2bbf30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 20:03:07 +0800 Subject: update --- script/vm/getDocs.lua | 77 ++++++++++++++++++++++--------------------------- test/highlight/init.lua | 38 +++++++----------------- 2 files changed, 44 insertions(+), 71 deletions(-) diff --git a/script/vm/getDocs.lua b/script/vm/getDocs.lua index 7cac0935..0c6b1695 100644 --- a/script/vm/getDocs.lua +++ b/script/vm/getDocs.lua @@ -187,55 +187,49 @@ local function makeDiagRange(uri, doc, results) end local row = guide.rowColOf(doc.start) if doc.mode == 'disable-next-line' then - if lines[row+1] then - results[#results+1] = { - mode = 'disable', - names = names, - offset = lines[row+1].start, - source = doc, - } - results[#results+1] = { - mode = 'enable', - names = names, - offset = lines[row+1].finish, - source = doc, - } - end + results[#results+1] = { + mode = 'disable', + names = names, + row = row + 1, + source = doc, + } + results[#results+1] = { + mode = 'enable', + names = names, + row = row + 2, + source = doc, + } elseif doc.mode == 'disable-line' then results[#results+1] = { mode = 'disable', names = names, - offset = lines[row].start, + row = row, source = doc, } results[#results+1] = { mode = 'enable', names = names, - offset = lines[row].finish, + row = row + 1, source = doc, } elseif doc.mode == 'disable' then - if lines[row+1] then - results[#results+1] = { - mode = 'disable', - names = names, - offset = lines[row+1].start, - source = doc, - } - end + results[#results+1] = { + mode = 'disable', + names = names, + row = row + 1, + source = doc, + } elseif doc.mode == 'enable' then - if lines[row+1] then - results[#results+1] = { - mode = 'enable', - names = names, - offset = lines[row+1].start, - source = doc, - } - end + results[#results+1] = { + mode = 'enable', + names = names, + row = row + 1, + source = doc, + } end end -function vm.isDiagDisabledAt(uri, offset, name) +function vm.isDiagDisabledAt(uri, position, name) local status = files.getState(uri) if not status then return false @@ -252,29 +246,26 @@ function vm.isDiagDisabledAt(uri, offset, name) end end table.sort(cache.diagnosticRanges, function (a, b) - return a.offset < b.offset + return a.row < b.row end) end if #cache.diagnosticRanges == 0 then return false end - local stack = {} + local myRow = guide.rowColOf(position) + local count = 0 for _, range in ipairs(cache.diagnosticRanges) do - if range.offset <= offset then + if range.row <= myRow then if not range.names or range.names[name] then if range.mode == 'disable' then - stack[#stack+1] = range + count = count + 1 elseif range.mode == 'enable' then - stack[#stack] = nil + count = count - 1 end end else break end end - local current = stack[#stack] - if not current then - return false - end - return true + return count > 0 end diff --git a/test/highlight/init.lua b/test/highlight/init.lua index 2bf639fa..7faa9e08 100644 --- a/test/highlight/init.lua +++ b/test/highlight/init.lua @@ -1,22 +1,6 @@ local core = require 'core.highlight' local files = require 'files' - -local function catch_target(script) - local list = {} - local cur = 1 - while true do - local start, finish = script:find('<[!?].-[!?]>', cur) - if not start then - break - end - list[#list+1] = { - start = start + 2, - finish = finish - 2, - } - cur = finish + 1 - end - return list -end +local catch = require 'catch' local function founded(targets, results) if #targets ~= #results then @@ -35,20 +19,18 @@ local function founded(targets, results) end function TEST(script) - local target = catch_target(script) - for _, enter in ipairs(target) do - local start, finish = enter.start, enter.finish - files.removeAll() + files.removeAll() + local newScript, catched = catch(script, '!') + files.setText('', newScript) + for _, enter in ipairs(catched['!']) do + local start, finish = enter[1], enter[2] local pos = (start + finish) // 2 - local new_script = script:gsub('<[!?~]', ' '):gsub('[!?~]>', ' ') - files.setText('', new_script) - local positions = core('', pos) - if positions then - assert(founded(target, positions)) - else - assert(#target == 0) + local results = {} + for _, position in ipairs(positions) do + results[#results+1] = { position.start, position.finish } end + assert(founded(catched['!'], results)) end end -- cgit v1.2.3 From 087a93d3df198aef7f0b7fb5a5af34b09fa630a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 20:51:51 +0800 Subject: update --- script/core/highlight.lua | 40 ++++++++++++++++++++-------------------- script/core/rename.lua | 25 +++++++++++++++---------- script/parser/guide.lua | 1 + script/parser/newparser.lua | 16 ++++++++-------- test/rename/init.lua | 17 ++++++++++++----- 5 files changed, 56 insertions(+), 43 deletions(-) diff --git a/script/core/highlight.lua b/script/core/highlight.lua index 47b482d5..02f3c07f 100644 --- a/script/core/highlight.lua +++ b/script/core/highlight.lua @@ -54,12 +54,12 @@ local function find(source, uri, callback) end end -local function checkInIf(source, text, offset) +local function checkInIf(state, source, text, position) -- 检查 end - local endA = source.finish - #'end' + 1 - local endB = source.finish - if offset >= endA - and offset <= endB + local endB = guide.positionToOffset(state, source.finish) + local endA = endB - #'end' + 1 + if position >= source.finish - #'end' + and position <= source.finish and text:sub(endA, endB) == 'end' then return true end @@ -68,7 +68,7 @@ local function checkInIf(source, text, offset) for i = 1, #block.keyword, 2 do local start = block.keyword[i] local finish = block.keyword[i+1] - if offset >= start and offset <= finish then + if position >= start and position <= finish then return true end end @@ -76,12 +76,12 @@ local function checkInIf(source, text, offset) return false end -local function makeIf(source, text, callback) +local function makeIf(state, source, text, callback) -- end - local endA = source.finish - #'end' + 1 - local endB = source.finish + local endB = guide.positionToOffset(state, source.finish) + local endA = endB - #'end' + 1 if text:sub(endA, endB) == 'end' then - callback(endA, endB) + callback(source.finish - #'end', source.finish) end -- 每个子模块 for _, block in ipairs(source) do @@ -94,8 +94,8 @@ local function makeIf(source, text, callback) return false end -local function findKeyWord(ast, text, offset, callback) - guide.eachSourceContain(ast.ast, offset, function (source) +local function findKeyWord(state, text, position, callback) + guide.eachSourceContain(state.ast, position, function (source) if source.type == 'do' or source.type == 'function' or source.type == 'loop' @@ -106,7 +106,7 @@ local function findKeyWord(ast, text, offset, callback) for i = 1, #source.keyword, 2 do local start = source.keyword[i] local finish = source.keyword[i+1] - if offset >= start and offset <= finish then + if position >= start and position <= finish then ok = true break end @@ -119,9 +119,9 @@ local function findKeyWord(ast, text, offset, callback) end end elseif source.type == 'if' then - local ok = checkInIf(source, text, offset) + local ok = checkInIf(state, source, text, position) if ok then - makeIf(source, text, callback) + makeIf(state, source, text, callback) end end end) @@ -238,15 +238,15 @@ local function isLiteralValue(source) end return function (uri, offset) - local ast = files.getState(uri) - if not ast then + local state = files.getState(uri) + if not state then return nil end local text = files.getText(uri) local results = {} local mark = {} - local source = findSource(ast, offset, accept) + local source = findSource(state, offset, accept) if source then local isGlobal = guide.isGlobal(source) local isLiteral = isLiteralValue(source) @@ -344,7 +344,7 @@ return function (uri, offset) end) end - findKeyWord(ast, text, offset, function (start, finish) + findKeyWord(state, text, offset, function (start, finish) results[#results+1] = { start = start, finish = finish, @@ -352,7 +352,7 @@ return function (uri, offset) } end) - checkRegion(ast, text, offset, function (start, finish) + checkRegion(state, text, offset, function (start, finish) results[#results+1] = { start = start, finish = finish, diff --git a/script/core/rename.lua b/script/core/rename.lua index 0ab7a055..0c48dbc4 100644 --- a/script/core/rename.lua +++ b/script/core/rename.lua @@ -36,12 +36,12 @@ local function isValidFunctionName(str) if isValidGlobal(str) then return true end - local pos = str:find(':', 1, true) - if not pos then + local offset = str:find(':', 1, true) + if not offset then return false end - return isValidGlobal(trim(str:sub(1, pos-1))) - and isValidName(trim(str:sub(pos+1))) + return isValidGlobal(trim(str:sub(1, offset-1))) + and isValidName(trim(str:sub(offset+1))) end local function isFunctionGlobalName(source) @@ -81,21 +81,26 @@ local function renameField(source, newname, callback) elseif parent.type == 'getmethod' then callback(source, source.start, source.finish, newname) elseif parent.type == 'setmethod' then - local uri = guide.getUri(source) - local text = files.getText(uri) + local uri = guide.getUri(source) + local text = files.getText(uri) + local state = files.getState(uri) local func = parent.value -- function mt:name () end --> mt['newname'] = function (self) end + local startOffset = guide.positionToOffset(state, parent.start) + 1 + local finishOffset = guide.positionToOffset(state, parent.node.finish) local newstr = string.format('%s[%s] = function ' - , text:sub(parent.start, parent.node.finish) + , text:sub(startOffset, finishOffset) , util.viewString(newname) ) callback(source, func.start, parent.finish, newstr) - local pl = text:find('(', parent.finish, true) + local finishOffset = guide.positionToOffset(state, parent.finish) + local pl = text:find('(', finishOffset, true) if pl then + local insertPos = guide.offsetToPosition(state, pl) if text:find('^%s*%)', pl + 1) then - callback(source, pl + 1, pl, 'self') + callback(source, insertPos, insertPos, 'self') else - callback(source, pl + 1, pl, 'self, ') + callback(source, insertPos, insertPos, 'self, ') end end end diff --git a/script/parser/guide.lua b/script/parser/guide.lua index cea56be8..28a275cf 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -54,6 +54,7 @@ local type = type ---@field ref parser.guide.object[] ---@field returnIndex integer ---@field docs parser.guide.object[] +---@field state table ---@field _root parser.guide.object ---@field _noders noders ---@field _mnode parser.guide.object diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index ba91cd10..957d98e8 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -416,11 +416,11 @@ local function parseLongString() fastForwardToken(finish + 1) local startPos = getPosition(start, 'left') local finishMark = sgsub(mark, '%[', ']') - local stringResult, finishOffset = resolveLongString(finishMark) + local stringResult, finishPos = resolveLongString(finishMark) return { type = 'string', start = startPos, - finish = getPosition(finishOffset, 'right'), + finish = finishPos, [1] = stringResult, [2] = mark, } @@ -1430,14 +1430,14 @@ local function parseExpList(mini) end local function parseIndex() - local bstart = getPosition(Tokens[Index], 'left') + local start = getPosition(Tokens[Index], 'left') Index = Index + 2 skipSpace() local exp = parseExp() local index = { type = 'index', - start = bstart, - finish = exp and exp.finish or (bstart + 1), + start = start, + finish = exp and exp.finish or (start + 1), index = exp } if exp then @@ -1764,9 +1764,9 @@ local function parseSimple(node, funcName) node.parent = call node = call else - local index = parseIndex() + local index = parseIndex() + local bstart = index.start index.type = 'getindex' - index.bstart = index.start index.start = node.start index.node = node node.next = index @@ -1775,7 +1775,7 @@ local function parseSimple(node, funcName) if funcName then pushError { type = 'INDEX_IN_FUNC_NAME', - start = index.bstart, + start = bstart, finish = index.finish, } end diff --git a/test/rename/init.lua b/test/rename/init.lua index 4b10756e..b20c0279 100644 --- a/test/rename/init.lua +++ b/test/rename/init.lua @@ -1,16 +1,21 @@ local core = require 'core.rename' local files = require 'files' +local catch = require 'catch' +local guide = require 'parser.guide' local function replace(text, positions) + local state = files.getState('') local buf = {} table.sort(positions, function (a, b) return a.start < b.start end) local lastPos = 1 for _, info in ipairs(positions) do - buf[#buf+1] = text:sub(lastPos, info.start - 1) + local start = guide.positionToOffset(state, info.start) + local finish = guide.positionToOffset(state, info.finish) + buf[#buf+1] = text:sub(lastPos, start) buf[#buf+1] = info.text - lastPos = info.finish + 1 + lastPos = finish + 1 end buf[#buf+1] = text:sub(lastPos) return table.concat(buf) @@ -21,10 +26,12 @@ function TEST(oldName, newName) return function (expectScript) files.removeAll() files.setText('', oldScript) - local pos = oldScript:find('[^%w_]'..oldName..'[^%w_]') - assert(pos) + local state = files.getState('') + local offset = oldScript:find('[^%w_]'..oldName..'[^%w_]') + assert(offset) + local position = guide.offsetToPosition(state, offset) - local positions = core.rename('', pos+1, newName) + local positions = core.rename('', position, newName) local script = oldScript if positions then script = replace(script, positions) -- cgit v1.2.3 From c608e84003aed61a16484296edad3fe4ff363322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 21:50:50 +0800 Subject: update --- script/core/signature.lua | 36 +++++---- test/signature/init.lua | 193 +++++++++++++--------------------------------- 2 files changed, 77 insertions(+), 152 deletions(-) diff --git a/script/core/signature.lua b/script/core/signature.lua index 26d9867c..007a3787 100644 --- a/script/core/signature.lua +++ b/script/core/signature.lua @@ -7,20 +7,22 @@ local guide = require 'parser.guide' local lookback = require 'core.look-backward' local function findNearCall(uri, ast, pos) - local text = files.getText(uri) + local text = files.getText(uri) + local state = files.getState(uri) local nearCall guide.eachSourceContain(ast.ast, pos, function (src) if src.type == 'call' or src.type == 'table' or src.type == 'function' then + local finishOffset = guide.positionToOffset(state, src.finish) -- call(),$ if src.finish <= pos - and text:sub(src.finish, src.finish) == ')' then + and text:sub(finishOffset, finishOffset) == ')' then return end -- {},$ if src.finish <= pos - and text:sub(src.finish, src.finish) == '}' then + and text:sub(finishOffset, finishOffset) == '}' then return end if not nearCall or nearCall.start <= src.start then @@ -56,13 +58,13 @@ local function makeOneSignature(source, oop, index) for start, finish in converted:gmatch '%s*()[^,]+()' do i = i + 1 params[i] = { - label = {start + argStart, finish - 1 + argStart}, + label = {start + argStart - 1, finish - 1 + argStart}, } end -- 不定参数 if index > i and i > 0 then local lastLabel = params[i].label - local text = label:sub(lastLabel[1], lastLabel[2]) + local text = label:sub(lastLabel[1] + 1, lastLabel[2]) if text == '...' then index = i end @@ -88,11 +90,15 @@ local function makeSignatures(text, call, pos) args[#args+1] = arg end end + local uri = guide.getUri(call) + local state = files.getState(uri) for i, arg in ipairs(args) do - local start = lookback.findTargetSymbol(text, arg.start - 1, '(') - or lookback.findTargetSymbol(text, arg.start - 1, ',') - or arg.start - if start > pos then + local startOffset = guide.positionToOffset(state, arg.start) + startOffset = lookback.findTargetSymbol(text, startOffset, '(') + or lookback.findTargetSymbol(text, startOffset, ',') + or startOffset + local startPos = guide.offsetToPosition(state, startOffset) + if startPos > pos then index = i - 1 break end @@ -102,7 +108,8 @@ local function makeSignatures(text, call, pos) end end if not index then - local backSymbol = lookback.findSymbol(text, pos) + local offset = guide.positionToOffset(state, pos) + local backSymbol = lookback.findSymbol(text, offset) if backSymbol == ',' or backSymbol == '(' then index = #args + 1 @@ -130,13 +137,14 @@ local function makeSignatures(text, call, pos) end return function (uri, pos) - local ast = files.getState(uri) - if not ast then + local state = files.getState(uri) + if not state then return nil end local text = files.getText(uri) - pos = lookback.skipSpace(text, pos) - local call = findNearCall(uri, ast, pos) + local offset = guide.positionToOffset(state, pos) + pos = guide.offsetToPosition(state, lookback.skipSpace(text, offset)) + local call = findNearCall(uri, state, pos) if not call then return nil end diff --git a/test/signature/init.lua b/test/signature/init.lua index 27051310..43bce29e 100644 --- a/test/signature/init.lua +++ b/test/signature/init.lua @@ -1,26 +1,25 @@ -local core = require 'core.signature' +local core = require 'core.signature' local files = require 'files' +local catch = require 'catch' rawset(_G, 'TEST', true) function TEST(script) return function (expect) - local pos = script:find('$', 1, true) - 1 - local new_script = script:gsub('%$', '') + local newScript, catched1 = catch(script, '?') + local newExpect, catched2 = catch(expect or '', '!') files.removeAll() - files.setText('', new_script) - local hovers = core('', pos) + files.setText('', newScript) + local hovers = core('', catched1['?'][1][1]) if hovers then assert(expect) local hover = hovers[#hovers] - local label = hover.label:gsub('^[\r\n]*(.-)[\r\n]*$', '%1'):gsub('\r\n', '\n') - expect.label = expect.label:gsub('^[\r\n]*(.-)[\r\n]*$', '%1'):gsub('\r\n', '\n') local arg = hover.params[hover.index].label - assert(expect.label == label) - assert(expect.arg[1] == arg[1]) - assert(expect.arg[2] == arg[2]) + assert(newExpect == hover.label) + assert(catched2['!'][1][1] == arg[1]) + assert(catched2['!'][1][2] == arg[2]) else assert(expect == nil) end @@ -31,93 +30,67 @@ TEST [[ local function x(a, b) end -x($ +x( ]] -{ - label = "function x(a: any, b: any)", - arg = {12, 17}, -} +'function x(, b: any)' TEST [[ local function x(a, b) end -x($) +x() ]] -{ - label = "function x(a: any, b: any)", - arg = {12, 17}, -} +'function x(, b: any)' TEST [[ local function x(a, b) end -x(xxx$) +x(xxx) ]] -{ - label = "function x(a: any, b: any)", - arg = {12, 17}, -} +'function x(, b: any)' TEST [[ local function x(a, b) end -x(xxx, $) +x(xxx, ) ]] -{ - label = "function x(a: any, b: any)", - arg = {20, 25}, -} +'function x(a: any, )' TEST [[ function mt:f(a) end -mt:f($ +mt:f( ]] -{ - label = 'function mt:f(a: any)', - arg = {15, 20}, -} +'function mt:f()' TEST [[ local function x(a, b) return 1 end -x($ +x( ]] -{ - label = "function x(a: any, b: any)", - arg = {12, 17}, -} +'function x(, b: any)' TEST [[ local function x(a, ...) return 1 end -x(1, 2, 3, $ +x(1, 2, 3, ]] -{ - label = "function x(a: any, ...)", - arg = {20, 22}, -} +'function x(a: any, )' TEST [[ -(''):sub($ +(''):sub( ]] -{ - label = [[ -function string:sub(i: integer, j?: integer) -]], - arg = {21, 30}, -} +'function string:sub(, j?: integer)' TEST [[ -(''):sub(1)$ +(''):sub(1) ]] (nil) @@ -125,39 +98,29 @@ TEST [[ local function f(a, b, c) end -f(1, 'string$') +f(1, 'string') ]] -{ - label = [[ -function f(a: any, b: any, c: any) -]], - arg = {20, 25}, -} +'function f(a: any, , c: any)' TEST [[ -pcall(function () $ end) +pcall(function () end) ]] (nil) TEST [[ -table.unpack {$} +table.unpack {} ]] (nil) TEST [[ ---@type fun(x: number, y: number):boolean local zzzz -zzzz($) +zzzz() ]] -{ - label = [[ -function zzzz(x: number, y: number) -]], - arg = {15, 23}, -} +'function zzzz(, y: number)' TEST [[ -('abc'):format(f($)) +('abc'):format(f()) ]] (nil) @@ -166,14 +129,9 @@ function Foo(param01, param02) end -Foo($) +Foo() ]] -{ - label = [[ -function Foo(param01: any, param02: any) -]], - arg = {14, 25}, -} +'function Foo(, param02: any)' TEST [[ function f1(a, b) @@ -182,51 +140,31 @@ end function f2(c, d) end -f2(f1(),$) +f2(f1(),) ]] -{ - label = [[ -function f2(c: any, d: any) -]], - arg = {21, 26}, -} +'function f2(c: any, )' TEST [[ local function f(a, b, c) end -f({},$) +f({},) ]] -{ - label = [[ -function f(a: any, b: any, c: any) -]], - arg = {20, 25}, -} +'function f(a: any, , c: any)' TEST [[ -for _ in pairs($) do +for _ in pairs() do end ]] -{ - label = [[ -function pairs(t: ) -]], - arg = {16, 21}, -} +'function pairs(!>)' TEST [[ function m:f() end -m.f($) +m.f() ]] -{ - label = [[ -function m.f(self: table) -]], - arg = {14, 24}, -} +'function m.f()' TEST [[ ---@alias nnn table @@ -234,59 +172,41 @@ TEST [[ ---@param x nnn local function f(x, y, z) end -f($) +f() ]] -{ - label = [[ -function f(x: table, y: any, z: any) -]], - arg = {12, 35}, -} - +'function f(!>, y: any, z: any)' TEST [[ local function x(a, b) end -x( aaaa $, 2) +x( aaaa , 2) ]] -{ - label = "function x(a: any, b: any)", - arg = {12, 17}, -} +"function x(, b: any)" TEST [[ local function x(a, b) end -x($ aaaa , 2) +x( aaaa , 2) ]] -{ - label = "function x(a: any, b: any)", - arg = {12, 17}, -} +'function x(, b: any)' TEST [[ local function x(a, b) end -x(aaaa ,$ 2) +x(aaaa , 2) ]] -{ - label = "function x(a: any, b: any)", - arg = {20, 25}, -} +'function x(a: any, )' TEST [[ local function x(a, b) end -x(aaaa , 2 $) +x(aaaa , 2 ) ]] -{ - label = "function x(a: any, b: any)", - arg = {20, 25}, -} +'function x(a: any, )' TEST [[ local fooC @@ -298,9 +218,6 @@ function fooC(callback, par) end fooC(function (x, s) -end,$) +end,) ]] -{ - label = 'function fooC(callback: fun(x: number, s: string):nil, par: number)', - arg = {56, 66}, -} +'function fooC(callback: fun(x: number, s: string):nil, )' -- cgit v1.2.3 From 687313e295f299c1e0e410d4d72d96b1f87b681c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 22:07:48 +0800 Subject: update --- script/core/command/autoRequire.lua | 23 +++++++++++++---------- test/command/auto-require.lua | 19 +++++++++++++------ 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/script/core/command/autoRequire.lua b/script/core/command/autoRequire.lua index e784a827..d711fb16 100644 --- a/script/core/command/autoRequire.lua +++ b/script/core/command/autoRequire.lua @@ -4,19 +4,22 @@ local config = require 'config' local rpath = require 'workspace.require-path' local client = require 'client' local lang = require 'language' +local guide = require 'parser.guide' -local function findInsertOffset(uri) +local function findInsertRow(uri) local text = files.getText(uri) + local state = files.getState(uri) + local lines = state.lines local fmt = { pair = false, quot = '"', col = nil, } - for i = 1, #lines do + for i = 0, #lines do local ln = lines[i] - local lnText = text:sub(ln.start, ln.finish) + local lnText = text:match('[^\r\n]*', ln) if not lnText:find('require', 1, true) then - return ln.start, fmt + return i, fmt else local lpPos = lnText:find '%(' if lpPos then @@ -32,7 +35,7 @@ local function findInsertOffset(uri) end end end - return 1, fmt + return 0, fmt end local function askAutoRequire(visiblePaths) @@ -69,7 +72,7 @@ local function askAutoRequire(visiblePaths) return nameMap[result] end -local function applyAutoRequire(uri, offset, name, result, fmt) +local function applyAutoRequire(uri, row, name, result, fmt) local quotedResult = ('%q'):format(result) if fmt.quot == "'" then quotedResult = ([['%s']]):format(quotedResult:sub(2, -2) @@ -87,11 +90,11 @@ local function applyAutoRequire(uri, offset, name, result, fmt) if fmt.col and fmt.col > #text then sp = (' '):rep(fmt.col - #text - 1) end - text = ('\nlocal %s%s= require%s\n'):format(name, sp, quotedResult) + text = ('local %s%s= require%s\n'):format(name, sp, quotedResult) client.editText(uri, { { - start = offset, - finish = offset - 1, + start = guide.positionOf(row, 0), + finish = guide.positionOf(row, 0), text = text, } }) @@ -120,6 +123,6 @@ return function (data) return end - local offset, fmt = findInsertOffset(uri) + local offset, fmt = findInsertRow(uri) applyAutoRequire(uri, offset, name, result, fmt) end diff --git a/test/command/auto-require.lua b/test/command/auto-require.lua index 94bb5069..a52662fb 100644 --- a/test/command/auto-require.lua +++ b/test/command/auto-require.lua @@ -3,7 +3,7 @@ local files = require 'files' local autoRequire = require 'core.command.autoRequire' local client = require 'client' -local findInsertOffset = util.getUpvalue(autoRequire, 'findInsertOffset') +local findInsertRow = util.getUpvalue(autoRequire, 'findInsertRow') local applyAutoRequire = util.getUpvalue(autoRequire, 'applyAutoRequire') local originEditText = client.editText @@ -19,18 +19,25 @@ function TEST(text) files.removeAll() files.setText('', text) EditResult = nil - local offset, fmt = findInsertOffset('') - applyAutoRequire('', offset, name, name, fmt) + local row, fmt = findInsertRow('') + applyAutoRequire('', row, name, name, fmt) assert(util.equal(EditResult, expect)) end end end --- TODO change to position TEST '' 'test' { start = 0, - finish = -1, - text = '\nlocal test = require "test"\n' + finish = 0, + text = 'local test = require "test"\n' +} + +TEST [[ +local aaaaaa = require 'aaa' +]] 'test' { + start = 10000, + finish = 10000, + text = 'local test = require \'test\'\n' } client.editText = originEditText -- cgit v1.2.3 From b6f99a71289f37e3c473a43d0a5290866a0822eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 23:26:28 +0800 Subject: update --- script/core/document-symbol.lua | 14 +- test/document_symbol/init.lua | 286 ++++++++++++++++++++-------------------- 2 files changed, 153 insertions(+), 147 deletions(-) diff --git a/script/core/document-symbol.lua b/script/core/document-symbol.lua index 9f950d25..cfabedab 100644 --- a/script/core/document-symbol.lua +++ b/script/core/document-symbol.lua @@ -5,20 +5,26 @@ local define = require 'proto.define' local util = require 'utility' local function buildName(source, text) + local uri = guide.getUri(source) + local state = files.getState(uri) + local startOffset = guide.positionToOffset(state, source.start) if source.type == 'setmethod' or source.type == 'getmethod' then if source.method then - return text:sub(source.start, source.method.finish) + local finishOffset = guide.positionToOffset(state, source.method.finish) + return text:sub(startOffset + 1, finishOffset) end end if source.type == 'setfield' or source.type == 'tablefield' or source.type == 'getfield' then if source.field then - return text:sub(source.start, source.field.finish) + local finishOffset = guide.positionToOffset(state, source.field.finish) + return text:sub(startOffset + 1, finishOffset) end end - return text:sub(source.start, source.finish) + local finishOffset = guide.positionToOffset(state, source.finish) + return text:sub(startOffset + 1, finishOffset) end local function buildFunctionParams(func) @@ -208,7 +214,7 @@ local function buildAnonymousFunction(source, text, used, symbols) detail = ('%sfunction (%s)'):format(head, buildFunctionParams(source)), kind = define.SymbolKind.Function, range = { source.start, source.finish }, - selectionRange = { source.start, source.start }, + selectionRange = { source.keyword[1], source.keyword[2] }, valueRange = { source.start, source.finish }, } end diff --git a/test/document_symbol/init.lua b/test/document_symbol/init.lua index d745d53f..d3168197 100644 --- a/test/document_symbol/init.lua +++ b/test/document_symbol/init.lua @@ -63,8 +63,8 @@ A = 1 name = 'A', detail = 'global number = 1', kind = define.SymbolKind.Class, - range = {1, 5}, - selectionRange = {1, 1}, + range = {0, 5}, + selectionRange = {0, 1}, } } @@ -77,9 +77,9 @@ end name = 'f', detail = 'function ()', kind = define.SymbolKind.Function, - range = {7, 22}, - selectionRange = {16, 16}, - valueRange = {7, 22}, + range = {6, 10003}, + selectionRange = {15, 16}, + valueRange = {6, 10003}, } } @@ -92,9 +92,9 @@ end name = 'f', detail = 'function ()', kind = define.SymbolKind.Function, - range = {1, 16}, - selectionRange = {10, 10}, - valueRange = {1, 16}, + range = {0, 10003}, + selectionRange = {9, 10}, + valueRange = {0, 10003}, } } @@ -107,9 +107,9 @@ end name = '', detail = 'return function ()', kind = define.SymbolKind.Function, - range = {8, 22}, - selectionRange = {8, 8}, - valueRange = {8, 22}, + range = {7, 10003}, + selectionRange = {7, 15}, + valueRange = {7, 10003}, } } @@ -122,9 +122,9 @@ end name = 'f', detail = 'function ()', kind = define.SymbolKind.Function, - range = {1, 19}, - selectionRange = {1, 1}, - valueRange = {5, 19}, + range = {0, 10003}, + selectionRange = {0, 1}, + valueRange = {4, 10003}, } } @@ -137,9 +137,9 @@ end name = 'f', detail = 'function ()', kind = define.SymbolKind.Function, - range = {7, 25}, - selectionRange = {7, 7}, - valueRange = {11, 25}, + range = {6, 10003}, + selectionRange = {6, 7}, + valueRange = {10, 10003}, } } @@ -152,9 +152,9 @@ end name = 'mt:add', detail = 'function ()', kind = define.SymbolKind.Method, - range = {1, 21}, - selectionRange = {10, 15}, - valueRange = {1, 21}, + range = {0, 10003}, + selectionRange = {9, 15}, + valueRange = {0, 10003}, } } @@ -173,25 +173,25 @@ end name = 'A', detail = 'function ()', kind = define.SymbolKind.Function, - range = {1, 68}, - selectionRange = {10, 10}, - valueRange = {1, 68}, + range = {0, 50003}, + selectionRange = {9, 10}, + valueRange = {0, 50003}, children = { [1] = { name = 'A1', detail = 'function ()', kind = define.SymbolKind.Function, - range = {18, 38}, - selectionRange = {27, 28}, - valueRange = {18, 38}, + range = {10004, 20007}, + selectionRange = {10013, 10015}, + valueRange = {10004, 20007}, }, [2] = { name = 'A2', detail = 'function ()', kind = define.SymbolKind.Function, - range = {44, 64}, - selectionRange = {53, 54}, - valueRange = {44, 64}, + range = {30004, 40007}, + selectionRange = {30013, 30015}, + valueRange = {30004, 40007}, }, }, }, @@ -199,9 +199,9 @@ end name = 'B', detail = 'function ()', kind = define.SymbolKind.Function, - range = {70, 85}, - selectionRange = {79, 79}, - valueRange = {70, 85}, + range = {60000, 70003}, + selectionRange = {60009, 60010}, + valueRange = {60000, 70003}, }, } @@ -220,31 +220,31 @@ local z name = 'x', detail = 'local number = 1', kind = define.SymbolKind.Variable, - range = {7, 11}, - selectionRange = {7, 7}, + range = {6, 11}, + selectionRange = {6, 7}, }, [2] = { name = 'f', detail = 'function ()', kind = define.SymbolKind.Function, - range = {19, 79}, - selectionRange = {28, 28}, - valueRange = {19, 79}, + range = {10006, 50003}, + selectionRange = {10015, 10016}, + valueRange = {10006, 50003}, children = { [1] = { name = 'x', detail = 'local string = "x"', kind = define.SymbolKind.Variable, - range = {42, 48}, - selectionRange = {42, 42}, + range = {20010, 20017}, + selectionRange = {20010, 20011}, }, [2] = { name = 'y', detail = 'local {}', kind = define.SymbolKind.Variable, - range = {60, 65}, - selectionRange = {60, 60}, - valueRange = {64, 65}, + range = {30010, 30016}, + selectionRange = {30010, 30011}, + valueRange = {30014, 30016}, }, --[3] = { -- name = 'z', @@ -260,15 +260,15 @@ local z name = 'y', detail = 'local boolean = true', kind = define.SymbolKind.Variable, - range = {87, 94}, - selectionRange = {87, 87}, + range = {60006, 60014}, + selectionRange = {60006, 60007}, }, [4] = { name = 'z', detail = 'local', kind = define.SymbolKind.Variable, - range = {102, 102}, - selectionRange = {102, 102}, + range = {70006, 70007}, + selectionRange = {70006, 70007}, }, } @@ -284,30 +284,30 @@ local t = { name = 't', detail = 'local {a, b, c}', kind = define.SymbolKind.Variable, - range = {7, 46}, - selectionRange = {7, 7}, - valueRange = {11, 46}, + range = {6, 40001}, + selectionRange = {6, 7}, + valueRange = {10, 40001}, children = { [1] = { name = 'a', detail = 'field number = 1', kind = define.SymbolKind.Property, - range = {17, 21}, - selectionRange = {17, 17}, + range = {10004, 10009}, + selectionRange = {10004, 10005}, }, [2] = { name = 'b', detail = 'field number = 2', kind = define.SymbolKind.Property, - range = {28, 32}, - selectionRange = {28, 28}, + range = {20004, 20009}, + selectionRange = {20004, 20005}, }, [3] = { name = 'c', detail = 'field number = 3', kind = define.SymbolKind.Property, - range = {39, 43}, - selectionRange = {39, 39}, + range = {30004, 30009}, + selectionRange = {30004, 30005}, }, } } @@ -325,24 +325,24 @@ local t = { name = 't', detail = 'local {a}', kind = define.SymbolKind.Variable, - range = {7, 44}, - selectionRange = {7, 7}, - valueRange = {11, 44}, + range = {6, 40001}, + selectionRange = {6, 7}, + valueRange = {10, 40001}, children = { [1] = { name = 'a', detail = 'field {b}', kind = define.SymbolKind.Property, - range = {17, 42}, - selectionRange = {17, 17}, - valueRange = {21, 42}, + range = {10004, 30005}, + selectionRange = {10004, 10005}, + valueRange = {10008, 30005}, children = { [1] = { name = 'b', detail = EXISTS, kind = define.SymbolKind.Property, - range = {31, 35}, - selectionRange = {31, 31}, + range = {20008, 20013}, + selectionRange = {20008, 20009}, } } }, @@ -360,16 +360,16 @@ g = 1 name = 'g', detail = 'function ()', kind = define.SymbolKind.Function, - range = {7, 22}, - selectionRange = {16, 16}, - valueRange = {7, 22}, + range = {6, 10003}, + selectionRange = {15, 16}, + valueRange = {6, 10003}, }, [2] = { name = 'g', detail = 'setlocal number = 1', kind = define.SymbolKind.Variable, - range = {25, 29}, - selectionRange = {25, 25}, + range = {30000, 30005}, + selectionRange = {30000, 30001}, } } @@ -383,30 +383,30 @@ end name = 'f', detail = 'function (a, b, ...)', kind = define.SymbolKind.Function, - range = {1, 58}, - selectionRange = {10, 10}, - valueRange = {1, 58}, + range = {0, 30003}, + selectionRange = {9, 10}, + valueRange = {0, 30003}, children = { [1] = { name = 'a', detail = 'param', kind = define.SymbolKind.Constant, - range = {12, 12}, - selectionRange = {12, 12}, + range = {11, 12}, + selectionRange = {11, 12}, }, [2] = { name = 'b', detail = 'param', kind = define.SymbolKind.Constant, - range = {15, 15}, - selectionRange = {15, 15}, + range = {14, 15}, + selectionRange = {14, 15}, }, [3] = { name = 'x', detail = 'local', kind = define.SymbolKind.Variable, - range = {33, 39}, - selectionRange = {33, 33}, + range = {10010, 10017}, + selectionRange = {10010, 10011}, } } }, @@ -424,17 +424,17 @@ local v = t name = 't', detail = 'local {a, b}', kind = define.SymbolKind.Variable, - range = {7, 35}, - selectionRange = {7, 7}, - valueRange = {11, 35}, + range = {6, 30001}, + selectionRange = {6, 7}, + valueRange = {10, 30001}, children = EXISTS, }, [2] = { name = 'v', detail = 'local', kind = define.SymbolKind.Variable, - range = {44, 48}, - selectionRange = {44, 44}, + range = {50006, 50011}, + selectionRange = {50006, 50007}, }, } @@ -446,47 +446,47 @@ local function name = 'x', detail = 'local', kind = define.SymbolKind.Variable, - range = {7, 7}, - selectionRange = {7, 7}, + range = {6, 7}, + selectionRange = {6, 7}, }, [2] = { name = "", detail = "function ()", kind = 12, - range = {15, 22}, - selectionRange = {15, 15}, - valueRange = {15, 22}, + range = {10006, 10014}, + selectionRange = {10006, 10014}, + valueRange = {10006, 10014}, }, } TEST [[ local a, b = { - x = 1, - y = 1, - z = 1, + x1 = 1, + y1 = 1, + z1 = 1, }, { - x = 1, - y = 1, - z = 1, + x2 = 1, + y2= 1, + z2 = 1, } ]]{ [1] = { name = 'a', - detail = 'local {x, y, z}', + detail = 'local {x1, y1, z1}', kind = define.SymbolKind.Variable, - range = {7, 49}, - selectionRange = {7, 7}, - valueRange = {14, 49}, + range = {6, 40001}, + selectionRange = {6, 7}, + valueRange = {13, 40001}, children = EXISTS, }, [2] = { name = 'b', - detail = 'local {x, y, z}', + detail = 'local {x2, y2, z2}', kind = define.SymbolKind.Variable, - range = {10, 87}, - selectionRange = {10, 10}, - valueRange = {52, 87}, + range = {9, 80001}, + selectionRange = {9, 10}, + valueRange = {40003, 80001}, children = EXISTS, } } @@ -504,24 +504,24 @@ end name = 'x', detail = 'function ()', kind = define.SymbolKind.Function, - range = {7, 22}, - selectionRange = {16, 16}, - valueRange = {7, 22}, + range = {6, 10003}, + selectionRange = {15, 16}, + valueRange = {6, 10003}, }, [2] = { name = 'f', detail = 'function ()', kind = define.SymbolKind.Function, - range = {31, 58}, - selectionRange = {40, 40}, - valueRange = {31, 58}, + range = {30006, 50003}, + selectionRange = {30015, 30016}, + valueRange = {30006, 50003}, children = { [1] = { name = 'c', detail = 'local', kind = define.SymbolKind.Variable, - range = {54, 54}, - selectionRange = {54, 54}, + range = {40010, 40011}, + selectionRange = {40010, 40011}, }, }, } @@ -537,16 +537,16 @@ local t = f({ name = 't', detail = 'local', kind = define.SymbolKind.Variable, - range = {7, 26}, - selectionRange = {7, 7}, - valueRange = {11, 26}, + range = {6, 20002}, + selectionRange = {6, 7}, + valueRange = {10, 20002}, children = { [1] = { name = 'k', detail = 'field number = 1', kind = define.SymbolKind.Property, - range = {19, 23}, - selectionRange = {19, 19}, + range = {10004, 10009}, + selectionRange = {10004, 10005}, } } } @@ -563,31 +563,31 @@ end name = 't', detail = 'local {}', kind = define.SymbolKind.Variable, - range = {7, 12}, - selectionRange = {7, 7}, - valueRange = {11, 12}, + range = {6, 12}, + selectionRange = {6, 7}, + valueRange = {10, 12}, }, [2] = { name = 'f', detail = 'function (a, b)', kind = define.SymbolKind.Function, - range = {21, 40}, - selectionRange = {30, 30}, - valueRange = {21, 40}, + range = {20006, 30003}, + selectionRange = {20015, 20016}, + valueRange = {20006, 30003}, children = { [1] = { name = 'a', detail = 'param', kind = define.SymbolKind.Constant, - range = {32, 32}, - selectionRange = {32, 32}, + range = {20017, 20018}, + selectionRange = {20017, 20018}, }, [2] = { name = 'b', detail = 'param', kind = define.SymbolKind.Constant, - range = {35, 35}, - selectionRange = {35, 35}, + range = {20020, 20021}, + selectionRange = {20020, 20021}, } } } @@ -604,17 +604,17 @@ local a = f { name = 'a', detail = 'local', kind = define.SymbolKind.Variable, - range = {7, 43}, - selectionRange = {7, 7}, - valueRange = {11, 43}, + range = {6, 30001}, + selectionRange = {6, 7}, + valueRange = {10, 30001}, children = { [1] = { name = 'x', detail = 'function ()', kind = define.SymbolKind.Function, - range = {19, 41}, - selectionRange = {19, 19}, - valueRange = {23, 41}, + range = {10004, 20007}, + selectionRange = {10004, 10005}, + valueRange = {10008, 20007}, } } } @@ -630,9 +630,9 @@ end) name = '', detail = 'table.sort -> function (a, b)', kind = define.SymbolKind.Function, - range = {15, 50}, - selectionRange = {15, 15}, - valueRange = {15, 50}, + range = {14, 20003}, + selectionRange = {14, 22}, + valueRange = {14, 20003}, children = EXISTS, } } @@ -643,32 +643,32 @@ local root = { local function function_inside_function() end end - } +} ]] { [1] = { name = 'root', detail = 'local {inner_function}', kind = define.SymbolKind.Variable, - range = {7, 123}, - selectionRange = {7, 10}, - valueRange = {14, 123}, + range = {6, 50001}, + selectionRange = {6, 10}, + valueRange = {13, 50001}, children = { [1] = { name = 'inner_function', detail = 'function ()', kind = define.SymbolKind.Function, - range = {20, 117}, - selectionRange = {20, 33}, - valueRange = {37, 117}, + range = {10004, 40007}, + selectionRange = {10004, 10018}, + valueRange = {10021, 40007}, children = { [1] = { name = 'function_inside_function', detail = 'function ()', kind = define.SymbolKind.Function, - range = {63, 109}, - selectionRange = {72, 95}, - valueRange = {63, 109}, + range = {20014, 30011}, + selectionRange = {20023, 20047}, + valueRange = {20014, 30011}, }, }, }, -- cgit v1.2.3 From c2a8838012780eb57fa7de36ae0cfa6fd4388b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Wed, 22 Sep 2021 23:44:21 +0800 Subject: update --- script/core/code-action.lua | 52 +++++++++++++++++++++++++++++++-------------- test/code_action/init.lua | 10 ++++----- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/script/core/code-action.lua b/script/core/code-action.lua index ce71f4af..5c8f1634 100644 --- a/script/core/code-action.lua +++ b/script/core/code-action.lua @@ -194,8 +194,13 @@ local function solveSyntaxByAddDoEnd(uri, err, results) [uri] = { { start = err.start, + finish = err.start, + newText = 'do ', + }, + { + start = err.finish, finish = err.finish, - newText = ('do %s end'):format(text:sub(err.start, err.finish)), + newText = ' end', }, } } @@ -262,7 +267,7 @@ local function solveSyntax(uri, diag, results) end local function solveNewlineCall(uri, diag, results) - local start = files.unrange(uri, diag.range) + local start = files.unrange(uri, diag.range) results[#results+1] = { title = lang.script.ACTION_ADD_SEMICOLON, kind = 'quickfix', @@ -346,18 +351,18 @@ local function checkQuickFix(results, uri, start, diagnostics) end local function checkSwapParams(results, uri, start, finish) - local ast = files.getState(uri) - local text = files.getText(uri) - if not ast then + local state = files.getState(uri) + local text = files.getText(uri) + if not state then return end local args = {} - guide.eachSourceBetween(ast.ast, start, finish, function (source) + guide.eachSourceBetween(state.ast, start, finish, function (source) if source.type == 'callargs' or source.type == 'funcargs' then local targetIndex for index, arg in ipairs(source) do - if arg.start - 1 <= finish and arg.finish >= start then + if arg.start <= finish and arg.finish >= start then -- should select only one param if targetIndex then return @@ -370,11 +375,17 @@ local function checkSwapParams(results, uri, start, finish) end local node if source.type == 'callargs' then - node = text:sub(source.parent.node.start, source.parent.node.finish) + node = text:sub( + guide.positionToOffset(state, source.parent.node.start) + 1, + guide.positionToOffset(state, source.parent.node.finish) + ) elseif source.type == 'funcargs' then local var = source.parent.parent if guide.isSet(var) then - node = text:sub(var.start, var.finish) + node = text:sub( + guide.positionToOffset(state, var.start) + 1, + guide.positionToOffset(state, var.finish) + ) else node = lang.script.SYMBOL_ANONYMOUS end @@ -408,12 +419,18 @@ local function checkSwapParams(results, uri, start, finish) { start = myArg.start, finish = myArg.finish, - newText = text:sub(targetArg.start, targetArg.finish), + newText = text:sub( + guide.positionToOffset(state, targetArg.start) + 1, + guide.positionToOffset(state, targetArg.finish) + ), }, { start = targetArg.start, finish = targetArg.finish, - newText = text:sub(myArg.start, myArg.finish), + newText = text:sub( + guide.positionToOffset(state, myArg.start) + 1, + guide.positionToOffset(state, myArg.finish) + ), }, } } @@ -496,13 +513,16 @@ end --end local function checkJsonToLua(results, uri, start, finish) - local text = files.getText(uri) - local jsonStart = text:match ('()[%{%[]', start) + local text = files.getText(uri) + local state = files.getState(uri) + local startOffset = guide.positionToOffset(state, start) + local finishOffset = guide.positionToOffset(state, finish) + local jsonStart = text:match ('()[%{%[]', startOffset + 1) if not jsonStart then return end local jsonFinish - for i = math.min(finish, #text), jsonStart + 1, -1 do + for i = math.min(finishOffset, #text), jsonStart + 1, -1 do local char = text:sub(i, i) if char == ']' or char == '}' then @@ -525,8 +545,8 @@ local function checkJsonToLua(results, uri, start, finish) arguments = { { uri = uri, - start = jsonStart, - finish = jsonFinish, + start = guide.offsetToPosition(state, jsonStart) - 1, + finish = guide.offsetToPosition(state, jsonFinish), } } }, diff --git a/test/code_action/init.lua b/test/code_action/init.lua index 11ce6ec7..70d8c9ec 100644 --- a/test/code_action/init.lua +++ b/test/code_action/init.lua @@ -1,6 +1,7 @@ local core = require 'core.code-action' local files = require 'files' local lang = require 'language' +local catch = require 'catch' rawset(_G, 'TEST', true) @@ -38,11 +39,10 @@ end function TEST(script) return function (expect) files.removeAll() - local start = script:find('', 1, true) - local new_script = script:gsub('<[!?]', ' '):gsub('[!?]>', ' ') - files.setText('', new_script) - local results = core('', start, finish) + + local newScript, catched = catch(script, '?') + files.setText('', newScript) + local results = core('', catched['?'][1][1], catched['?'][1][2]) assert(results) assert(eq(expect, results)) end -- cgit v1.2.3 From 0a60aa17c240d4fb080b091891f659a9d74aeffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 00:00:30 +0800 Subject: update --- script/files.lua | 107 -------------------------------------------------- test.lua | 2 +- test/full/example.lua | 14 +++---- test/full/init.lua | 7 ++-- 4 files changed, 10 insertions(+), 120 deletions(-) diff --git a/script/files.lua b/script/files.lua index 25f07ca2..e0c0dccb 100644 --- a/script/files.lua +++ b/script/files.lua @@ -202,8 +202,6 @@ function m.setRawText(uri, text) local file = m.fileMap[uri] file.text = text file.originText = text - m.linesMap[uri] = nil - m.originLinesMap[uri] = nil m.astMap[uri] = nil end @@ -317,8 +315,6 @@ function m.remove(uri) end m.fileMap[uri] = nil m.astMap[uri] = nil - m.linesMap[uri] = nil - m.originLinesMap[uri] = nil m._pairsCache = nil m.flushFileCache(uri) @@ -549,109 +545,6 @@ end ---@alias position table ---- 获取 position 对应的光标位置 ----@param uri uri ----@param position position ----@param isFinish? boolean ----@return integer -function m.offset(uri, position, isFinish) - local file = m.getFile(uri) - local lines = m.getLines(uri) - local text = m.getText(uri) - if not file then - return 0 - end - if file._diffInfo then - lines = m.getOriginLines(uri) - text = m.getOriginText(uri) - end - local row = position.line + 1 - local start, finish, char - if row > #lines then - start, finish = guide.lineRange(lines, #lines) - start = start + 1 - char = util.utf8Len(text, start, finish) - else - start, finish = guide.lineRange(lines, row) - start = start + 1 - char = position.character - end - local utf8Len = util.utf8Len(text, start, finish) - local offset - if char <= 0 then - offset = start - else - if char >= utf8Len then - char = utf8Len - end - local left = utf8.offset(text, char, start) - local right = utf8.offset(text, char + 1, start) - if isFinish then - offset = left - else - offset = right - end - end - if file._diffInfo then - local start, finish = smerger.getOffset(file._diffInfo, offset) - if isFinish then - offset = finish - else - offset = start - end - end - return offset -end - ---- 获取 position 对应的光标位置(根据附近的单词) ----@param uri uri ----@param position position ----@return integer -function m.offsetOfWord(uri, position) - local file = m.getFile(uri) - local lines = m.getLines(uri) - local text = m.getText(uri) - if not file then - return 0 - end - if file._diffInfo then - lines = m.getOriginLines(uri) - text = m.getOriginText(uri) - end - local row = position.line + 1 - local start, finish, char - if row > #lines then - start, finish = guide.lineRange(lines, #lines) - start = start + 1 - char = util.utf8Len(text, start, finish) - else - start, finish = guide.lineRange(lines, row) - start = start + 1 - char = position.character - end - local utf8Len = util.utf8Len(text, start, finish) - local offset - if char <= 0 then - offset = start - else - if char >= utf8Len then - char = utf8Len - end - local left = utf8.offset(text, char, start) - local right = utf8.offset(text, char + 1, start) - if isNameChar(text:sub(left, right - 1)) - and not isNameChar(text:sub(right, right)) then - offset = left - else - offset = right - end - end - if file._diffInfo then - offset = smerger.getOffset(file._diffInfo, offset) - end - return offset -end - --- 将应用差异前的offset转换为应用差异后的offset ---@param uri uri ---@param offset integer diff --git a/test.lua b/test.lua index d2e2c38a..f0e905b9 100644 --- a/test.lua +++ b/test.lua @@ -77,7 +77,7 @@ local function testAll() test 'command' test 'document_symbol' test 'code_action' - test 'type_formatting' + --test 'type_formatting' --test 'other' end diff --git a/test/full/example.lua b/test/full/example.lua index 5596233e..20de5528 100644 --- a/test/full/example.lua +++ b/test/full/example.lua @@ -12,26 +12,24 @@ local function testIfExit(path) config.set('Lua.workspace.preloadFileSize', 1000000000) local buf = util.loadFile(path:string()) if buf then - local vm + local state local clock = os.clock() local max = 1 local need - local parseClock = 0 local compileClock = 0 local luadocClock = 0 local noderClock = 0 local total for i = 1, max do - vm = TEST(buf) + state = TEST(buf) local luadocStart = os.clock() - luadoc(nil, vm) + luadoc(state) local luadocPassed = os.clock() - luadocStart local passed = os.clock() - clock local noderStart = os.clock() local noderPassed = os.clock() - noderStart - parseClock = parseClock + vm.parseClock - compileClock = compileClock + vm.compileClock + compileClock = compileClock + state.compileClock luadocClock = luadocClock + luadocPassed noderClock = noderClock + noderPassed if passed >= 1.0 or i == max then @@ -40,10 +38,9 @@ local function testIfExit(path) break end end - print(('基准编译测试[%s]单次耗时:%.10f(解析:%.10f, 编译:%.10f, LuaDoc: %.10f, Noder: %.10f)'):format( + print(('基准编译测试[%s]单次耗时:%.10f(解析:%.10f, LuaDoc: %.10f, Noder: %.10f)'):format( path:filename():string(), need, - parseClock / total, compileClock / total, luadocClock / total, noderClock / total @@ -52,7 +49,6 @@ local function testIfExit(path) local clock = os.clock() local max = 100 local need - local lines = parser:lines(buf) for i = 1, max do files.removeAll() files.open('') diff --git a/test/full/init.lua b/test/full/init.lua index 89d9b8b3..9584db6f 100644 --- a/test/full/init.lua +++ b/test/full/init.lua @@ -5,9 +5,10 @@ local util = require 'utility' rawset(_G, 'TEST', true) function TEST(script) - local ast = parser:compile(script, 'lua', 'Lua 5.3') - assert(ast) - return ast + local clock = os.clock() + local state = parser.compile(script, 'Lua', 'Lua 5.3') + state.compileClock = os.clock() - clock + return state end local function startCollectDiagTimes() -- cgit v1.2.3 From 5c9b1b467af1636ea21a9bd3d398e220790eea54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 15:00:50 +0800 Subject: cleanup --- script/core/code-action.lua | 21 ++++++++-------- script/core/command/solve.lua | 12 ++++----- script/core/semantic-tokens.lua | 5 ++-- script/files.lua | 5 ++-- script/proto/converter.lua | 50 ++++++++++++++++++++++++++++++++++++ script/provider/provider.lua | 56 ++++++++++++++++++++--------------------- 6 files changed, 100 insertions(+), 49 deletions(-) create mode 100644 script/proto/converter.lua diff --git a/script/core/code-action.lua b/script/core/code-action.lua index 5c8f1634..2bc6ae50 100644 --- a/script/core/code-action.lua +++ b/script/core/code-action.lua @@ -1,8 +1,9 @@ -local files = require 'files' -local lang = require 'language' -local util = require 'utility' -local sp = require 'bee.subprocess' -local guide = require "parser.guide" +local files = require 'files' +local lang = require 'language' +local util = require 'utility' +local sp = require 'bee.subprocess' +local guide = require "parser.guide" +local converter = require 'proto.converter' local function checkDisableByLuaDocExits(uri, row, mode, code) local ast = files.getState(uri) @@ -131,8 +132,8 @@ end local function solveUndefinedGlobal(uri, diag, results) local ast = files.getState(uri) - local offset = files.offsetOfWord(uri, diag.range.start) - guide.eachSourceContain(ast.ast, offset, function (source) + local start = converter.unpackRange(uri, diag.range) + guide.eachSourceContain(ast.ast, start, function (source) if source.type ~= 'getglobal' then return end @@ -150,8 +151,8 @@ end local function solveLowercaseGlobal(uri, diag, results) local ast = files.getState(uri) - local offset = files.offsetOfWord(uri, diag.range.start) - guide.eachSourceContain(ast.ast, offset, function (source) + local start = converter.unpackRange(uri, diag.range) + guide.eachSourceContain(ast.ast, start, function (source) if source.type ~= 'setglobal' then return end @@ -267,7 +268,7 @@ local function solveSyntax(uri, diag, results) end local function solveNewlineCall(uri, diag, results) - local start = files.unrange(uri, diag.range) + local start = converter.unpackRange(uri, diag.range) results[#results+1] = { title = lang.script.ACTION_ADD_SEMICOLON, kind = 'quickfix', diff --git a/script/core/command/solve.lua b/script/core/command/solve.lua index a493de24..790adbee 100644 --- a/script/core/command/solve.lua +++ b/script/core/command/solve.lua @@ -1,7 +1,8 @@ -local files = require 'files' -local guide = require 'parser.guide' -local proto = require 'proto' -local lang = require 'language' +local files = require 'files' +local guide = require 'parser.guide' +local proto = require 'proto' +local lang = require 'language' +local converter = require 'proto.converter' local opMap = { ['+'] = true, @@ -34,8 +35,7 @@ return function (data) return end - local start = files.offsetOfWord(uri, data.range.start) - local finish = files.offsetOfWord(uri, data.range['end']) + local start, finish = converter.unpackRange(uri, data.range) local result = guide.eachSourceContain(ast.ast, start, function (source) if source.start ~= start diff --git a/script/core/semantic-tokens.lua b/script/core/semantic-tokens.lua index 238df862..405f2735 100644 --- a/script/core/semantic-tokens.lua +++ b/script/core/semantic-tokens.lua @@ -5,6 +5,7 @@ local define = require 'proto.define' local vm = require 'vm' local util = require 'utility' local guide = require 'parser.guide' +local converter = require 'proto.converter' local Care = {} Care['setglobal'] = function (source, results) @@ -188,8 +189,8 @@ local function buildTokens(uri, results) local lastLine = 0 local lastStartChar = 0 for i, source in ipairs(results) do - local startPos = files.position(uri, source.start, 'left') - local finishPos = files.position(uri, source.finish, 'right') + local startPos = converter.packPosition(uri, source.start) + local finishPos = converter.packPosition(uri, source.finish) local line = startPos.line local startChar = startPos.character local deltaLine = line - lastLine diff --git a/script/files.lua b/script/files.lua index e0c0dccb..d6ea057f 100644 --- a/script/files.lua +++ b/script/files.lua @@ -518,6 +518,7 @@ function m.getVisibles(uri) end local visibles = {} for i, range in ipairs(ranges) do + -- TODO 改成行号 local start, finish = m.unrange(uri, range) visibles[i] = { start = start, @@ -543,8 +544,6 @@ local function isNameChar(text) return false end ----@alias position table - --- 将应用差异前的offset转换为应用差异后的offset ---@param uri uri ---@param offset integer @@ -626,7 +625,7 @@ function m.position(uri, offset, leftOrRight) end --- 将起点与终点位置转化为 range ----@alias range table + ---@param uri uri ---@param offset1 integer ---@param offset2 integer diff --git a/script/proto/converter.lua b/script/proto/converter.lua new file mode 100644 index 00000000..4b4b9f5d --- /dev/null +++ b/script/proto/converter.lua @@ -0,0 +1,50 @@ +local guide = require 'parser.guide' + +local m = {} + + +---@alias position {line: integer, character: integer} + +---@param uri uri +---@param pos integer +---@return position +function m.packPosition(uri, pos) + local row, col = guide.rowColOf(pos) + return { + line = row, + character = col, + } +end + +---@param uri uri +---@param position position +function m.unpackPosition(uri, position) + local pos = guide.positionOf(position.line, position.character) + return pos +end + +---@alias range {start: position, end: position} + +---@param uri uri +---@param start integer +---@param finish integer +---@return range +function m.packRange(uri, start, finish) + local range = { + start = m.packPosition(uri, start), + ['end'] = m.packPosition(uri, finish), + } + return range +end + +---@param uri uri +---@param range range +---@return integer start +---@return integer finish +function m.unpackRange(uri, range) + local start = m.unpackPosition(uri, range.start) + local finish = m.unpackPosition(uri, range['end']) + return start, finish +end + +return m diff --git a/script/provider/provider.lua b/script/provider/provider.lua index e1bd0f4f..d4bf0bee 100644 --- a/script/provider/provider.lua +++ b/script/provider/provider.lua @@ -13,6 +13,7 @@ local lang = require 'language' local progress = require 'progress' local tm = require 'text-merger' local cfgLoader = require 'config.loader' +local converter = require 'proto.converter' local function updateConfig() local new @@ -183,8 +184,8 @@ proto.on('textDocument/hover', function (params) if not files.exists(uri) then return nil end - local offset = files.offsetOfWord(uri, params.position) - local hover, source = core.byUri(uri, offset) + local pos = converter.unpackPosition(uri, params.position) + local hover, source = core.byUri(uri, pos) if not hover then return nil end @@ -205,8 +206,8 @@ proto.on('textDocument/definition', function (params) if not files.exists(uri) then return nil end - local offset = files.offsetOfWord(uri, params.position) - local result = core(uri, offset) + local pos = converter.unpackPosition(uri, params.position) + local result = core(uri, pos) if not result then return nil end @@ -240,8 +241,8 @@ proto.on('textDocument/typeDefinition', function (params) if not files.exists(uri) then return nil end - local offset = files.offsetOfWord(uri, params.position) - local result = core(uri, offset) + local pos = converter.unpackPosition(uri, params.position) + local result = core(uri, pos) if not result then return nil end @@ -275,8 +276,8 @@ proto.on('textDocument/references', function (params) if not files.exists(uri) then return nil end - local offset = files.offsetOfWord(uri, params.position) - local result = core(uri, offset) + local pos = converter.unpackPosition(uri, params.position) + local result = core(uri, pos) if not result then return nil end @@ -296,8 +297,8 @@ proto.on('textDocument/documentHighlight', function (params) if not files.exists(uri) then return nil end - local offset = files.offsetOfWord(uri, params.position) - local result = core(uri, offset) + local pos = converter.unpackPosition(uri, params.position) + local result = core(uri, pos) if not result then return nil end @@ -319,8 +320,8 @@ proto.on('textDocument/rename', function (params) if not files.exists(uri) then return nil end - local offset = files.offsetOfWord(uri, params.position) - local result = core.rename(uri, offset, params.newName) + local pos = converter.unpackPosition(uri, params.position) + local result = core.rename(uri, pos, params.newName) if not result then return nil end @@ -344,8 +345,8 @@ proto.on('textDocument/prepareRename', function (params) if not files.exists(uri) then return nil end - local offset = files.offsetOfWord(uri, params.position) - local result = core.prepareRename(uri, offset) + local pos = converter.unpackPosition(uri, params.position) + local result = core.prepareRename(uri, pos) if not result then return nil end @@ -391,8 +392,8 @@ proto.on('textDocument/completion', function (params) end await.setPriority(1000) local clock = os.clock() - local offset = files.offset(uri, params.position) - local result = core.completion(uri, offset - 1, triggerCharacter) + local pos = converter.unpackPosition(uri, params.position) + local result = core.completion(uri, pos, triggerCharacter) local passed = os.clock() - clock if passed > 0.1 then log.warn(('Completion takes %.3f sec.'):format(passed)) @@ -517,9 +518,9 @@ proto.on('textDocument/signatureHelp', function (params) end await.close('signatureHelp') await.setID('signatureHelp') - local offset = files.offset(uri, params.position) + local pos = converter.unpackPosition(uri, params.position) local core = require 'core.signature' - local results = core(uri, offset - 1) + local results = core(uri, pos) if not results then return nil end @@ -599,7 +600,7 @@ proto.on('textDocument/codeAction', function (params) return nil end - local start, finish = files.unrange(uri, range) + local start, finish = converter.unpackRange(uri, range) local results = core(uri, start, finish, diagnostics) if not results or #results == 0 then @@ -705,8 +706,7 @@ proto.on('textDocument/semanticTokens/range', function (params) start = 0 finish = #files.getText(uri) else - start = files.offsetOfWord(uri, params.range.start) - finish = files.offsetOfWord(uri, params.range['end']) + start, finish = converter.unpackRange(uri, params.range) end local results = core(uri, start, finish) return { @@ -729,8 +729,8 @@ proto.on('textDocument/foldingRange', function (params) local results = {} for _, region in ipairs(regions) do - local startLine = files.position(uri, region.start, 'left').line - local endLine = files.position(uri, region.finish, 'right').line + local startLine = converter.packPosition(uri, region.start).line + local endLine = converter.packPosition(uri, region.finish).line if not region.hideLastLine then endLine = endLine - 1 end @@ -778,8 +778,8 @@ proto.on('textDocument/onTypeFormatting', function (params) return nil end local core = require 'core.type-formatting' - local offset = files.offset(uri, params.position) - local edits = core(uri, offset - 1, ch) + local pos = converter.unpackPosition(uri, params.position) + local edits = core(uri, pos, ch) if not edits or #edits == 0 then return nil end @@ -804,13 +804,13 @@ proto.on('$/requestHint', function (params) end workspace.awaitReady() local uri = params.textDocument.uri - local start, finish = files.unrange(uri, params.range) + local start, finish = converter.unpackRange(uri, params.range) local results = core(uri, start, finish) local hintResults = {} for i, res in ipairs(results) do hintResults[i] = { text = res.text, - pos = files.position(uri, res.offset, res.where), + pos = converter.packPosition(uri, res.offset), kind = res.kind, } end @@ -840,7 +840,7 @@ do for _, edit in ipairs(piece) do edits[#edits+1] = { text = edit.text, - pos = files.position(uri, edit.offset, edit.where), + pos = converter.packPosition(uri, edit.offset), } end end -- cgit v1.2.3 From 466874e8a8e360634833a07508fb48131530b704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 16:02:08 +0800 Subject: cleanup --- script/brave/work.lua | 2 +- script/client.lua | 3 ++- script/core/code-action.lua | 2 +- script/core/command/jsonToLua.lua | 15 ++++++------- script/core/command/removeSpace.lua | 11 +++++----- script/core/command/solve.lua | 2 +- script/core/noder.lua | 2 +- script/provider/diagnostic.lua | 31 ++++++++++++++------------- script/provider/provider.lua | 42 ++++++++++++++++++------------------- 9 files changed, 57 insertions(+), 53 deletions(-) diff --git a/script/brave/work.lua b/script/brave/work.lua index ee7b4acd..7af36fda 100644 --- a/script/brave/work.lua +++ b/script/brave/work.lua @@ -26,7 +26,7 @@ brave.on('timer', function (time) end) brave.on('compile', function (text) - local state, err = parser.compile(text, 'lua', 'Lua 5.4') + local state, err = parser.compile(text, 'Lua', 'Lua 5.4') if not state then log.error(err) return diff --git a/script/client.lua b/script/client.lua index c22b59ab..c539a0f7 100644 --- a/script/client.lua +++ b/script/client.lua @@ -4,6 +4,7 @@ local lang = require 'language' local proto = require 'proto' local define = require 'proto.define' local config = require 'config' +local converter = require 'proto.converter' local m = {} @@ -223,7 +224,7 @@ function m.editText(uri, edits) local files = require 'files' local textEdits = {} for i, edit in ipairs(edits) do - textEdits[i] = define.textEdit(files.range(uri, edit.start, edit.finish), edit.text) + textEdits[i] = define.textEdit(converter.packRange(uri, edit.start, edit.finish), edit.text) end proto.request('workspace/applyEdit', { edit = { diff --git a/script/core/code-action.lua b/script/core/code-action.lua index 2bc6ae50..40aef8fc 100644 --- a/script/core/code-action.lua +++ b/script/core/code-action.lua @@ -166,7 +166,7 @@ local function findSyntax(uri, diag) local ast = files.getState(uri) for _, err in ipairs(ast.errs) do if err.type:lower():gsub('_', '-') == diag.code then - local range = files.range(uri, err.start, err.finish) + local range = converter.packRange(uri, err.start, err.finish) if util.equal(range, diag.range) then return err end diff --git a/script/core/command/jsonToLua.lua b/script/core/command/jsonToLua.lua index c4f001ff..8a493b5e 100644 --- a/script/core/command/jsonToLua.lua +++ b/script/core/command/jsonToLua.lua @@ -1,9 +1,10 @@ -local files = require 'files' -local json = require 'json' -local util = require 'utility' -local proto = require 'proto' -local define = require 'proto.define' -local lang = require 'language' +local files = require 'files' +local json = require 'json' +local util = require 'utility' +local proto = require 'proto' +local define = require 'proto.define' +local lang = require 'language' +local converter = require 'proto.converter' return function (data) local text = files.getText(data.uri) @@ -26,7 +27,7 @@ return function (data) changes = { [data.uri] = { { - range = files.range(data.uri, data.start, data.finish), + range = converter.packRange(data.uri, data.start, data.finish), newText = luaStr, } } diff --git a/script/core/command/removeSpace.lua b/script/core/command/removeSpace.lua index 34c74ce0..3d7795a1 100644 --- a/script/core/command/removeSpace.lua +++ b/script/core/command/removeSpace.lua @@ -1,7 +1,8 @@ -local files = require 'files' -local guide = require 'parser.guide' -local proto = require 'proto' -local lang = require 'language' +local files = require 'files' +local guide = require 'parser.guide' +local proto = require 'proto' +local lang = require 'language' +local converter = require 'proto.converter' local function isInString(ast, offset) return guide.eachSourceContain(ast.ast, offset, function (source) @@ -30,7 +31,7 @@ return function (data) goto NEXT_LINE end textEdit[#textEdit+1] = { - range = files.range(uri, start, finish), + range = converter.packRange(uri, start, finish), newText = '', } goto NEXT_LINE diff --git a/script/core/command/solve.lua b/script/core/command/solve.lua index 790adbee..9428d065 100644 --- a/script/core/command/solve.lua +++ b/script/core/command/solve.lua @@ -85,7 +85,7 @@ return function (data) changes = { [uri] = { { - range = files.range(uri, result.start, result.finish), + range = converter.packRange(uri, result.start, result.finish), newText = ('(%s)'):format(text:sub(result.start, result.finish)), } }, diff --git a/script/core/noder.lua b/script/core/noder.lua index 1107dcda..177a151c 100644 --- a/script/core/noder.lua +++ b/script/core/noder.lua @@ -1337,7 +1337,7 @@ function m.compileNode(noders, source) local id = getID(source) bindValue(noders, source, id) - if specialMap[source.special] then + if id and specialMap[source.special] then noders.skip[id] = true end diff --git a/script/provider/diagnostic.lua b/script/provider/diagnostic.lua index db377ea0..ec579428 100644 --- a/script/provider/diagnostic.lua +++ b/script/provider/diagnostic.lua @@ -1,14 +1,15 @@ -local await = require 'await' -local proto = require 'proto.proto' -local define = require 'proto.define' -local lang = require 'language' -local files = require 'files' -local config = require 'config' -local core = require 'core.diagnostics' -local util = require 'utility' -local ws = require 'workspace' -local progress = require "progress" -local client = require 'client' +local await = require 'await' +local proto = require 'proto.proto' +local define = require 'proto.define' +local lang = require 'language' +local files = require 'files' +local config = require 'config' +local core = require 'core.diagnostics' +local util = require 'utility' +local ws = require 'workspace' +local progress = require "progress" +local client = require 'client' +local converter = require 'proto.converter' local m = {} m._start = false @@ -48,14 +49,14 @@ local function buildSyntaxError(uri, err) local relUri = rel.uri relatedInformation[#relatedInformation+1] = { message = rmessage, - location = define.location(relUri, files.range(relUri, rel.start, rel.finish)), + location = define.location(relUri, converter.packRange(relUri, rel.start, rel.finish)), } end end return { code = err.type:lower():gsub('_', '-'), - range = files.range(uri, err.start, err.finish), + range = converter.packRange(uri, err.start, err.finish), severity = define.DiagnosticSeverity.Error, source = lang.script.DIAG_SYNTAX_CHECK, message = message, @@ -75,13 +76,13 @@ local function buildDiagnostic(uri, diag) local rtext = files.getText(rel.uri) relatedInformation[#relatedInformation+1] = { message = rel.message or rtext:sub(rel.start, rel.finish), - location = define.location(rel.uri, files.range(rel.uri, rel.start, rel.finish)) + location = define.location(rel.uri, converter.packRange(rel.uri, rel.start, rel.finish)) } end end return { - range = files.range(uri, diag.start, diag.finish), + range = converter.packRange(uri, diag.start, diag.finish), source = lang.script.DIAG_DIAGNOSTICS, severity = diag.level, message = diag.message, diff --git a/script/provider/provider.lua b/script/provider/provider.lua index d4bf0bee..af62372b 100644 --- a/script/provider/provider.lua +++ b/script/provider/provider.lua @@ -194,7 +194,7 @@ proto.on('textDocument/hover', function (params) value = tostring(hover), kind = 'markdown', }, - range = files.range(uri, source.start, source.finish), + range = converter.packRange(uri, source.start, source.finish), } end) @@ -218,13 +218,13 @@ proto.on('textDocument/definition', function (params) if files.exists(targetUri) then if client.getAbility 'textDocument.definition.linkSupport' then response[i] = define.locationLink(targetUri - , files.range(targetUri, info.target.start, info.target.finish) - , files.range(targetUri, info.target.start, info.target.finish) - , files.range(uri, info.source.start, info.source.finish) + , converter.packRange(targetUri, info.target.start, info.target.finish) + , converter.packRange(targetUri, info.target.start, info.target.finish) + , converter.packRange(uri, info.source.start, info.source.finish) ) else response[i] = define.location(targetUri - , files.range(targetUri, info.target.start, info.target.finish) + , converter.packRange(targetUri, info.target.start, info.target.finish) ) end end @@ -253,13 +253,13 @@ proto.on('textDocument/typeDefinition', function (params) if files.exists(targetUri) then if client.getAbility 'textDocument.typeDefinition.linkSupport' then response[i] = define.locationLink(targetUri - , files.range(targetUri, info.target.start, info.target.finish) - , files.range(targetUri, info.target.start, info.target.finish) - , files.range(uri, info.source.start, info.source.finish) + , converter.packRange(targetUri, info.target.start, info.target.finish) + , converter.packRange(targetUri, info.target.start, info.target.finish) + , converter.packRange(uri, info.source.start, info.source.finish) ) else response[i] = define.location(targetUri - , files.range(targetUri, info.target.start, info.target.finish) + , converter.packRange(targetUri, info.target.start, info.target.finish) ) end end @@ -285,7 +285,7 @@ proto.on('textDocument/references', function (params) for i, info in ipairs(result) do local targetUri = info.uri response[i] = define.location(targetUri - , files.range(targetUri, info.target.start, info.target.finish) + , converter.packRange(targetUri, info.target.start, info.target.finish) ) end return response @@ -305,7 +305,7 @@ proto.on('textDocument/documentHighlight', function (params) local response = {} for _, info in ipairs(result) do response[#response+1] = { - range = files.range(uri, info.start, info.finish), + range = converter.packRange(uri, info.start, info.finish), kind = info.kind, } end @@ -333,7 +333,7 @@ proto.on('textDocument/rename', function (params) if not workspaceEdit.changes[ruri] then workspaceEdit.changes[ruri] = {} end - local textEdit = define.textEdit(files.range(ruri, info.start, info.finish), info.text) + local textEdit = define.textEdit(converter.packRange(ruri, info.start, info.finish), info.text) workspaceEdit.changes[ruri][#workspaceEdit.changes[ruri]+1] = textEdit end return workspaceEdit @@ -351,7 +351,7 @@ proto.on('textDocument/prepareRename', function (params) return nil end return { - range = files.range(uri, result.start, result.finish), + range = converter.packRange(uri, result.start, result.finish), placeholder = result.text, } end) @@ -418,7 +418,7 @@ proto.on('textDocument/completion', function (params) commitCharacters = res.commitCharacters, command = res.command, textEdit = res.textEdit and { - range = files.range( + range = converter.packRange( uri, res.textEdit.start, res.textEdit.finish @@ -429,7 +429,7 @@ proto.on('textDocument/completion', function (params) local t = {} for j, edit in ipairs(res.additionalTextEdits) do t[j] = { - range = files.range( + range = converter.packRange( uri, edit.start, edit.finish @@ -493,7 +493,7 @@ proto.on('completionItem/resolve', function (item) local t = {} for j, edit in ipairs(resolved.additionalTextEdits) do t[j] = { - range = files.range( + range = converter.packRange( uri, edit.start, edit.finish @@ -563,12 +563,12 @@ proto.on('textDocument/documentSymbol', function (params) local function convert(symbol) await.delay() - symbol.range = files.range( + symbol.range = converter.packRange( uri, symbol.range[1], symbol.range[2] ) - symbol.selectionRange = files.range( + symbol.selectionRange = converter.packRange( uri, symbol.selectionRange[1], symbol.selectionRange[2] @@ -611,7 +611,7 @@ proto.on('textDocument/codeAction', function (params) if res.edit then for turi, changes in pairs(res.edit.changes) do for _, change in ipairs(changes) do - change.range = files.range(turi, change.start, change.finish) + change.range = converter.packRange(turi, change.start, change.finish) change.start = nil change.finish = nil end @@ -658,7 +658,7 @@ proto.on('workspace/symbol', function (params) local function convert(symbol) symbol.location = define.location( symbol.uri, - files.range( + converter.packRange( symbol.uri, symbol.range[1], symbol.range[2] @@ -790,7 +790,7 @@ proto.on('textDocument/onTypeFormatting', function (params) local results = {} for i, edit in ipairs(edits) do results[i] = { - range = files.range(uri, edit.start, edit.finish), + range = converter.packRange(uri, edit.start, edit.finish), newText = edit.text:gsub('\t', tab), } end -- cgit v1.2.3 From 5fd5881a00a9a3c99ee0b8c9e17d1bd40f1f5309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 16:03:37 +0800 Subject: cleanup --- script/core/completion.lua | 29 ------------------ script/files.lua | 76 ---------------------------------------------- 2 files changed, 105 deletions(-) diff --git a/script/core/completion.lua b/script/core/completion.lua index e56ed3f8..bb55506a 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -225,35 +225,6 @@ local function buildFunction(results, source, value, oop, data) end end -local function buildInsertRequire(state, targetUri, stemName) - local uri = guide.getUri(state.ast) - local text = files.getText(uri) - local start = 1 - for i = 1, #lines do - local ln = lines[i] - local lnText = text:sub(ln.start, ln.finish) - if not lnText:find('require', 1, true) then - start = ln.start - break - end - end - local path = furi.decode(targetUri) - local visiblePaths = rpath.getVisiblePath(path, config.get 'Lua.runtime.path', true) - if not visiblePaths or #visiblePaths == 0 then - return nil - end - table.sort(visiblePaths, function (a, b) - return #a.expect < #b.expect - end) - return { - { - start = start, - finish = start - 1, - newText = ('local %s = require %q\n'):format(stemName, visiblePaths[1].expect) - } - } -end - local function isSameSource(state, source, pos) if guide.getUri(source) ~= guide.getUri(state.ast) then return false diff --git a/script/files.lua b/script/files.lua index d6ea057f..e7999533 100644 --- a/script/files.lua +++ b/script/files.lua @@ -576,78 +576,6 @@ function m.diffedOffsetBack(uri, offset) return smerger.getOffsetBack(file._diffInfo, offset) end ---- 将光标位置转化为 position ----@param uri uri ----@param offset integer ----@param leftOrRight? '"left"'|'"right"' ----@return position -function m.position(uri, offset, leftOrRight) - local file = m.getFile(uri) - local lines = m.getLines(uri) - local text = m.getText(uri) - if not file then - return { - line = 0, - character = 0, - } - end - if file._diffInfo then - local start, finish = smerger.getOffsetBack(file._diffInfo, offset) - if leftOrRight == 'right' then - offset = finish - else - offset = start - end - lines = m.getOriginLines(uri) - text = m.getOriginText(uri) - end - local row, col = guide.rowColOf(offset) - local start, finish = guide.lineRange(lines, row, true) - start = start + 1 - if col <= finish - start + 1 then - local ucol = util.utf8Len(text, start, start + col - 1) - if row < 1 then - row = 1 - end - if leftOrRight == 'left' and ucol > 0 then - ucol = ucol - 1 - end - return { - line = row - 1, - character = ucol, - } - else - return { - line = row - 1, - character = util.utf8Len(text, start, finish), - } - end -end - ---- 将起点与终点位置转化为 range - ----@param uri uri ----@param offset1 integer ----@param offset2 integer -function m.range(uri, offset1, offset2) - local range = { - start = m.position(uri, offset1, 'left'), - ['end'] = m.position(uri, offset2, 'right'), - } - return range -end - ---- convert `range` to `offsetStart` and `offsetFinish` ----@param uri table ----@param range table ----@return integer start ----@return integer finish -function m.unrange(uri, range) - local start = m.offset(uri, range.start, true) - local finish = m.offset(uri, range['end'], false) - return start, finish -end - --- 获取文件的自定义缓存信息(在文件内容更新后自动失效) function m.getCache(uri) local file = m.fileMap[uri] @@ -778,8 +706,6 @@ end function m.flushCache() for uri, file in pairs(m.fileMap) do file.cacheActiveTime = math.huge - m.linesMap[uri] = nil - m.originLinesMap[uri] = nil m.astMap[uri] = nil file.cache = {} end @@ -791,8 +717,6 @@ function m.flushFileCache(uri) return end file.cacheActiveTime = math.huge - m.linesMap[uri] = nil - m.originLinesMap[uri] = nil m.astMap[uri] = nil file.cache = {} end -- cgit v1.2.3 From 1b2ca30ec04f69d0fbc8127bb72eff488218e086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 16:10:03 +0800 Subject: cleanup --- script/client.lua | 6 +++--- script/proto/converter.lua | 41 +++++++++++++++++++++++++++++++++++++++++ script/proto/define.lua | 32 -------------------------------- script/provider/diagnostic.lua | 4 ++-- script/provider/provider.lua | 14 +++++++------- 5 files changed, 53 insertions(+), 44 deletions(-) diff --git a/script/client.lua b/script/client.lua index c539a0f7..e77eaaae 100644 --- a/script/client.lua +++ b/script/client.lua @@ -216,15 +216,15 @@ function m.setConfig(changes, onlyMemory) end end ----@alias textEdit {start: integer, finish: integer, text: string} +---@alias textEditor {start: integer, finish: integer, text: string} ---@param uri uri ----@param edits textEdit[] +---@param edits textEditor[] function m.editText(uri, edits) local files = require 'files' local textEdits = {} for i, edit in ipairs(edits) do - textEdits[i] = define.textEdit(converter.packRange(uri, edit.start, edit.finish), edit.text) + textEdits[i] = converter.textEdit(converter.packRange(uri, edit.start, edit.finish), edit.text) end proto.request('workspace/applyEdit', { edit = { diff --git a/script/proto/converter.lua b/script/proto/converter.lua index 4b4b9f5d..b8744181 100644 --- a/script/proto/converter.lua +++ b/script/proto/converter.lua @@ -18,6 +18,7 @@ end ---@param uri uri ---@param position position +---@return integer function m.unpackPosition(uri, position) local pos = guide.positionOf(position.line, position.character) return pos @@ -47,4 +48,44 @@ function m.unpackRange(uri, range) return start, finish end +---@alias location {uri: uri, range: range} + +---@param uri string +---@param range range +---@return location +function m.location(uri, range) + return { + uri = uri, + range = range, + } +end + +---@alias locationLink {targetUri:uri, targetRange: range, targetSelectionRange: range, originSelectionRange: range} + +---@param uri string +---@param range range +---@param selection range +---@param origin range +---@return locationLink +function m.locationLink(uri, range, selection, origin) + return { + targetUri = uri, + targetRange = range, + targetSelectionRange = selection, + originSelectionRange = origin, + } +end + +---@alias textEdit {range: range, newText: string} + +---@param range range +---@param newtext string +---@return textEdit +function m.textEdit(range, newtext) + return { + range = range, + newText = newtext, + } +end + return m diff --git a/script/proto/define.lua b/script/proto/define.lua index 2e61bc3e..0cdc6406 100644 --- a/script/proto/define.lua +++ b/script/proto/define.lua @@ -1,37 +1,5 @@ local m = {} ----@alias location table ----@param uri string ----@param range range ----@return location -function m.location(uri, range) - return { - uri = uri, - range = range, - } -end - ----@alias locationLink table ----@param uri string ----@param range range ----@param selection range ----@param origin range -function m.locationLink(uri, range, selection, origin) - return { - targetUri = uri, - targetRange = range, - targetSelectionRange = selection, - originSelectionRange = origin, - } -end - -function m.textEdit(range, newtext) - return { - range = range, - newText = newtext, - } -end - --- 诊断等级 m.DiagnosticSeverity = { Error = 1, diff --git a/script/provider/diagnostic.lua b/script/provider/diagnostic.lua index ec579428..37c25cf9 100644 --- a/script/provider/diagnostic.lua +++ b/script/provider/diagnostic.lua @@ -49,7 +49,7 @@ local function buildSyntaxError(uri, err) local relUri = rel.uri relatedInformation[#relatedInformation+1] = { message = rmessage, - location = define.location(relUri, converter.packRange(relUri, rel.start, rel.finish)), + location = converter.location(relUri, converter.packRange(relUri, rel.start, rel.finish)), } end end @@ -76,7 +76,7 @@ local function buildDiagnostic(uri, diag) local rtext = files.getText(rel.uri) relatedInformation[#relatedInformation+1] = { message = rel.message or rtext:sub(rel.start, rel.finish), - location = define.location(rel.uri, converter.packRange(rel.uri, rel.start, rel.finish)) + location = converter.location(rel.uri, converter.packRange(rel.uri, rel.start, rel.finish)) } end end diff --git a/script/provider/provider.lua b/script/provider/provider.lua index af62372b..938b3102 100644 --- a/script/provider/provider.lua +++ b/script/provider/provider.lua @@ -217,13 +217,13 @@ proto.on('textDocument/definition', function (params) if targetUri then if files.exists(targetUri) then if client.getAbility 'textDocument.definition.linkSupport' then - response[i] = define.locationLink(targetUri + response[i] = converter.locationLink(targetUri , converter.packRange(targetUri, info.target.start, info.target.finish) , converter.packRange(targetUri, info.target.start, info.target.finish) , converter.packRange(uri, info.source.start, info.source.finish) ) else - response[i] = define.location(targetUri + response[i] = converter.location(targetUri , converter.packRange(targetUri, info.target.start, info.target.finish) ) end @@ -252,13 +252,13 @@ proto.on('textDocument/typeDefinition', function (params) if targetUri then if files.exists(targetUri) then if client.getAbility 'textDocument.typeDefinition.linkSupport' then - response[i] = define.locationLink(targetUri + response[i] = converter.locationLink(targetUri , converter.packRange(targetUri, info.target.start, info.target.finish) , converter.packRange(targetUri, info.target.start, info.target.finish) , converter.packRange(uri, info.source.start, info.source.finish) ) else - response[i] = define.location(targetUri + response[i] = converter.location(targetUri , converter.packRange(targetUri, info.target.start, info.target.finish) ) end @@ -284,7 +284,7 @@ proto.on('textDocument/references', function (params) local response = {} for i, info in ipairs(result) do local targetUri = info.uri - response[i] = define.location(targetUri + response[i] = converter.location(targetUri , converter.packRange(targetUri, info.target.start, info.target.finish) ) end @@ -333,7 +333,7 @@ proto.on('textDocument/rename', function (params) if not workspaceEdit.changes[ruri] then workspaceEdit.changes[ruri] = {} end - local textEdit = define.textEdit(converter.packRange(ruri, info.start, info.finish), info.text) + local textEdit = converter.textEdit(converter.packRange(ruri, info.start, info.finish), info.text) workspaceEdit.changes[ruri][#workspaceEdit.changes[ruri]+1] = textEdit end return workspaceEdit @@ -656,7 +656,7 @@ proto.on('workspace/symbol', function (params) end local function convert(symbol) - symbol.location = define.location( + symbol.location = converter.location( symbol.uri, converter.packRange( symbol.uri, -- cgit v1.2.3 From 7253c49258c847601fe27d7e623d7d416556ba06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 16:39:54 +0800 Subject: update --- script/proto/converter.lua | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/script/proto/converter.lua b/script/proto/converter.lua index b8744181..d2be23d2 100644 --- a/script/proto/converter.lua +++ b/script/proto/converter.lua @@ -1,4 +1,5 @@ local guide = require 'parser.guide' +local files = require 'files' local m = {} @@ -10,6 +11,12 @@ local m = {} ---@return position function m.packPosition(uri, pos) local row, col = guide.rowColOf(pos) + local state = files.getState(uri) + local text = files.getText(uri) + if text then + local lineOffset = state.lines[row] + col = utf8.len(text, lineOffset, lineOffset + col - 1, true) + end return { line = row, character = col, @@ -20,7 +27,14 @@ end ---@param position position ---@return integer function m.unpackPosition(uri, position) - local pos = guide.positionOf(position.line, position.character) + local row, col = position.line, position.character + local state = files.getState(uri) + local text = files.getText(uri) + if text then + local lineOffset = state.lines[row] + col = utf8.offset(text, lineOffset + col, lineOffset) - 1 + end + local pos = guide.positionOf(row, col) return pos end -- cgit v1.2.3 From c73a5ccba1b39784b8b5ce8ce3f8694aee3e19da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 17:02:59 +0800 Subject: update --- script/core/code-action.lua | 58 ++++++++++++++----------------------- script/core/command/removeSpace.lua | 42 +++++++++++++++++---------- script/files.lua | 8 ++--- 3 files changed, 53 insertions(+), 55 deletions(-) diff --git a/script/core/code-action.lua b/script/core/code-action.lua index 40aef8fc..c9f2ddd2 100644 --- a/script/core/code-action.lua +++ b/script/core/code-action.lua @@ -6,51 +6,37 @@ local guide = require "parser.guide" local converter = require 'proto.converter' local function checkDisableByLuaDocExits(uri, row, mode, code) - local ast = files.getState(uri) + local state = files.getState(uri) local text = files.getOriginText(uri) - local line = lines[row] - if ast.ast.docs and line then - for _, doc in ipairs(ast.ast.docs) do - if doc.start >= line.start - and doc.finish <= line.finish then - if doc.type == 'doc.diagnostic' then - if doc.mode == mode then - if doc.names then - return { - start = doc.finish, - finish = doc.finish, - newText = text:sub(doc.finish, doc.finish) - .. ', ' - .. code - } - else - return { - start = doc.finish, - finish = doc.finish, - newText = text:sub(doc.finish, doc.finish) - .. ': ' - .. code - } - end - end + local lines = state.lines + if state.ast.docs and lines then + guide.eachSourceBetween(state.ast.docs, guide.positionOf(row, 0), guide.positionOf(row + 1, 0), function (doc) + if doc.type == 'doc.diagnostic' + and doc.mode == mode then + if doc.names then + return { + start = doc.finish, + finish = doc.finish, + newText = ', ' .. code, + } + else + return { + start = doc.finish, + finish = doc.finish, + newText = ': ' .. code, + } end end - end + end) end return nil end local function checkDisableByLuaDocInsert(uri, row, mode, code) - local ast = files.getState(uri) - local text = files.getOriginText(uri) - -- 先看看上一行是不是已经有了 - -- 没有的话就插入一行 - local line = lines[row] return { - start = line.start, - finish = line.start, - newText = '---@diagnostic ' .. mode .. ': ' .. code .. '\n' - .. text:sub(line.start, line.start) + start = guide.positionOf(row, 0), + finish = guide.positionOf(row, 0), + newText = '---@diagnostic ' .. mode .. ': ' .. code .. '\n', } end diff --git a/script/core/command/removeSpace.lua b/script/core/command/removeSpace.lua index 3d7795a1..d92fee79 100644 --- a/script/core/command/removeSpace.lua +++ b/script/core/command/removeSpace.lua @@ -15,27 +15,39 @@ end return function (data) local uri = data.uri local text = files.getText(uri) - local ast = files.getState(uri) - if not lines then + local state = files.getState(uri) + if not state then return end + local lines = {} local textEdit = {} - for i = 1, #lines do - local line = guide.lineContent(lines, text, i, true) - local pos = line:find '[ \t]+$' - if pos then - local start, finish = guide.lineRange(lines, i, true) - start = start + pos - if isInString(ast, start) then - goto NEXT_LINE - end - textEdit[#textEdit+1] = { - range = converter.packRange(uri, start, finish), - newText = '', - } + for i = 0, #lines do + local startPos = lines[i] + local startOffset = guide.positionToOffset(state, startPos) + local finishOffset = text:find('[\r\n]', startOffset) or (#text + 1) + local lastOffset = finishOffset - 1 + local lastChar = text:sub(lastOffset, lastOffset) + if lastChar ~= ' ' and lastChar ~= '\t' then + goto NEXT_LINE + end + local lastPos = guide.offsetToPosition(state, lastOffset) + if isInString(state.ast, lastPos) then goto NEXT_LINE end + local firstOffset = startOffset + for n = lastOffset - 1, startOffset, -1 do + local char = text:sub(n, n) + if char ~= ' ' and char ~= '\t' then + firstOffset = n + 1 + break + end + end + local firstPos = guide.offsetToPosition(state, firstOffset) - 1 + textEdit[#textEdit+1] = { + range = converter.packRange(uri, firstPos, lastPos), + newText = '', + } ::NEXT_LINE:: end diff --git a/script/files.lua b/script/files.lua index e7999533..0c2c2874 100644 --- a/script/files.lua +++ b/script/files.lua @@ -518,11 +518,11 @@ function m.getVisibles(uri) end local visibles = {} for i, range in ipairs(ranges) do - -- TODO 改成行号 - local start, finish = m.unrange(uri, range) + local startRow = guide.rowColOf(range.start) + local finishRow = guide.rowColOf(range['end']) visibles[i] = { - start = start, - finish = finish, + start = guide.positionOf(startRow, 0), + finish = guide.positionOf(finishRow, 0), } end return visibles -- cgit v1.2.3 From cf8bf5e0dff95fb19dc8fc15e7f3cfd5e44edb04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 17:03:54 +0800 Subject: disable fornow --- script/core/type-formatting.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/script/core/type-formatting.lua b/script/core/type-formatting.lua index cd2044bc..e3494220 100644 --- a/script/core/type-formatting.lua +++ b/script/core/type-formatting.lua @@ -36,6 +36,7 @@ local function findBackward(text, offset, ...) end local function checkSplitOneLine(results, uri, offset, ch) + do return end if ch ~= '\n' then return end -- cgit v1.2.3 From 08265aeeeb71d3101ebdfeaa3f630c964da1aea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 17:20:37 +0800 Subject: update submodules --- 3rd/bee.lua | 2 +- 3rd/luamake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/3rd/bee.lua b/3rd/bee.lua index b025c851..18115443 160000 --- a/3rd/bee.lua +++ b/3rd/bee.lua @@ -1 +1 @@ -Subproject commit b025c851433cc698b6e6f6af2043f54cd085f0c3 +Subproject commit 1811544335a7e69467639570d67e728e01cbece5 diff --git a/3rd/luamake b/3rd/luamake index 077e399e..59940d9a 160000 --- a/3rd/luamake +++ b/3rd/luamake @@ -1 +1 @@ -Subproject commit 077e399e7e04def80ee59f686a4a88bfee0cf3a7 +Subproject commit 59940d9a2c7de34d4c6bfd575dac654719bd144f -- cgit v1.2.3 From e98031d6afff3e8a1b383ad0548d5857c3f06ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 17:25:48 +0800 Subject: fix --- script/files.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/script/files.lua b/script/files.lua index 0c2c2874..dc39a446 100644 --- a/script/files.lua +++ b/script/files.lua @@ -7,12 +7,10 @@ local proto = require 'proto' local lang = require 'language' local await = require 'await' local timer = require 'timer' -local plugin = require 'plugin' local util = require 'utility' local guide = require 'parser.guide' local smerger = require 'string-merger' local progress = require "progress" -local client = require 'client' local unicode @@ -98,6 +96,7 @@ function m.exists(uri) end local function pluginOnSetText(file, text) + local plugin = require 'plugin' file._diffInfo = nil local suc, result = plugin.dispatch('OnSetText', file.uri, text) if not suc then @@ -409,7 +408,8 @@ function m.eachDll() end function m.compileState(uri, text) - local ws = require 'workspace' + local ws = require 'workspace' + local client = require 'client' if not m.isOpen(uri) and not m.isLibrary(uri) and #text >= config.get 'Lua.workspace.preloadFileSize' * 1000 then -- cgit v1.2.3 From 48fe9fdd2071da918d3c7f0011f0e8c56b865b9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 17:34:51 +0800 Subject: fix --- .vscode/launch.json | 2 +- script/files.lua | 4 ++-- script/proto/converter.lua | 24 ++++++++++++++---------- script/provider/diagnostic.lua | 2 +- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 73516e26..c4194825 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -24,7 +24,7 @@ "type": "lua", "request": "attach", "stopOnEntry": false, - "address": "127.0.0.1:11427", + "address": "127.0.0.1:11413", "outputCapture": [ ], "sourceMaps": [ diff --git a/script/files.lua b/script/files.lua index dc39a446..19f4da89 100644 --- a/script/files.lua +++ b/script/files.lua @@ -518,8 +518,8 @@ function m.getVisibles(uri) end local visibles = {} for i, range in ipairs(ranges) do - local startRow = guide.rowColOf(range.start) - local finishRow = guide.rowColOf(range['end']) + local startRow = range.start.line + local finishRow = range['end'].line visibles[i] = { start = guide.positionOf(startRow, 0), finish = guide.positionOf(finishRow, 0), diff --git a/script/proto/converter.lua b/script/proto/converter.lua index d2be23d2..9ff7e4dd 100644 --- a/script/proto/converter.lua +++ b/script/proto/converter.lua @@ -11,11 +11,13 @@ local m = {} ---@return position function m.packPosition(uri, pos) local row, col = guide.rowColOf(pos) - local state = files.getState(uri) - local text = files.getText(uri) - if text then - local lineOffset = state.lines[row] - col = utf8.len(text, lineOffset, lineOffset + col - 1, true) + if col > 0 then + local state = files.getState(uri) + local text = files.getText(uri) + if text then + local lineOffset = state.lines[row] + col = utf8.len(text, lineOffset, lineOffset + col - 1, true) + end end return { line = row, @@ -28,11 +30,13 @@ end ---@return integer function m.unpackPosition(uri, position) local row, col = position.line, position.character - local state = files.getState(uri) - local text = files.getText(uri) - if text then - local lineOffset = state.lines[row] - col = utf8.offset(text, lineOffset + col, lineOffset) - 1 + if col > 0 then + local state = files.getState(uri) + local text = files.getText(uri) + if text then + local lineOffset = state.lines[row] + col = utf8.offset(text, col + 1, lineOffset) - 1 + end end local pos = guide.positionOf(row, col) return pos diff --git a/script/provider/diagnostic.lua b/script/provider/diagnostic.lua index 37c25cf9..382b73d9 100644 --- a/script/provider/diagnostic.lua +++ b/script/provider/diagnostic.lua @@ -46,7 +46,7 @@ local function buildSyntaxError(uri, err) else rmessage = text:sub(rel.start, rel.finish) end - local relUri = rel.uri + local relUri = rel.uri or uri relatedInformation[#relatedInformation+1] = { message = rmessage, location = converter.location(relUri, converter.packRange(relUri, rel.start, rel.finish)), -- cgit v1.2.3 From 127f0c549bb46d218e4b81db6c4ffd40394927ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 19:17:13 +0800 Subject: update parser --- script/parser/newparser.lua | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index 957d98e8..e4210d0f 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -192,7 +192,6 @@ local ChunkFinishMap = { ['else'] = true, ['elseif'] = true, ['in'] = true, - ['do'] = true, ['then'] = true, ['until'] = true, [';'] = true, @@ -201,6 +200,22 @@ local ChunkFinishMap = { ['}'] = true, } +local ListFinishMap = { + ['end'] = true, + ['else'] = true, + ['elseif'] = true, + ['in'] = true, + ['then'] = true, + ['do'] = true, + ['until'] = true, + ['for'] = true, + ['if'] = true, + ['local'] = true, + ['repeat'] = true, + ['return'] = true, + ['while'] = true, +} + local State, Lua, Line, LineOffset, Chunk, Tokens, Index, LastTokenFinish, Mode, LocalCount local LocalLimit = 200 @@ -1367,7 +1382,7 @@ local function parseExpList(mini) if not token then break end - if ChunkFinishMap[token] then + if ListFinishMap[token] then break end if token == ',' then @@ -1395,7 +1410,8 @@ local function parseExpList(mini) and nextToken ~= 'function' and nextToken ~= 'true' and nextToken ~= 'false' - and nextToken ~= 'nil' then + and nextToken ~= 'nil' + and nextToken ~= 'not' then break end end @@ -1820,7 +1836,9 @@ local function parseVarargs() break end end - if not varargs.node and Mode == 'Lua' then + if not varargs.node + and Mode == 'Lua' + and Chunk[#Chunk].type ~= 'main' then pushError { type = 'UNEXPECT_DOTS', start = varargs.start, @@ -1931,8 +1949,7 @@ local function isChunkFinishToken(token) if tp == 'for' or tp == 'in' or tp == 'loop' then - return token == 'do' - or token == 'end' + return token == 'end' end if tp == 'if' or tp == 'ifblock' @@ -1943,7 +1960,7 @@ local function isChunkFinishToken(token) or token == 'else' or token == 'elseif' end - return token ~= 'do' + return true end local function parseActions() @@ -2226,16 +2243,13 @@ local function parseExpUnit() return nil end -local function parseUnaryOP(level) +local function parseUnaryOP() local token = Tokens[Index + 1] local symbol = UnarySymbol[token] and token or UnaryAlias[token] if not symbol then return nil end local myLevel = UnarySymbol[symbol] - if level and myLevel < level then - return nil - end local op = { type = symbol, start = getPosition(Tokens[Index], 'left'), @@ -2324,7 +2338,7 @@ end function parseExp(asAction, level) local exp - local uop, uopLevel = parseUnaryOP(level) + local uop, uopLevel = parseUnaryOP() if uop then skipSpace() local child = parseExp(asAction, uopLevel) @@ -3249,7 +3263,10 @@ local function parseWhile() Index = Index + 2 skipSpace() - local filter = parseExp() + local nextToken = Tokens[Index + 1] + local filter = nextToken ~= 'do' + and nextToken ~= 'then' + and parseExp() if filter then action.filter = filter action.finish = filter.finish -- cgit v1.2.3 From 5e6897bc1a25b936724af6eeb5fc463a8d395d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 19:28:34 +0800 Subject: fix --- script/core/command/removeSpace.lua | 5 ++--- script/core/diagnostics/trailing-space.lua | 3 +-- script/proto/converter.lua | 2 +- script/provider/provider.lua | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/script/core/command/removeSpace.lua b/script/core/command/removeSpace.lua index d92fee79..3021d4a4 100644 --- a/script/core/command/removeSpace.lua +++ b/script/core/command/removeSpace.lua @@ -20,11 +20,10 @@ return function (data) return end - local lines = {} + local lines = state.lines local textEdit = {} for i = 0, #lines do - local startPos = lines[i] - local startOffset = guide.positionToOffset(state, startPos) + local startOffset = lines[i] local finishOffset = text:find('[\r\n]', startOffset) or (#text + 1) local lastOffset = finishOffset - 1 local lastChar = text:sub(lastOffset, lastOffset) diff --git a/script/core/diagnostics/trailing-space.lua b/script/core/diagnostics/trailing-space.lua index 5c66b118..cc51cf77 100644 --- a/script/core/diagnostics/trailing-space.lua +++ b/script/core/diagnostics/trailing-space.lua @@ -20,8 +20,7 @@ return function (uri, callback) local text = files.getText(uri) local lines = state.lines for i = 0, #lines do - local startPos = lines[i] - local startOffset = guide.positionToOffset(state, startPos) + local startOffset = lines[i] local finishOffset = text:find('[\r\n]', startOffset) or (#text + 1) local lastOffset = finishOffset - 1 local lastChar = text:sub(lastOffset, lastOffset) diff --git a/script/proto/converter.lua b/script/proto/converter.lua index 9ff7e4dd..53b65b12 100644 --- a/script/proto/converter.lua +++ b/script/proto/converter.lua @@ -35,7 +35,7 @@ function m.unpackPosition(uri, position) local text = files.getText(uri) if text then local lineOffset = state.lines[row] - col = utf8.offset(text, col + 1, lineOffset) - 1 + col = utf8.offset(text, col + 1, lineOffset) - lineOffset end end local pos = guide.positionOf(row, col) diff --git a/script/provider/provider.lua b/script/provider/provider.lua index 938b3102..39683b2b 100644 --- a/script/provider/provider.lua +++ b/script/provider/provider.lua @@ -530,7 +530,7 @@ proto.on('textDocument/signatureHelp', function (params) for j, param in ipairs(result.params) do parameters[j] = { label = { - param.label[1] - 1, + param.label[1], param.label[2], } } -- cgit v1.2.3 From 7ddc57e0f0a8b32d7d8bfa9228e856d897fc8de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 20:38:07 +0800 Subject: update --- script/core/code-action.lua | 1 - script/core/type-formatting.lua | 72 ++++++++++++++++++++------------------- script/parser/newparser.lua | 2 +- test.lua | 2 +- test/type_formatting/init.lua | 74 +++++++++++++++++++++++++++-------------- 5 files changed, 89 insertions(+), 62 deletions(-) diff --git a/script/core/code-action.lua b/script/core/code-action.lua index c9f2ddd2..ff141bbf 100644 --- a/script/core/code-action.lua +++ b/script/core/code-action.lua @@ -7,7 +7,6 @@ local converter = require 'proto.converter' local function checkDisableByLuaDocExits(uri, row, mode, code) local state = files.getState(uri) - local text = files.getOriginText(uri) local lines = state.lines if state.ast.docs and lines then guide.eachSourceBetween(state.ast.docs, guide.positionOf(row, 0), guide.positionOf(row + 1, 0), function (doc) diff --git a/script/core/type-formatting.lua b/script/core/type-formatting.lua index e3494220..b946184b 100644 --- a/script/core/type-formatting.lua +++ b/script/core/type-formatting.lua @@ -2,85 +2,89 @@ local files = require 'files' local lookBackward = require 'core.look-backward' local guide = require "parser.guide" -local function insertIndentation(uri, offset, edits) - local text = files.getOriginText(uri) - local row = guide.rowColOf(offset) - local line = lines[row] - local indent = text:sub(line.start, line.finish):match '^%s*' +local function insertIndentation(uri, position, edits) + local text = files.getText(uri) + local state = files.getState(uri) + local row = guide.rowColOf(position) + local offset = state.lines[row] + local indent = text:match('^%s*', offset) for _, edit in ipairs(edits) do edit.text = edit.text:gsub('\n', '\n' .. indent) end end -local function findForward(text, offset, ...) - local pos = text:match('^[ \t]*()', offset) - if not pos then +local function findForward(uri, position, ...) + local text = files.getText(uri) + local state = files.getState(uri) + local offset = guide.positionToOffset(state, position) + local firstOffset = text:match('^[ \t]*()', offset + 1) + if not firstOffset then return nil end for _, symbol in ipairs { ... } do - if text:sub(pos, pos + #symbol - 1) == symbol then - return pos, symbol + if text:sub(firstOffset, firstOffset + #symbol - 1) == symbol then + return guide.offsetToPosition(state, firstOffset - 1), symbol end end return nil end -local function findBackward(text, offset, ...) - local pos = lookBackward.findAnyOffset(text, offset) +local function findBackward(uri, position, ...) + local text = files.getText(uri) + local state = files.getState(uri) + local offset = guide.positionToOffset(state, position) + local lastOffset = lookBackward.findAnyOffset(text, offset) for _, symbol in ipairs { ... } do - if text:sub(pos - #symbol + 1, pos) == symbol then - return pos - #symbol + 1, symbol + if text:sub(lastOffset - #symbol + 1, lastOffset) == symbol then + return guide.offsetToPosition(state, lastOffset) end end return nil end -local function checkSplitOneLine(results, uri, offset, ch) - do return end +local function checkSplitOneLine(results, uri, position, ch) if ch ~= '\n' then return end - local text = files.getOriginText(uri) - local fOffset, fSymbol = findForward(text, offset + 1, 'end', '}') - if not fOffset then + local fPosition, fSymbol = findForward(uri, position, 'end', '}') + if not fPosition then return end - local bOffset, bSymbol = findBackward(text, offset, 'then', 'do', ')', '{') - if not bOffset then + local bPosition = findBackward(uri, position, 'then', 'do', ')', '{') + if not bPosition then return end local edits = {} edits[#edits+1] = { - start = bOffset + #bSymbol, - finish = offset, + start = bPosition, + finish = position, text = '\n\t', } edits[#edits+1] = { - start = offset + 1, - finish = fOffset + #fSymbol - 1, - text = '' + start = position, + finish = fPosition + 1, + text = '', } edits[#edits+1] = { - start = fOffset + #fSymbol, - finish = fOffset + #fSymbol - 1, - text = '\n' .. fSymbol + start = fPosition + 1, + finish = fPosition + 1, + text = '\n' .. fSymbol:sub(1, 1) } - insertIndentation(uri, bOffset, edits) + insertIndentation(uri, bPosition, edits) for _, edit in ipairs(edits) do results[#results+1] = edit end end -return function (uri, offset, ch) +return function (uri, position, ch) local ast = files.getState(uri) - local text = files.getOriginText(uri) - if not ast or not text then + if not ast then return nil end local results = {} -- split `function () $ end` - checkSplitOneLine(results, uri, offset, ch) + checkSplitOneLine(results, uri, position, ch) return results end diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index e4210d0f..96b1fb64 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -2627,7 +2627,7 @@ local function parseMultiVars(n1, parser, isLocal) if not nrest or not nrest[i] then v.redundant = { max = max, - passed = v + 2, + passed = i + 2, } pushActionIntoCurrentChunk(v) end diff --git a/test.lua b/test.lua index f0e905b9..d2e2c38a 100644 --- a/test.lua +++ b/test.lua @@ -77,7 +77,7 @@ local function testAll() test 'command' test 'document_symbol' test 'code_action' - --test 'type_formatting' + test 'type_formatting' --test 'other' end diff --git a/test/type_formatting/init.lua b/test/type_formatting/init.lua index 9178ea4f..46b8223d 100644 --- a/test/type_formatting/init.lua +++ b/test/type_formatting/init.lua @@ -1,16 +1,16 @@ local core = require 'core.type-formatting' local files = require 'files' local util = require 'utility' +local catch = require 'catch' rawset(_G, 'TEST', true) function TEST(script) return function (expect) - local pos = script:find('$', 1, true) - 1 - local new_script = script:gsub('%$', '') files.removeAll() - files.setText('', new_script) - local edits = core('', pos, expect.ch) + local newScript, catched = catch(script, '?') + files.setText('', newScript) + local edits = core('', catched['?'][1][1], expect.ch) if edits then assert(expect.edits) assert(util.equal(edits, expect.edits)) @@ -21,80 +21,104 @@ function TEST(script) end TEST [[ -if true then $ end +if true then end ]] { ch = '\n', edits = { { - start = 13, + start = 12, finish = 13, text = '\n\t', }, { - start = 14, - finish = 17, + start = 13, + finish = 15, text = '', }, { - start = 18, - finish = 17, - text = '\nend', + start = 15, + finish = 15, + text = '\ne', }, } } TEST [[ -if true then $end +if true then end ]] { ch = '\n', edits = { { - start = 13, + start = 12, finish = 13, text = '\n\t', }, { - start = 14, - finish = 16, + start = 13, + finish = 14, text = '', }, { - start = 17, - finish = 16, - text = '\nend', + start = 14, + finish = 14, + text = '\ne', }, } } TEST [[ -if true then$end +if true thenend ]] { ch = '\n', edits = { { - start = 13, + start = 12, finish = 12, text = '\n\t', }, { - start = 13, - finish = 15, + start = 12, + finish = 13, text = '', }, + { + start = 13, + finish = 13, + text = '\ne', + }, + } +} + +TEST [[ + if true thenend +]] +{ + ch = '\n', + edits = { { start = 16, - finish = 15, - text = '\nend', + finish = 16, + text = '\n \t', + }, + { + start = 16, + finish = 17, + text = '', + }, + { + start = 17, + finish = 17, + text = '\n e', }, } } TEST [[ if true then - $ + end ]] { -- cgit v1.2.3 From 291a7b3a7fcaee5bc761722ca46265f3cd7f70f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 20:51:25 +0800 Subject: fix --- .vscode/launch.json | 2 +- script/core/code-action.lua | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index c4194825..73516e26 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -24,7 +24,7 @@ "type": "lua", "request": "attach", "stopOnEntry": false, - "address": "127.0.0.1:11413", + "address": "127.0.0.1:11427", "outputCapture": [ ], "sourceMaps": [ diff --git a/script/core/code-action.lua b/script/core/code-action.lua index ff141bbf..8256107e 100644 --- a/script/core/code-action.lua +++ b/script/core/code-action.lua @@ -6,10 +6,13 @@ local guide = require "parser.guide" local converter = require 'proto.converter' local function checkDisableByLuaDocExits(uri, row, mode, code) + if row < 0 then + return nil + end local state = files.getState(uri) local lines = state.lines if state.ast.docs and lines then - guide.eachSourceBetween(state.ast.docs, guide.positionOf(row, 0), guide.positionOf(row + 1, 0), function (doc) + return guide.eachSourceBetween(state.ast.docs, guide.positionOf(row, 0), guide.positionOf(row + 1, 0), function (doc) if doc.type == 'doc.diagnostic' and doc.mode == mode then if doc.names then @@ -73,8 +76,8 @@ local function disableDiagnostic(uri, code, start, results) checkDisableByLuaDocExits (uri, row - 1, 'disable-next-line', code) or checkDisableByLuaDocInsert(uri, row, 'disable-next-line', code)) pushEdit(lang.script('ACTION_DISABLE_DIAG_FILE', code), - checkDisableByLuaDocExits (uri, 1, 'disable', code) - or checkDisableByLuaDocInsert(uri, 1, 'disable', code)) + checkDisableByLuaDocExits (uri, 0, 'disable', code) + or checkDisableByLuaDocInsert(uri, 0, 'disable', code)) end local function markGlobal(uri, name, results) -- cgit v1.2.3 From c95e9c91236bccb4593a0d9d218dca78bcb06ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 23 Sep 2021 22:15:47 +0800 Subject: update --- script/files.lua | 20 +++++++++++++ script/parser/guide.lua | 24 ++++++---------- script/parser/lines.lua | 20 ++++--------- script/proto/converter.lua | 72 ++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 97 insertions(+), 39 deletions(-) diff --git a/script/files.lua b/script/files.lua index 19f4da89..659a1aa0 100644 --- a/script/files.lua +++ b/script/files.lua @@ -112,6 +112,7 @@ local function pluginOnSetText(file, text) suc, result, diffs = xpcall(smerger.mergeDiff, log.error, text, result) if suc then file._diffInfo = diffs + file.originLines = parser.lines(text) return result else if DEVELOP and result then @@ -291,6 +292,17 @@ function m.getOriginText(uri) return file.originText end +--- 获取文件原始行表 +---@param uri uri +---@return integer[] +function m.getOriginLines(uri) + local file = m.fileMap[uri] + if not file then + return nil + end + return file.originLines +end + function m.getChildFiles(uri) local results = {} local uris = m.getAllUris() @@ -576,6 +588,14 @@ function m.diffedOffsetBack(uri, offset) return smerger.getOffsetBack(file._diffInfo, offset) end +function m.hasDiffed(uri) + local file = m.getFile(uri) + if not file then + return false + end + return file._diffInfo ~= nil +end + --- 获取文件的自定义缓存信息(在文件内容更新后自动失效) function m.getCache(uri) local file = m.fileMap[uri] diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 28a275cf..b65d9680 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -759,17 +759,19 @@ function m.positionOf(row, col) return row * 10000 + col end +function m.positionToOffsetByLines(lines, position) + local row, col = m.rowColOf(position) + return lines[row] + col - 1 +end + --- 返回全文光标位置 ---@param state any ---@param position integer function m.positionToOffset(state, position) - local lines = state.lines - local row, col = m.rowColOf(position) - return lines[row] + col - 1 + return m.positionToOffsetByLines(state.lines, position) end -function m.offsetToPosition(state, offset) - local lines = state.lines +function m.offsetToPositionByLines(lines, offset) local left = 0 local right = #lines local row = 0 @@ -794,16 +796,8 @@ function m.offsetToPosition(state, offset) return m.positionOf(row, col) end -function m.lineContent(lines, text, row, ignoreNL) - local line = lines[row] - if not line then - return '' - end - if ignoreNL then - return text:sub(line.start, line.range) - else - return text:sub(line.start, line.finish) - end +function m.offsetToPosition(state, offset) + return m.offsetToPositionByLines(state.lines, offset) end local isSetMap = { diff --git a/script/parser/lines.lua b/script/parser/lines.lua index 06023df1..964aabf4 100644 --- a/script/parser/lines.lua +++ b/script/parser/lines.lua @@ -5,30 +5,20 @@ local ssub = string.sub return function (text) local current = 1 local lines = {} - local i = 1 + lines[0] = 1 + local i = 0 while true do local pos = sfind(text,'[\r\n]', current) if not pos then break end - local line = { - start = current - 1, - range = pos - 1, - } - lines[i] = line i = i + 1 if ssub(text, pos, pos + 1) == '\r\n' then - current = pos + 2 - line.finish = pos + 1 + current = pos + 2 else - current = pos + 1 - line.finish = pos + current = pos + 1 end + lines[i] = current end - lines[i] = { - start = current - 1, - finish = #text, - range = #text, - } return lines end diff --git a/script/proto/converter.lua b/script/proto/converter.lua index 53b65b12..5fb73c14 100644 --- a/script/proto/converter.lua +++ b/script/proto/converter.lua @@ -3,13 +3,9 @@ local files = require 'files' local m = {} - ---@alias position {line: integer, character: integer} ----@param uri uri ----@param pos integer ----@return position -function m.packPosition(uri, pos) +local function rawPackPosition(uri, pos) local row, col = guide.rowColOf(pos) if col > 0 then local state = files.getState(uri) @@ -25,10 +21,39 @@ function m.packPosition(uri, pos) } end ----@param uri uri ----@param position position ----@return integer -function m.unpackPosition(uri, position) + +local function diffedPackPosition(uri, originPos) + local state = files.getState(uri) + local originLines = files.getOriginLines(uri) + local originOffset = guide.positionToOffsetByLines(originLines, originPos) + local offset = files.diffedOffsetBack(uri, originOffset) + local pos = guide.offsetToPosition(state, offset) + local row, col = guide.rowColOf(pos) + if col > 0 then + local text = files.getOriginText(uri) + if text then + local lineOffset = originLines[row] + col = utf8.len(text, lineOffset, lineOffset + col - 1, true) + end + end + return { + line = row, + character = col, + } +end + +---@param uri uri +---@param pos integer +---@return position +function m.packPosition(uri, pos) + if files.hasDiffed(uri) then + return diffedPackPosition(uri, pos) + else + return rawPackPosition(uri, pos) + end +end + +local function rawUnpackPosition(uri, position) local row, col = position.line, position.character if col > 0 then local state = files.getState(uri) @@ -42,6 +67,35 @@ function m.unpackPosition(uri, position) return pos end +local function diffedUnpackPosition(uri, position) + local row, col = position.line, position.character + local originLines = files.getOriginLines(uri) + if col > 0 then + local text = files.getOriginText(uri) + if text then + local lineOffset = originLines[row] + col = utf8.offset(text, col + 1, lineOffset) - lineOffset + end + end + local state = files.getState(uri) + local originPos = guide.positionOf(row, col) + local originOffset = guide.positionToOffsetByLines(originLines, originPos) + local offset = files.diffedOffset(originOffset) + local pos = guide.offsetToPosition(state, offset) + return pos +end + +---@param uri uri +---@param position position +---@return integer +function m.unpackPosition(uri, position) + if files.hasDiffed(uri) then + return diffedUnpackPosition(uri, position) + else + return rawUnpackPosition(uri, position) + end +end + ---@alias range {start: position, end: position} ---@param uri uri -- cgit v1.2.3 From 9f73d326ccea763762cefd2866e477796221b10f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 10:16:04 +0800 Subject: fix --- script/core/noder.lua | 2 +- script/parser/newparser.lua | 62 +++++++++++++++++++++++---------------------- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/script/core/noder.lua b/script/core/noder.lua index 177a151c..927f3c6d 100644 --- a/script/core/noder.lua +++ b/script/core/noder.lua @@ -1271,7 +1271,7 @@ compileNodeMap = util.switch() type = 'call', dummy = true, start = source.keyword[3], - finish = source.keyword[6], + finish = exps[#exps].finish, node = node, args = { param1, param2 }, parent = source, diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index 96b1fb64..ee2c5e62 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -1496,36 +1496,6 @@ local function parseTable() goto CONTINUE end local lastRight = lastRightPosition() - if token == '[' then - if wantSep then - pushError { - type = 'MISS_SEP_IN_TABLE', - start = lastRight, - finish = getPosition(Tokens[Index], 'left'), - } - end - wantSep = true - index = index + 1 - local tindex = parseIndex() - skipSpace() - if expectAssign() then - skipSpace() - local ivalue = parseExp() - tindex.type = 'tableindex' - tindex.parent = tbl - if ivalue then - ivalue.parent = tindex - tindex.finish = ivalue.finish - tindex.value = ivalue - else - missExp() - end - tbl[index] = tindex - else - missSymbol '=' - end - goto CONTINUE - end local exp = parseExp(true) if exp then @@ -1581,6 +1551,38 @@ local function parseTable() tbl[index] = texp goto CONTINUE end + + if token == '[' then + if wantSep then + pushError { + type = 'MISS_SEP_IN_TABLE', + start = lastRight, + finish = getPosition(Tokens[Index], 'left'), + } + end + wantSep = true + index = index + 1 + local tindex = parseIndex() + skipSpace() + if expectAssign() then + skipSpace() + local ivalue = parseExp() + tindex.type = 'tableindex' + tindex.parent = tbl + if ivalue then + ivalue.parent = tindex + tindex.finish = ivalue.finish + tindex.value = ivalue + else + missExp() + end + tbl[index] = tindex + else + missSymbol '=' + end + goto CONTINUE + end + missSymbol '}' break ::CONTINUE:: -- cgit v1.2.3 From 05e9b84c2f9c0effbe5ae86c19fd390ba8067e17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 11:54:59 +0800 Subject: fix --- script/proto/converter.lua | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/script/proto/converter.lua b/script/proto/converter.lua index 5fb73c14..0ff07290 100644 --- a/script/proto/converter.lua +++ b/script/proto/converter.lua @@ -21,14 +21,13 @@ local function rawPackPosition(uri, pos) } end - -local function diffedPackPosition(uri, originPos) +local function diffedPackPosition(uri, pos) local state = files.getState(uri) + local offset = guide.positionToOffset(state, pos) + local originOffset = files.diffedOffsetBack(uri, offset) local originLines = files.getOriginLines(uri) - local originOffset = guide.positionToOffsetByLines(originLines, originPos) - local offset = files.diffedOffsetBack(uri, originOffset) - local pos = guide.offsetToPosition(state, offset) - local row, col = guide.rowColOf(pos) + local originPos = guide.offsetToPositionByLines(originLines, originOffset) + local row, col = guide.rowColOf(originPos) if col > 0 then local text = files.getOriginText(uri) if text then @@ -80,7 +79,7 @@ local function diffedUnpackPosition(uri, position) local state = files.getState(uri) local originPos = guide.positionOf(row, col) local originOffset = guide.positionToOffsetByLines(originLines, originPos) - local offset = files.diffedOffset(originOffset) + local offset = files.diffedOffset(uri, originOffset) local pos = guide.offsetToPosition(state, offset) return pos end -- cgit v1.2.3 From 8870b6a8f8827c7eaa70f9663f754586aa2408fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 15:02:50 +0800 Subject: resolve #639 --- changelog.md | 1 + script/core/hover/label.lua | 3 +-- script/core/infer.lua | 5 +++-- script/core/noder.lua | 3 +++ script/parser/luadoc.lua | 2 +- script/parser/newparser.lua | 16 ++++++++-------- test/hover/init.lua | 15 +++++++++++++++ test/type_inference/init.lua | 7 +++++++ 8 files changed, 39 insertions(+), 13 deletions(-) diff --git a/changelog.md b/changelog.md index 7d46a108..8d897903 100644 --- a/changelog.md +++ b/changelog.md @@ -8,6 +8,7 @@ + `Lua.completion.requireSeparator` * `NEW` diagnostics: + `different-requires` +* `NEW` supports `---@CustomClass` * `CHG` hover: improve showing multi defines * `CHG` hover: improve showing multi comments at enums * `CHG` hint: `Lua.hint.paramName` now supports `Disable`, `Literal` and `All` diff --git a/script/core/hover/label.lua b/script/core/hover/label.lua index a29cf672..3322e0d3 100644 --- a/script/core/hover/label.lua +++ b/script/core/hover/label.lua @@ -50,8 +50,7 @@ local function asValue(source, title) local literal = infer.searchAndViewLiterals(source) local cont if not infer.hasType(source, 'string') - and not type:find('%[%]$') - and not type:find('%w%<') then + and not type:find('%[%]$') then if #vm.getRefs(source, '*') > 0 or infer.hasType(source, 'table') then cont = buildTable(source) diff --git a/script/core/infer.lua b/script/core/infer.lua index d6784c67..2915f7f5 100644 --- a/script/core/infer.lua +++ b/script/core/infer.lua @@ -371,9 +371,10 @@ function m.getDocName(doc) return nodeName .. '[]' end if doc.type == 'doc.type.table' then - local key = m.viewDocName(doc.tkey) or '?' + local node = m.viewDocName(doc.node) or '?' + local key = m.viewDocName(doc.tkey) or '?' local value = m.viewDocName(doc.tvalue) or '?' - return ('table<%s, %s>'):format(key, value) + return ('%s<%s, %s>'):format(node, key, value) end if doc.type == 'doc.type.function' then return m.viewDocFunction(doc) diff --git a/script/core/noder.lua b/script/core/noder.lua index 927f3c6d..f364f458 100644 --- a/script/core/noder.lua +++ b/script/core/noder.lua @@ -905,6 +905,9 @@ compileNodeMap = util.switch() end) : case 'doc.type.table' : call(function (noders, id, source) + if source.node then + pushForward(noders, id, getID(source.node), INFO_CLASS_TO_EXNTENDS) + end if source.tkey then local keyID = id .. TABLE_KEY pushForward(noders, keyID, getID(source.tkey)) diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 4a431e68..56da32f2 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -324,7 +324,7 @@ local function parseTypeUnitTable(parent, node) end nextSymbolOrError('>') - node.parent = result; + node.parent = result result.finish = getFinish() result.tkey = key result.tvalue = value diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index ee2c5e62..8469b68d 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -374,6 +374,12 @@ local function fastForwardToken(offset) or myOffset >= offset then break end + local token = Tokens[Index + 1] + if NLMap[token] then + Line = Line + 1 + LineOffset = Tokens[Index] + #token + State.lines[Line] = LineOffset + end Index = Index + 2 end end @@ -390,14 +396,8 @@ local function resolveLongString(finishMark) local stringResult = ssub(Lua, start, finishOffset - 1) local lastLN = stringResult:find '[\r\n][^\r\n]*$' if lastLN then - local result, count = stringResult - : gsub('\r\n', '\n') - : gsub('[\r\n]', '\n') - LineOffset = lastLN + start - for i = Line + 1, Line + count do - State.lines[i] = LineOffset - end - Line = Line + count + local result = stringResult + : gsub('\r\n?', '\n') stringResult = result end fastForwardToken(finishOffset + #finishMark) diff --git a/test/hover/init.lua b/test/hover/init.lua index c16e466d..8058317d 100644 --- a/test/hover/init.lua +++ b/test/hover/init.lua @@ -1699,3 +1699,18 @@ print(b.) [[ field A.x: any ]] + +TEST [[ +---@class A +---@field x number +---@field y number + +---@type A +local +]] +[[ +local t: A { + x: number, + y: number, +} +]] diff --git a/test/type_inference/init.lua b/test/type_inference/init.lua index 286d47cb..23ebf54e 100644 --- a/test/type_inference/init.lua +++ b/test/type_inference/init.lua @@ -353,6 +353,13 @@ TEST 'table' [[ local ]] +TEST 'A' [[ +---@class A + +---@type A +local +]] + TEST 'table' [[ self.[#self.t+1] = {} ]] -- cgit v1.2.3 From ba29b31eccde71832b97a2d01af6339e5e52a94a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 15:03:57 +0800 Subject: `completion.displayContext` default to `0` --- changelog.md | 1 + script/config/config.lua | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 8d897903..00805c1b 100644 --- a/changelog.md +++ b/changelog.md @@ -16,6 +16,7 @@ * `CHG` no longer ignore file names case in Windows * `CHG` watching library changes * `CHG` completion: improve misspelling results +* `CHG` completion: `Lua.completion.displayContext` default to `0` * `FIX` runtime errors * `FIX` hint: may show param-2 as `self` * `FIX` semantic: may fail when scrolling diff --git a/script/config/config.lua b/script/config/config.lua index b44b48dc..52848a44 100644 --- a/script/config/config.lua +++ b/script/config/config.lua @@ -180,7 +180,7 @@ local Template = { ['Lua.completion.enable'] = Type.Boolean >> true, ['Lua.completion.callSnippet'] = Type.String >> 'Disable', ['Lua.completion.keywordSnippet'] = Type.String >> 'Replace', - ['Lua.completion.displayContext'] = Type.Integer >> 6, + ['Lua.completion.displayContext'] = Type.Integer >> 0, ['Lua.completion.workspaceWord'] = Type.Boolean >> true, ['Lua.completion.showWord'] = Type.String >> 'Fallback', ['Lua.completion.autoRequire'] = Type.Boolean >> true, -- cgit v1.2.3 From a116c777779030fee63a0ea3a56c6c6f0000fabc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 15:05:54 +0800 Subject: resolve #663 --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 00805c1b..69dca83e 100644 --- a/changelog.md +++ b/changelog.md @@ -17,6 +17,7 @@ * `CHG` watching library changes * `CHG` completion: improve misspelling results * `CHG` completion: `Lua.completion.displayContext` default to `0` +* `CHG` [#663](https://github.com/sumneko/lua-language-server/issues/663) * `FIX` runtime errors * `FIX` hint: may show param-2 as `self` * `FIX` semantic: may fail when scrolling -- cgit v1.2.3 From 35ce57976db3b4c42193279dd55972ea013fecad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 15:06:58 +0800 Subject: fix #673 --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 69dca83e..cdc1d294 100644 --- a/changelog.md +++ b/changelog.md @@ -22,6 +22,7 @@ * `FIX` hint: may show param-2 as `self` * `FIX` semantic: may fail when scrolling * `FIX` [#660](https://github.com/sumneko/lua-language-server/issues/660) +* `FIX` [#673](https://github.com/sumneko/lua-language-server/issues/673) ## 2.3.7 `2021-8-17` -- cgit v1.2.3 From d3be298e8e9d1769a7444c233c1f70e316584a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 15:10:57 +0800 Subject: update submodules --- 3rd/bee.lua | 2 +- 3rd/love-api | 2 +- meta/3rd/love2d/library/love.graphics.lua | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/3rd/bee.lua b/3rd/bee.lua index 18115443..9a359f98 160000 --- a/3rd/bee.lua +++ b/3rd/bee.lua @@ -1 +1 @@ -Subproject commit 1811544335a7e69467639570d67e728e01cbece5 +Subproject commit 9a359f9806da860bf7d5aa630cc9eb6496679ef9 diff --git a/3rd/love-api b/3rd/love-api index b913d6e8..4fa1de69 160000 --- a/3rd/love-api +++ b/3rd/love-api @@ -1 +1 @@ -Subproject commit b913d6e804402d39401b343e3032b30eef0c83bb +Subproject commit 4fa1de69cb04af2e405b3ac400d4e0cec0e07530 diff --git a/meta/3rd/love2d/library/love.graphics.lua b/meta/3rd/love2d/library/love.graphics.lua index 9f453304..f70efefd 100644 --- a/meta/3rd/love2d/library/love.graphics.lua +++ b/meta/3rd/love2d/library/love.graphics.lua @@ -530,12 +530,13 @@ function love.graphics.newFont(filename) end --- ---Creates a new Image from a filepath, FileData, an ImageData, or a CompressedImageData, and optionally generates or specifies mipmaps for the image. --- ----@overload fun(imageData: love.ImageData):love.Image ----@overload fun(compressedImageData: love.CompressedImageData):love.Image ----@overload fun(filename: string, flags: table):love.Image +---@overload fun(fileData: love.FileData, flags: table):love.Image +---@overload fun(imageData: love.ImageData, flags: table):love.Image +---@overload fun(compressedImageData: love.CompressedImageData, flags: table):love.Image ---@param filename string # The filepath to the image file. ----@return love.Image image # An Image object which can be drawn on screen. -function love.graphics.newImage(filename) end +---@param flags {dpiscale: number, linear: boolean, mipmaps: boolean} # A table containing the following fields: +---@return love.Image image # A new Image object which can be drawn on screen. +function love.graphics.newImage(filename, flags) end --- ---Creates a new specifically formatted image. -- cgit v1.2.3 From e604de0e0871d676d2a062fc9c838b24ca0e9793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 15:28:40 +0800 Subject: resolve #659 --- changelog.md | 1 + script/core/command/autoRequire.lua | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index cdc1d294..486b0654 100644 --- a/changelog.md +++ b/changelog.md @@ -17,6 +17,7 @@ * `CHG` watching library changes * `CHG` completion: improve misspelling results * `CHG` completion: `Lua.completion.displayContext` default to `0` +* `CHG` completion: `autoRequire` has better inserting position * `CHG` [#663](https://github.com/sumneko/lua-language-server/issues/663) * `FIX` runtime errors * `FIX` hint: may show param-2 as `self` diff --git a/script/core/command/autoRequire.lua b/script/core/command/autoRequire.lua index d711fb16..b485fcb1 100644 --- a/script/core/command/autoRequire.lua +++ b/script/core/command/autoRequire.lua @@ -15,12 +15,21 @@ local function findInsertRow(uri) quot = '"', col = nil, } + local hasFounded for i = 0, #lines do local ln = lines[i] local lnText = text:match('[^\r\n]*', ln) if not lnText:find('require', 1, true) then - return i, fmt + if hasFounded then + return i, fmt + end + if not lnText:match '^local%s' + and not lnText:match '^%s*$' + and not lnText:match '^%-%-' then + return i, fmt + end else + hasFounded = true local lpPos = lnText:find '%(' if lpPos then fmt.pair = true -- cgit v1.2.3 From 706fcdaa6d220d988c256aabf6dc3125d265d385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 16:44:41 +0800 Subject: fix --- .vscode/launch.json | 2 +- script/parser/newparser.lua | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 73516e26..c4194825 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -24,7 +24,7 @@ "type": "lua", "request": "attach", "stopOnEntry": false, - "address": "127.0.0.1:11427", + "address": "127.0.0.1:11413", "outputCapture": [ ], "sourceMaps": [ diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index 8469b68d..e063040e 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -1001,9 +1001,10 @@ local function parseShortString() goto CONTINUE end if NLMap[nextToken] then + stringIndex = stringIndex + 1 stringPool[stringIndex] = '\n' currentOffset = Tokens[Index] + #nextToken - Index = Index + 2 + skipNL() goto CONTINUE end pushError { -- cgit v1.2.3 From 9ed21208bbd28207da7f57a314d761ceb120b510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 16:44:55 +0800 Subject: update bee --- 3rd/bee.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rd/bee.lua b/3rd/bee.lua index 9a359f98..ba8291f1 160000 --- a/3rd/bee.lua +++ b/3rd/bee.lua @@ -1 +1 @@ -Subproject commit 9a359f9806da860bf7d5aa630cc9eb6496679ef9 +Subproject commit ba8291f17c44c1f934a261535e818364a5828571 -- cgit v1.2.3 From f06d38754a38ef25bfe5a10b931b596becc092e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 17:08:15 +0800 Subject: stop provider when file changing --- script/core/folding.lua | 10 +++++----- script/core/semantic-tokens.lua | 8 ++++---- script/provider/provider.lua | 29 +++++++++++++++++++---------- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/script/core/folding.lua b/script/core/folding.lua index 51d1be6b..bd3ba5f3 100644 --- a/script/core/folding.lua +++ b/script/core/folding.lua @@ -146,22 +146,22 @@ local Care = { } return function (uri) - local ast = files.getState(uri) - local text = files.getText(uri) - if not ast or not text then + local state = files.getState(uri) + local text = files.getText(uri) + if not state or not text then return nil end local regions = {} local status = {} - guide.eachSource(ast.ast, function (source) + guide.eachSource(state.ast, function (source) local tp = source.type if Care[tp] then await.delay() Care[tp](source, text, regions) end end) - for _, source in ipairs(ast.comms) do + for _, source in ipairs(state.comms) do local tp = source.type if Care[tp] then await.delay() diff --git a/script/core/semantic-tokens.lua b/script/core/semantic-tokens.lua index 405f2735..38b75227 100644 --- a/script/core/semantic-tokens.lua +++ b/script/core/semantic-tokens.lua @@ -214,14 +214,14 @@ local function buildTokens(uri, results) end return function (uri, start, finish) - local ast = files.getState(uri) + local state = files.getState(uri) local text = files.getText(uri) - if not ast then + if not state then return nil end local results = {} - guide.eachSourceBetween(ast.ast, start, finish, function (source) + guide.eachSourceBetween(state.ast, start, finish, function (source) local method = Care[source.type] if not method then return @@ -230,7 +230,7 @@ return function (uri, start, finish) await.delay() end) - for _, comm in ipairs(ast.comms) do + for _, comm in ipairs(state.comms) do if comm.type == 'comment.cshort' then results[#results+1] = { start = comm.start, diff --git a/script/provider/provider.lua b/script/provider/provider.lua index 39683b2b..2b6a1f7c 100644 --- a/script/provider/provider.lua +++ b/script/provider/provider.lua @@ -166,8 +166,11 @@ proto.on('textDocument/didChange', function (params) end) proto.on('textDocument/hover', function (params) + local doc = params.textDocument + local uri = doc.uri await.close 'hover' await.setID 'hover' + await.setID('update:' .. uri) if not workspace.isReady() then local count, max = workspace.getLoadProcess() return { @@ -179,8 +182,6 @@ proto.on('textDocument/hover', function (params) end local _ = progress.create(lang.script.WINDOW_PROCESSING_HOVER, 0.5) local core = require 'core.hover' - local doc = params.textDocument - local uri = doc.uri if not files.exists(uri) then return nil end @@ -357,8 +358,10 @@ proto.on('textDocument/prepareRename', function (params) end) proto.on('textDocument/completion', function (params) + local uri = params.textDocument.uri await.close 'completion' await.setID 'completion' + await.setID('update:' .. uri) if not workspace.isReady() then local count, max = workspace.getLoadProcess() return { @@ -378,7 +381,6 @@ proto.on('textDocument/completion', function (params) local core = require 'core.completion' --log.debug('textDocument/completion') --log.debug('completion:', params.context and params.context.triggerKind, params.context and params.context.triggerCharacter) - local uri = params.textDocument.uri if not files.exists(uri) then return nil end @@ -475,10 +477,11 @@ proto.on('completionItem/resolve', function (item) if not item.data then return item end - await.close 'completion.resolve' - await.setID 'completion.resolve' local id = item.data.id local uri = item.data.uri + await.close 'completion.resolve' + await.setID 'completion.resolve' + await.setID('update:' .. uri) --await.setPriority(1000) local resolved = core.resolve(id) if not resolved then @@ -518,6 +521,7 @@ proto.on('textDocument/signatureHelp', function (params) end await.close('signatureHelp') await.setID('signatureHelp') + await.setID('update:' .. uri) local pos = converter.unpackPosition(uri, params.position) local core = require 'core.signature' local results = core(uri, pos) @@ -649,6 +653,7 @@ proto.on('workspace/symbol', function (params) await.close('workspace/symbol') await.setID('workspace/symbol') + await.setID('files.version') local symbols = core(params.query) if not symbols or #symbols == 0 then @@ -676,12 +681,13 @@ end) proto.on('textDocument/semanticTokens/full', function (params) - workspace.awaitReady() + local uri = params.textDocument.uri await.close('textDocument/semanticTokens/full') await.setID('textDocument/semanticTokens/full') + await.setID('update:' .. uri) + workspace.awaitReady() local _ = progress.create(lang.script.WINDOW_PROCESSING_SEMANTIC_FULL, 0.5) local core = require 'core.semantic-tokens' - local uri = params.textDocument.uri local text = files.getText(uri) if not text then return nil @@ -693,12 +699,13 @@ proto.on('textDocument/semanticTokens/full', function (params) end) proto.on('textDocument/semanticTokens/range', function (params) + local uri = params.textDocument.uri + await.close('textDocument/semanticTokens/range') + await.setID('textDocument/semanticTokens/range') + await.setID('update:' .. uri) workspace.awaitReady() - --await.close('textDocument/semanticTokens/range') - --await.setID('textDocument/semanticTokens/range') local _ = progress.create(lang.script.WINDOW_PROCESSING_SEMANTIC_RANGE, 0.5) local core = require 'core.semantic-tokens' - local uri = params.textDocument.uri local cache = files.getOpenedCache(uri) local start, finish if cache and not cache['firstSemantic'] then @@ -722,6 +729,7 @@ proto.on('textDocument/foldingRange', function (params) end await.close('textDocument/foldingRange') await.setID('textDocument/foldingRange') + await.setID('update:' .. uri) local regions = core(uri) if not regions then return nil @@ -826,6 +834,7 @@ do return end await.setID(awaitID) + await.setID('update:' .. uri) workspace.awaitReady() local visibles = files.getVisibles(uri) if not visibles then -- cgit v1.2.3 From e5a094cfc9ecaaea9873905b37658b9227c8fe99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 17:20:52 +0800 Subject: supports `$/cancelRequest` --- changelog.md | 1 + script/await.lua | 8 +++++--- script/proto/proto.lua | 5 ++++- script/provider/provider.lua | 4 ++++ 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/changelog.md b/changelog.md index 486b0654..df0a8350 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,7 @@ * `NEW` diagnostics: + `different-requires` * `NEW` supports `---@CustomClass` +* `NEW` supports `$/cancelRequest` * `CHG` hover: improve showing multi defines * `CHG` hover: improve showing multi comments at enums * `CHG` hint: `Lua.hint.paramName` now supports `Disable`, `Literal` and `All` diff --git a/script/await.lua b/script/await.lua index 2d27ae2c..495f381c 100644 --- a/script/await.lua +++ b/script/await.lua @@ -1,11 +1,12 @@ local timer = require 'timer' -local util = require 'utility' + +local wkmt = { __mode = 'k' } ---@class await local m = {} m.type = 'await' -m.coMap = setmetatable({}, { __mode = 'k' }) +m.coMap = setmetatable({}, wkmt) m.idMap = {} m.delayQueue = {} m.delayQueueIndex = 1 @@ -74,7 +75,7 @@ function m.setID(id, co) return end if not m.idMap[id] then - m.idMap[id] = setmetatable({}, { __mode = 'k' }) + m.idMap[id] = setmetatable({}, wkmt) end m.idMap[id][co] = true end @@ -85,6 +86,7 @@ function m.close(id) if not map then return end + m.idMap[id] = nil for co in pairs(map) do if coroutine.status(co) == 'suspended' then map[co] = nil diff --git a/script/proto/proto.lua b/script/proto/proto.lua index a0880011..61306b9f 100644 --- a/script/proto/proto.lua +++ b/script/proto/proto.lua @@ -4,7 +4,6 @@ local await = require 'await' local pub = require 'pub' local jsonrpc = require 'jsonrpc' local define = require 'proto.define' -local timer = require 'timer' local json = require 'json' local reqCounter = util.counter() @@ -121,6 +120,9 @@ function m.doMethod(proto) end await.call(function () --log.debug('Start method:', method) + if proto.id then + await.setID('proto:' .. proto.id) + end local clock = os.clock() local ok = true local res @@ -134,6 +136,7 @@ function m.doMethod(proto) if not proto.id then return end + await.close('proto:' .. proto.id) if ok then m.response(proto.id, res) else diff --git a/script/provider/provider.lua b/script/provider/provider.lua index 2b6a1f7c..070652ef 100644 --- a/script/provider/provider.lua +++ b/script/provider/provider.lua @@ -805,6 +805,10 @@ proto.on('textDocument/onTypeFormatting', function (params) return results end) +proto.on('$/cancelRequest', function (params) + await.close('proto:' .. params.id) +end) + proto.on('$/requestHint', function (params) local core = require 'core.hint' if not config.get 'Lua.hint.enable' then -- cgit v1.2.3 From 1a0f6e3aa420afff9028c4db6261f8faa6fa2ba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 17:31:53 +0800 Subject: check nil --- script/proto/converter.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/script/proto/converter.lua b/script/proto/converter.lua index 0ff07290..19d592fe 100644 --- a/script/proto/converter.lua +++ b/script/proto/converter.lua @@ -59,7 +59,10 @@ local function rawUnpackPosition(uri, position) local text = files.getText(uri) if text then local lineOffset = state.lines[row] - col = utf8.offset(text, col + 1, lineOffset) - lineOffset + local textOffset = utf8.offset(text, col + 1, lineOffset) + if textOffset then + col = textOffset - lineOffset + end end end local pos = guide.positionOf(row, col) @@ -73,7 +76,10 @@ local function diffedUnpackPosition(uri, position) local text = files.getOriginText(uri) if text then local lineOffset = originLines[row] - col = utf8.offset(text, col + 1, lineOffset) - lineOffset + local textOffset = utf8.offset(text, col + 1, lineOffset) + if textOffset then + col = textOffset - lineOffset + end end end local state = files.getState(uri) -- cgit v1.2.3 From 437bb61d0daf663a3eee894946f47bc550c39e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 18:57:03 +0800 Subject: fix #647 --- changelog.md | 1 + script/core/noder.lua | 8 ++++---- test/references/common.lua | 24 +++--------------------- 3 files changed, 8 insertions(+), 25 deletions(-) diff --git a/changelog.md b/changelog.md index df0a8350..ec34f4e0 100644 --- a/changelog.md +++ b/changelog.md @@ -23,6 +23,7 @@ * `FIX` runtime errors * `FIX` hint: may show param-2 as `self` * `FIX` semantic: may fail when scrolling +* `FIX` [#647](https://github.com/sumneko/lua-language-server/issues/647) * `FIX` [#660](https://github.com/sumneko/lua-language-server/issues/660) * `FIX` [#673](https://github.com/sumneko/lua-language-server/issues/673) diff --git a/script/core/noder.lua b/script/core/noder.lua index f364f458..d1388cb3 100644 --- a/script/core/noder.lua +++ b/script/core/noder.lua @@ -883,8 +883,8 @@ compileNodeMap = util.switch() : call(function (noders, id, source) if source.bindSources then for _, src in ipairs(source.bindSources) do - pushForward(noders, getID(src), id, INFO_REJECT_SET) - pushForward(noders, id, getID(src)) + pushForward(noders, getID(src), id) + pushBackward(noders, id, getID(src)) end end for _, enumUnit in ipairs(source.enums) do @@ -898,7 +898,7 @@ compileNodeMap = util.switch() pushForward(noders, id, unitID) if source.bindSources then for _, src in ipairs(source.bindSources) do - pushBackward(noders, unitID, getID(src), INFO_REJECT_SET) + pushBackward(noders, unitID, getID(src)) end end end @@ -972,7 +972,7 @@ compileNodeMap = util.switch() if source.bindSources then for _, src in ipairs(source.bindSources) do pushForward(noders, getID(src), id) - pushForward(noders, id, getID(src), INFO_REJECT_SET) + pushForward(noders, id, getID(src)) end end for _, field in ipairs(source.fields) do diff --git a/test/references/common.lua b/test/references/common.lua index 3669486b..4245a79d 100644 --- a/test/references/common.lua +++ b/test/references/common.lua @@ -221,30 +221,12 @@ TEST [[ ---@class A local a -a. = 1 - ---@type A local b -b.xxx = 1 -- Dont search this - ----@class C: A -local c -print(c.) -]] - -TEST [[ ----@class A -local - ----@class B -local b - -b.xx = 1 -- Dont search this - ----@type B +---@type A local c ----@type A -c. = 1 +b. = 1 +c. = 1 ]] -- cgit v1.2.3 From 10ef09e0c3b553fa40845499ef7038b8e7574a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 19:02:09 +0800 Subject: less bind --- script/parser/luadoc.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 56da32f2..1645487d 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -1250,8 +1250,16 @@ local function bindDocsBetween(sources, binded, bindSources, start, finish) break end if src.start >= start then - src.bindDocs = binded - bindSources[#bindSources+1] = src + if src.type == 'local' + or src.type == 'setglobal' + or src.type == 'tablefield' + or src.type == 'tableindex' + or src.type == 'setfield' + or src.type == 'setindex' + or src.type == 'function' then + src.bindDocs = binded + bindSources[#bindSources+1] = src + end end end end -- cgit v1.2.3 From 105476fe549a37250d6799262d5ffe370e8b9350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 19:28:13 +0800 Subject: default severity to `Warning` --- changelog.md | 3 +++ script/core/completion.lua | 2 +- script/proto/define.lua | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index ec34f4e0..73fb8878 100644 --- a/changelog.md +++ b/changelog.md @@ -19,6 +19,9 @@ * `CHG` completion: improve misspelling results * `CHG` completion: `Lua.completion.displayContext` default to `0` * `CHG` completion: `autoRequire` has better inserting position +* `CHG` diagnostics: + + `redundant-parameter` default severity to `Warning` + + `redundant-value` default severity to `Warning` * `CHG` [#663](https://github.com/sumneko/lua-language-server/issues/663) * `FIX` runtime errors * `FIX` hint: may show param-2 as `self` diff --git a/script/core/completion.lua b/script/core/completion.lua index bb55506a..d384017d 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -1994,7 +1994,7 @@ local function completion(uri, position, triggerCharacter) local results = getCache(uri, position) tracy.ZoneEnd() if results then - return results + --return results end tracy.ZoneBeginN 'completion #1' local state = files.getState(uri) diff --git a/script/proto/define.lua b/script/proto/define.lua index 0cdc6406..699bcd15 100644 --- a/script/proto/define.lua +++ b/script/proto/define.lua @@ -28,14 +28,14 @@ m.DiagnosticDefaultSeverity = { ['redefined-local'] = 'Hint', ['newline-call'] = 'Information', ['newfield-call'] = 'Warning', - ['redundant-parameter'] = 'Hint', + ['redundant-parameter'] = 'Warning', ['ambiguity-1'] = 'Warning', ['lowercase-global'] = 'Information', ['undefined-env-child'] = 'Information', ['duplicate-index'] = 'Warning', ['duplicate-set-field'] = 'Warning', ['empty-block'] = 'Hint', - ['redundant-value'] = 'Hint', + ['redundant-value'] = 'Warning', ['code-after-break'] = 'Hint', ['unbalanced-assignments'] = 'Warning', ['close-non-object'] = 'Warning', -- cgit v1.2.3 From 25c980851262e0cb00a6284f0f56843c31a72ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 19:46:32 +0800 Subject: mistake commit --- script/core/completion.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/core/completion.lua b/script/core/completion.lua index d384017d..bb55506a 100644 --- a/script/core/completion.lua +++ b/script/core/completion.lua @@ -1994,7 +1994,7 @@ local function completion(uri, position, triggerCharacter) local results = getCache(uri, position) tracy.ZoneEnd() if results then - --return results + return results end tracy.ZoneBeginN 'completion #1' local state = files.getState(uri) -- cgit v1.2.3 From 1f0a2d0e9283a4cb7f7b3fc72258eb1c5ba4e5dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 24 Sep 2021 20:16:19 +0800 Subject: update parser --- script/parser/newparser.lua | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index e063040e..1b02a5d9 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -904,8 +904,15 @@ local function parseShortString() Index = Index + 2 break end - if not token - or NLMap[token] then + if NLMap[token] then + stringIndex = stringIndex + 1 + stringPool[stringIndex] = ssub(Lua, currentOffset, Tokens[Index] - 1) + missSymbol(mark) + break + end + if not token then + stringIndex = stringIndex + 1 + stringPool[stringIndex] = ssub(Lua, currentOffset) missSymbol(mark) break end -- cgit v1.2.3