Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 71 additions & 55 deletions script/core/completion/completion.lua
Original file line number Diff line number Diff line change
Expand Up @@ -376,63 +376,79 @@ local function checkModule(state, word, position, results)
goto CONTINUE
end
local path = furi.decode(uri)
local fileName = path:match '[^/\\]*$'
local stemName = fileName:gsub('%..+', '')
if not locals[stemName]
and not vm.hasGlobalSets(state.uri, 'variable', stemName)
and not globals[stemName]
and stemName:match(guide.namePatternFull)
and matchKey(word, stemName) then
local targetState = files.getState(uri)
if not targetState then
goto CONTINUE
end
local targetReturns = targetState.ast.returns
if not targetReturns then
goto CONTINUE
end
local targetSource = targetReturns[1] and targetReturns[1][1]
if not targetSource then
goto CONTINUE
end
if targetSource.type ~= 'getlocal'
and targetSource.type ~= 'table'
and targetSource.type ~= 'function' then
goto CONTINUE
end
if targetSource.type == 'getlocal'
and vm.getDeprecated(targetSource.node) then
goto CONTINUE
end
results[#results+1] = {
label = stemName,
kind = define.CompletionItemKind.Variable,
commitCharacters = { '.' },
command = {
title = 'autoRequire',
command = 'lua.autoRequire',
arguments = {
{
uri = guide.getUri(state.ast),
target = uri,
name = stemName,
local relativePath = workspace.getRelativePath(path)
local infos = rpath.getVisiblePath(uri, path)
local testedStem = { }
for _, sr in ipairs(infos) do
local pattern = sr.searcher
:gsub("(%p)", "%%%1")
:gsub("%%%?", "(.-)")

local stemName = relativePath
:match(pattern)
:match("[%a_][%w_]*$")

if not stemName or testedStem[stemName] then
goto INNER_CONTINUE
end
testedStem[stemName] = true

if not locals[stemName]
and not vm.hasGlobalSets(state.uri, 'variable', stemName)
and not globals[stemName]
and matchKey(word, stemName) then
local targetState = files.getState(uri)
if not targetState then
goto INNER_CONTINUE
end
local targetReturns = targetState.ast.returns
if not targetReturns then
goto INNER_CONTINUE
end
local targetSource = targetReturns[1] and targetReturns[1][1]
if not targetSource then
goto INNER_CONTINUE
end
if targetSource.type ~= 'getlocal'
and targetSource.type ~= 'table'
and targetSource.type ~= 'function' then
goto INNER_CONTINUE
end
if targetSource.type == 'getlocal'
and vm.getDeprecated(targetSource.node) then
goto INNER_CONTINUE
end
results[#results+1] = {
label = stemName,
kind = define.CompletionItemKind.Variable,
commitCharacters = { '.' },
command = {
title = 'autoRequire',
command = 'lua.autoRequire',
arguments = {
{
uri = guide.getUri(state.ast),
target = uri,
name = stemName,
},
},
},
},
id = stack(targetSource, function (newSource) ---@async
local md = markdown()
md:add('md', lang.script('COMPLETION_IMPORT_FROM', ('[%s](%s)'):format(
workspace.getRelativePath(uri),
uri
)))
md:add('md', buildDesc(newSource))
return {
detail = buildDetail(newSource),
description = md,
--additionalTextEdits = buildInsertRequire(state, originUri, stemName),
}
end)
}
id = stack(targetSource, function (newSource) ---@async
local md = markdown()
md:add('md', lang.script('COMPLETION_IMPORT_FROM', ('[%s](%s)'):format(
workspace.getRelativePath(uri),
uri
)))
md:add('md', buildDesc(newSource))
return {
detail = buildDetail(newSource),
description = md,
--additionalTextEdits = buildInsertRequire(state, originUri, stemName),
}
end)
}
end
::INNER_CONTINUE::
end
::CONTINUE::
end
Expand Down
83 changes: 83 additions & 0 deletions test/crossfile/completion.lua
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,18 @@ function TEST(data)
assert(eq(expect, result))
end

local function WITH_CONFIG(cfg, f)
local prev = { }
for k, v in pairs(cfg) do
prev[k] = config.get(nil, k)
config.set(nil, k, v)
end
f()
for k, v in pairs(prev) do
config.set(nil, k, v)
end
end

TEST {
{
path = 'abc.lua',
Expand Down Expand Up @@ -951,3 +963,74 @@ TEST {
},
completion = EXISTS
}

-- Find obscured modules

WITH_CONFIG({
["Lua.runtime.pathStrict"] = true,
["Lua.runtime.path"] = {
"?/init.lua",
"sub/?/init.lua",
"obscure_path/?/?/init.lua"
},
}, function()
TEST {
{ path = 'myLib/init.lua', content = 'return {}' },
{
path = 'main.lua',
main = true,
content = [[
myLib<??>
]],
},
completion = EXISTS
}

TEST {
{ path = 'sub/myLib/init.lua', content = 'return {}' },
{
path = 'main.lua',
main = true,
content = [[
myLib<??>
]],
},
completion = EXISTS
}

TEST {
{ path = 'sub/myLib/sublib/init.lua', content = 'return {}' },
{
path = 'main.lua',
main = true,
content = [[
sublib<??>
]],
},
completion = EXISTS
}

TEST {
{ path = 'sublib/init.lua', content = 'return {}' },
{
path = 'main.lua',
main = true,
content = [[
sublib<??>
]],
},
completion = EXISTS
}

TEST {
{ path = 'obscure_path/myLib/obscure/myLib/obscure/init.lua', content = 'return {}' },
{
path = 'main.lua',
main = true,
content = [[
obscure<??>
]],
},
completion = EXISTS
}
end)