summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lau <tomandfatboy@gmail.com>2024-07-01 09:40:16 +0800
committerTom Lau <tomandfatboy@gmail.com>2024-07-01 09:40:16 +0800
commitcad34b796b14c1e9d9ae062339d7e9d4cd18cc22 (patch)
tree9e8e9f9b741b54ec9e5ab5c84deeecfca82bd673
parentfea3b6d81ace6a23bf990602731ba31902c26375 (diff)
downloadlua-language-server-cad34b796b14c1e9d9ae062339d7e9d4cd18cc22.zip
perf: Optimize undefined-field check early break logic
The current early break only wants to check if there are any definition. There is no need to fetch the full definitions list. We can early break as soon as we found the 1st one.
-rw-r--r--script/core/diagnostics/undefined-field.lua2
-rw-r--r--script/vm/def.lua39
2 files changed, 40 insertions, 1 deletions
diff --git a/script/core/diagnostics/undefined-field.lua b/script/core/diagnostics/undefined-field.lua
index 4fd55966..ab5d4d54 100644
--- a/script/core/diagnostics/undefined-field.lua
+++ b/script/core/diagnostics/undefined-field.lua
@@ -21,7 +21,7 @@ return function (uri, callback)
local function checkUndefinedField(src)
await.delay()
- if #vm.getDefs(src) > 0 then
+ if vm.hasDef(src) then
return
end
local node = src.node
diff --git a/script/vm/def.lua b/script/vm/def.lua
index 5388a384..669d39c2 100644
--- a/script/vm/def.lua
+++ b/script/vm/def.lua
@@ -92,3 +92,42 @@ function vm.getDefs(source)
return results
end
+
+local HAS_DEF_ERR = {} -- the error object for comparing
+local function checkHasDef(checkFunc, source, pushResult)
+ local _, err = pcall(checkFunc, source, pushResult)
+ return err == HAS_DEF_ERR
+end
+
+---@param source parser.object
+function vm.hasDef(source)
+ local mark = {}
+ local hasLocal
+ local function pushResult(src)
+ if src.type == 'local' then
+ if hasLocal then
+ return
+ end
+ hasLocal = true
+ if source.type ~= 'local'
+ and source.type ~= 'getlocal'
+ and source.type ~= 'setlocal'
+ and source.type ~= 'doc.cast.name' then
+ return
+ end
+ end
+ if not mark[src] then
+ mark[src] = true
+ if guide.isAssign(src)
+ or guide.isLiteral(src) then
+ -- break out on 1st result using error() with a unique error object
+ error(HAS_DEF_ERR)
+ end
+ end
+ end
+
+ return checkHasDef(searchBySimple, source, pushResult)
+ or checkHasDef(searchByLocalID, source, pushResult)
+ or checkHasDef(vm.compileByNodeChain, source, pushResult)
+ or checkHasDef(searchByNode, source, pushResult)
+end