diff options
author | Tom Lau <tomandfatboy@gmail.com> | 2024-07-01 09:40:16 +0800 |
---|---|---|
committer | Tom Lau <tomandfatboy@gmail.com> | 2024-07-01 09:40:16 +0800 |
commit | cad34b796b14c1e9d9ae062339d7e9d4cd18cc22 (patch) | |
tree | 9e8e9f9b741b54ec9e5ab5c84deeecfca82bd673 | |
parent | fea3b6d81ace6a23bf990602731ba31902c26375 (diff) | |
download | lua-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.lua | 2 | ||||
-rw-r--r-- | script/vm/def.lua | 39 |
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 |