summaryrefslogtreecommitdiff
path: root/script/vm/def.lua
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 /script/vm/def.lua
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.
Diffstat (limited to 'script/vm/def.lua')
-rw-r--r--script/vm/def.lua39
1 files changed, 39 insertions, 0 deletions
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