summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2024-07-01 15:05:53 +0800
committerGitHub <noreply@github.com>2024-07-01 15:05:53 +0800
commit4c03394901e88e9c09a40667e561093a155fa169 (patch)
treea425dde30a599f9fd561a3737d27335238c9b2d2
parent48a4b917f17a1b688404e74bc5a578c15ba4d0c6 (diff)
parentebbc372f6754f458e7ac9b08655ce79737868aea (diff)
downloadlua-language-server-4c03394901e88e9c09a40667e561093a155fa169.zip
Merge branch 'master' into fix-params
-rw-r--r--changelog.md1
-rw-r--r--script/cli/check_worker.lua13
-rw-r--r--script/core/diagnostics/undefined-field.lua2
-rw-r--r--script/vm/def.lua39
4 files changed, 43 insertions, 12 deletions
diff --git a/changelog.md b/changelog.md
index 54e972e3..87ef33ef 100644
--- a/changelog.md
+++ b/changelog.md
@@ -6,6 +6,7 @@
* `FIX` `diagnostics.severity` defaulting to "Warning" when run using `--check` [#2730](https://github.com/LuaLS/lua-language-server/issues/2730)
* `NEW` Add support for lambda style functions, `|paramList| expr` is syntactic sugar for `function(paramList) return expr end`
* `FIX` Respect `completion.showParams` config for local function completion
+* `CHG` Improve performance of multithreaded `--check` and `undefined-field` diagnostic
## 3.9.3
`2024-6-11`
diff --git a/script/cli/check_worker.lua b/script/cli/check_worker.lua
index 23c34b2c..822c83dc 100644
--- a/script/cli/check_worker.lua
+++ b/script/cli/check_worker.lua
@@ -43,15 +43,6 @@ local checkLevel = define.DiagnosticSeverity[CHECKLEVEL] or define.DiagnosticSev
util.enableCloseFunction()
--- Hash function used to distribute work.
-local function hashString(str)
- local hash = 0
- for i = 1, #str do
- hash = (hash * 37 & 0xFFFFFFFF) + str:byte(i, i)
- end
- return hash
-end
-
local lastClock = os.clock()
local results = {}
@@ -109,9 +100,9 @@ xpcall(lclient.start, errorhandler, lclient, function (client)
local uris = files.getChildFiles(rootUri)
local max = #uris
+ table.sort(uris) -- sort file list to ensure the work distribution order across multiple threads
for i, uri in ipairs(uris) do
- local hash = hashString(uri) % numThreads + 1
- if hash == threadId then
+ if (i % numThreads + 1) == threadId then
files.open(uri)
diag.doDiagnostic(uri, true)
-- Print regularly but always print the last entry to ensure that logs written to files don't look incomplete.
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