summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2024-08-15 14:49:49 +0800
committerGitHub <noreply@github.com>2024-08-15 14:49:49 +0800
commit1d515a0efff310dd91bf3c8ac7a06aced9473622 (patch)
tree100b9211a00bb379cf1039b07e0346859e9bb7e6
parentc51f0389096e12a02711b911b7272f49910b1f1b (diff)
parentd32b49d5a27840bfa4079ba708de4ed3c01b816f (diff)
downloadlua-language-server-1d515a0efff310dd91bf3c8ac7a06aced9473622.zip
Merge pull request #2792 from lewis6991/feat/deforder
fix: improve textDocument/definition ordering
-rw-r--r--changelog.md1
-rw-r--r--script/core/definition.lua66
2 files changed, 63 insertions, 4 deletions
diff --git a/changelog.md b/changelog.md
index 070f0b8f..3be4b982 100644
--- a/changelog.md
+++ b/changelog.md
@@ -2,6 +2,7 @@
## Unreleased
<!-- Add all new changes here. They will be moved under a version at release -->
+* `FIX` Improved ordering of results for `textDocument/definition`.
* `FIX` Error `attempt to index a nil value` when `Lua.hint.semicolon == 'All'` [#2788](https://github.com/LuaLS/lua-language-server/issues/2788)
## 3.10.3
diff --git a/script/core/definition.lua b/script/core/definition.lua
index 3619916e..f94d3628 100644
--- a/script/core/definition.lua
+++ b/script/core/definition.lua
@@ -7,18 +7,76 @@ local rpath = require 'workspace.require-path'
local jumpSource = require 'core.jump-source'
local wssymbol = require 'core.workspace-symbol'
-local function sortResults(results)
+--- @param s string
+--- @return string[]
+local function split(s)
+ local r = {}
+ s:gsub('[^/]+', function (w)
+ r[#r+1] = w:gsub("~1", "/"):gsub("~0", "~")
+ end)
+ return r
+end
+
+--- Returns the Levenshtein distance between the two given string arrays
+--- @param a string[]
+--- @param b string[]
+--- @return number
+local function levenshteinDistance(a, b)
+ local a_len, b_len = #a, #b
+ local matrix = {} --- @type integer[][]
+
+ -- Initialize the matrix
+ for i = 1, a_len + 1 do
+ matrix[i] = { [1] = i }
+ end
+
+ for j = 1, b_len + 1 do
+ matrix[1][j] = j
+ end
+
+ -- Compute the Levenshtein distance
+ for i = 1, a_len do
+ for j = 1, b_len do
+ local cost = (a[i] == b[j]) and 0 or 1
+ matrix[i + 1][j + 1] =
+ math.min(matrix[i][j + 1] + 1, matrix[i + 1][j] + 1, matrix[i][j] + cost)
+ end
+ end
+
+ -- Return the Levenshtein distance
+ return matrix[a_len + 1][b_len + 1]
+end
+
+--- @param path1 string
+--- @param path2 string
+--- @return number
+local function pathSimilarityRatio(path1, path2)
+ if path1 == path2 then
+ return 0
+ end
+ local parts1 = split(path1)
+ local parts2 = split(path2)
+ local distance = levenshteinDistance(parts1, parts2)
+ return distance * 2 / (#parts1 + #parts2)
+end
+
+local function sortResults(results, uri)
-- 先按照顺序排序
+ -- Sort in order first
+ local simularity_cache = {} --- @type table<string,number>
table.sort(results, function (a, b)
local u1 = guide.getUri(a.target)
local u2 = guide.getUri(b.target)
if u1 == u2 then
return a.target.start < b.target.start
else
- return u1 < u2
+ simularity_cache[u1] = simularity_cache[u1] or pathSimilarityRatio(uri, u1)
+ simularity_cache[u2] = simularity_cache[u2] or pathSimilarityRatio(uri, u2)
+ return simularity_cache[u1] < simularity_cache[u2]
end
end)
-- 如果2个结果处于嵌套状态,则取范围小的那个
+ -- If two results are nested, take the one with the smaller range
local lf, lu
for i = #results, 1, -1 do
local res = results[i].target
@@ -141,7 +199,7 @@ return function (uri, offset)
local results = {}
local uris = checkRequire(source)
if uris then
- for i, uri in ipairs(uris) do
+ for _, uri in ipairs(uris) do
results[#results+1] = {
uri = uri,
source = source,
@@ -230,7 +288,7 @@ return function (uri, offset)
return nil
end
- sortResults(results)
+ sortResults(results, uri)
jumpSource(results)
return results