diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-12-02 16:59:04 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-02 16:59:04 +0800 |
commit | 98efc5696e8fa512f64dff9508e79143e6aeb200 (patch) | |
tree | 6d19bfedaad7e304247d123a871ac9e120181780 | |
parent | 6999dbb25bf2b7ae306599eceaa0f438ee4f8b8f (diff) | |
parent | 2492c1fb71d213de22756949a65e9811af50a92d (diff) | |
download | lua-language-server-98efc5696e8fa512f64dff9508e79143e6aeb200.zip |
Merge pull request #1711 from sewbacca/feature/auto-require-without-init
Feature/auto require without init
-rw-r--r-- | script/core/completion/completion.lua | 126 | ||||
-rw-r--r-- | test/crossfile/completion.lua | 83 |
2 files changed, 154 insertions, 55 deletions
diff --git a/script/core/completion/completion.lua b/script/core/completion/completion.lua index e63e8d35..f96d7b99 100644 --- a/script/core/completion/completion.lua +++ b/script/core/completion/completion.lua @@ -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 diff --git a/test/crossfile/completion.lua b/test/crossfile/completion.lua index 24a5f6c9..8504758e 100644 --- a/test/crossfile/completion.lua +++ b/test/crossfile/completion.lua @@ -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', @@ -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) |