Skip to content

Commit 1d515a0

Browse files
authored
Merge pull request #2792 from lewis6991/feat/deforder
fix: improve textDocument/definition ordering
2 parents c51f038 + d32b49d commit 1d515a0

File tree

2 files changed

+63
-4
lines changed

2 files changed

+63
-4
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Unreleased
44
<!-- Add all new changes here. They will be moved under a version at release -->
5+
* `FIX` Improved ordering of results for `textDocument/definition`.
56
* `FIX` Error `attempt to index a nil value` when `Lua.hint.semicolon == 'All'` [#2788](https://github.com/LuaLS/lua-language-server/issues/2788)
67

78
## 3.10.3

script/core/definition.lua

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,76 @@ local rpath = require 'workspace.require-path'
77
local jumpSource = require 'core.jump-source'
88
local wssymbol = require 'core.workspace-symbol'
99

10-
local function sortResults(results)
10+
--- @param s string
11+
--- @return string[]
12+
local function split(s)
13+
local r = {}
14+
s:gsub('[^/]+', function (w)
15+
r[#r+1] = w:gsub("~1", "/"):gsub("~0", "~")
16+
end)
17+
return r
18+
end
19+
20+
--- Returns the Levenshtein distance between the two given string arrays
21+
--- @param a string[]
22+
--- @param b string[]
23+
--- @return number
24+
local function levenshteinDistance(a, b)
25+
local a_len, b_len = #a, #b
26+
local matrix = {} --- @type integer[][]
27+
28+
-- Initialize the matrix
29+
for i = 1, a_len + 1 do
30+
matrix[i] = { [1] = i }
31+
end
32+
33+
for j = 1, b_len + 1 do
34+
matrix[1][j] = j
35+
end
36+
37+
-- Compute the Levenshtein distance
38+
for i = 1, a_len do
39+
for j = 1, b_len do
40+
local cost = (a[i] == b[j]) and 0 or 1
41+
matrix[i + 1][j + 1] =
42+
math.min(matrix[i][j + 1] + 1, matrix[i + 1][j] + 1, matrix[i][j] + cost)
43+
end
44+
end
45+
46+
-- Return the Levenshtein distance
47+
return matrix[a_len + 1][b_len + 1]
48+
end
49+
50+
--- @param path1 string
51+
--- @param path2 string
52+
--- @return number
53+
local function pathSimilarityRatio(path1, path2)
54+
if path1 == path2 then
55+
return 0
56+
end
57+
local parts1 = split(path1)
58+
local parts2 = split(path2)
59+
local distance = levenshteinDistance(parts1, parts2)
60+
return distance * 2 / (#parts1 + #parts2)
61+
end
62+
63+
local function sortResults(results, uri)
1164
-- 先按照顺序排序
65+
-- Sort in order first
66+
local simularity_cache = {} --- @type table<string,number>
1267
table.sort(results, function (a, b)
1368
local u1 = guide.getUri(a.target)
1469
local u2 = guide.getUri(b.target)
1570
if u1 == u2 then
1671
return a.target.start < b.target.start
1772
else
18-
return u1 < u2
73+
simularity_cache[u1] = simularity_cache[u1] or pathSimilarityRatio(uri, u1)
74+
simularity_cache[u2] = simularity_cache[u2] or pathSimilarityRatio(uri, u2)
75+
return simularity_cache[u1] < simularity_cache[u2]
1976
end
2077
end)
2178
-- 如果2个结果处于嵌套状态,则取范围小的那个
79+
-- If two results are nested, take the one with the smaller range
2280
local lf, lu
2381
for i = #results, 1, -1 do
2482
local res = results[i].target
@@ -141,7 +199,7 @@ return function (uri, offset)
141199
local results = {}
142200
local uris = checkRequire(source)
143201
if uris then
144-
for i, uri in ipairs(uris) do
202+
for _, uri in ipairs(uris) do
145203
results[#results+1] = {
146204
uri = uri,
147205
source = source,
@@ -230,7 +288,7 @@ return function (uri, offset)
230288
return nil
231289
end
232290

233-
sortResults(results)
291+
sortResults(results, uri)
234292
jumpSource(results)
235293

236294
return results

0 commit comments

Comments
 (0)