Skip to content

Commit d1b6b51

Browse files
committed
improve auto-require
#1745
1 parent 3eb1852 commit d1b6b51

File tree

2 files changed

+131
-81
lines changed

2 files changed

+131
-81
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
local config = require 'config'
2+
local util = require 'utility'
3+
local guide = require 'parser.guide'
4+
local workspace = require 'workspace'
5+
local files = require 'files'
6+
local furi = require 'file-uri'
7+
local rpath = require 'workspace.require-path'
8+
local vm = require 'vm'
9+
local matchKey = require 'core.matchkey'
10+
11+
---@class auto-require
12+
local m = {}
13+
14+
---@type table<uri, true>
15+
m.validUris = {}
16+
17+
---@param state parser.state
18+
---@return parser.object?
19+
function m.getTargetSource(state)
20+
local targetReturns = state.ast.returns
21+
if not targetReturns then
22+
return nil
23+
end
24+
local targetSource = targetReturns[1] and targetReturns[1][1]
25+
if not targetSource then
26+
return nil
27+
end
28+
if targetSource.type ~= 'getlocal'
29+
and targetSource.type ~= 'table'
30+
and targetSource.type ~= 'function' then
31+
return nil
32+
end
33+
return targetSource
34+
end
35+
36+
function m.check(state, word, position, callback)
37+
local globals = util.arrayToHash(config.get(state.uri, 'Lua.diagnostics.globals'))
38+
local locals = guide.getVisibleLocals(state.ast, position)
39+
for uri in files.eachFile(state.uri) do
40+
if uri == guide.getUri(state.ast) then
41+
goto CONTINUE
42+
end
43+
if not m.validUris[uri] then
44+
goto CONTINUE
45+
end
46+
local path = furi.decode(uri)
47+
local relativePath = workspace.getRelativePath(path)
48+
local infos = rpath.getVisiblePath(uri, path)
49+
local testedStem = { }
50+
for _, sr in ipairs(infos) do
51+
local pattern = sr.searcher
52+
:gsub("(%p)", "%%%1")
53+
:gsub("%%%?", "(.-)")
54+
55+
local stemName = relativePath
56+
:match(pattern)
57+
:match("[%a_][%w_]*$")
58+
59+
if not stemName or testedStem[stemName] then
60+
goto INNER_CONTINUE
61+
end
62+
testedStem[stemName] = true
63+
64+
if not locals[stemName]
65+
and not vm.hasGlobalSets(state.uri, 'variable', stemName)
66+
and not globals[stemName]
67+
and matchKey(word, stemName) then
68+
local targetState = files.getState(uri)
69+
if not targetState then
70+
goto INNER_CONTINUE
71+
end
72+
local targetSource = m.getTargetSource(targetState)
73+
if not targetSource then
74+
goto INNER_CONTINUE
75+
end
76+
if targetSource.type == 'getlocal'
77+
and vm.getDeprecated(targetSource.node) then
78+
goto INNER_CONTINUE
79+
end
80+
callback(uri, stemName, targetSource)
81+
end
82+
::INNER_CONTINUE::
83+
end
84+
::CONTINUE::
85+
end
86+
end
87+
88+
files.watch(function (ev, uri)
89+
if ev == 'update'
90+
or ev == 'remove' then
91+
m.validUris[uri] = nil
92+
end
93+
if ev == 'compile' then
94+
local state = files.getLastState(uri)
95+
if state and m.getTargetSource(state) then
96+
m.validUris[uri] = true
97+
end
98+
end
99+
end)
100+
101+
return m

script/core/completion/completion.lua

Lines changed: 30 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ local diag = require 'proto.diagnostic'
2222
local wssymbol = require 'core.workspace-symbol'
2323
local findSource = require 'core.find-source'
2424
local diagnostic = require 'provider.diagnostic'
25+
local autoRequire = require 'core.completion.auto-require'
2526

2627
local diagnosticModes = {
2728
'disable-next-line',
@@ -369,89 +370,37 @@ local function checkModule(state, word, position, results)
369370
if not config.get(state.uri, 'Lua.completion.autoRequire') then
370371
return
371372
end
372-
local globals = util.arrayToHash(config.get(state.uri, 'Lua.diagnostics.globals'))
373-
local locals = guide.getVisibleLocals(state.ast, position)
374-
for uri in files.eachFile(state.uri) do
375-
if uri == guide.getUri(state.ast) then
376-
goto CONTINUE
377-
end
378-
local path = furi.decode(uri)
379-
local relativePath = workspace.getRelativePath(path)
380-
local infos = rpath.getVisiblePath(uri, path)
381-
local testedStem = { }
382-
for _, sr in ipairs(infos) do
383-
local pattern = sr.searcher
384-
:gsub("(%p)", "%%%1")
385-
:gsub("%%%?", "(.-)")
386-
387-
local stemName = relativePath
388-
:match(pattern)
389-
:match("[%a_][%w_]*$")
390-
391-
if not stemName or testedStem[stemName] then
392-
goto INNER_CONTINUE
393-
end
394-
testedStem[stemName] = true
395-
396-
if not locals[stemName]
397-
and not vm.hasGlobalSets(state.uri, 'variable', stemName)
398-
and not globals[stemName]
399-
and matchKey(word, stemName) then
400-
local targetState = files.getState(uri)
401-
if not targetState then
402-
goto INNER_CONTINUE
403-
end
404-
local targetReturns = targetState.ast.returns
405-
if not targetReturns then
406-
goto INNER_CONTINUE
407-
end
408-
local targetSource = targetReturns[1] and targetReturns[1][1]
409-
if not targetSource then
410-
goto INNER_CONTINUE
411-
end
412-
if targetSource.type ~= 'getlocal'
413-
and targetSource.type ~= 'table'
414-
and targetSource.type ~= 'function' then
415-
goto INNER_CONTINUE
416-
end
417-
if targetSource.type == 'getlocal'
418-
and vm.getDeprecated(targetSource.node) then
419-
goto INNER_CONTINUE
420-
end
421-
results[#results+1] = {
422-
label = stemName,
423-
kind = define.CompletionItemKind.Variable,
424-
commitCharacters = { '.' },
425-
command = {
426-
title = 'autoRequire',
427-
command = 'lua.autoRequire',
428-
arguments = {
429-
{
430-
uri = guide.getUri(state.ast),
431-
target = uri,
432-
name = stemName,
433-
},
434-
},
373+
autoRequire.check(state, word, position, function (uri, stemName, targetSource)
374+
results[#results+1] = {
375+
label = stemName,
376+
kind = define.CompletionItemKind.Variable,
377+
commitCharacters = { '.' },
378+
command = {
379+
title = 'autoRequire',
380+
command = 'lua.autoRequire',
381+
arguments = {
382+
{
383+
uri = guide.getUri(state.ast),
384+
target = uri,
385+
name = stemName,
435386
},
436-
id = stack(targetSource, function (newSource) ---@async
437-
local md = markdown()
438-
md:add('md', lang.script('COMPLETION_IMPORT_FROM', ('[%s](%s)'):format(
439-
workspace.getRelativePath(uri),
440-
uri
441-
)))
442-
md:add('md', buildDesc(newSource))
443-
return {
444-
detail = buildDetail(newSource),
445-
description = md,
446-
--additionalTextEdits = buildInsertRequire(state, originUri, stemName),
447-
}
448-
end)
387+
},
388+
},
389+
id = stack(targetSource, function (newSource) ---@async
390+
local md = markdown()
391+
md:add('md', lang.script('COMPLETION_IMPORT_FROM', ('[%s](%s)'):format(
392+
workspace.getRelativePath(uri),
393+
uri
394+
)))
395+
md:add('md', buildDesc(newSource))
396+
return {
397+
detail = buildDetail(newSource),
398+
description = md,
399+
--additionalTextEdits = buildInsertRequire(state, originUri, stemName),
449400
}
450-
end
451-
::INNER_CONTINUE::
452-
end
453-
::CONTINUE::
454-
end
401+
end)
402+
}
403+
end)
455404
end
456405

457406
local function checkFieldFromFieldToIndex(state, name, src, parent, word, startPos, position)

0 commit comments

Comments
 (0)