summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--script/core/completion.lua380
-rw-r--r--script/parser/guide.lua9
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