1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
local core = require 'core'
local parser = require 'parser'
local function posToRange(lines, start, finish)
local start_row, start_col = lines:rowcol(start)
local finish_row, finish_col = lines:rowcol(finish)
return {
start = {
line = start_row - 1,
character = start_col - 1,
},
['end'] = {
line = finish_row - 1,
character = finish_col,
},
}
end
local function findStartPos(pos, buf)
local res = nil
for i = pos, 1, -1 do
local c = buf:sub(i, i)
if c:find '[%w_]' then
res = i
else
break
end
end
if not res then
for i = pos, 1, -1 do
local c = buf:sub(i, i)
if c == '.' or c == ':' then
res = i
elseif c:find '[%s%c]' then
else
break
end
end
end
if not res then
return pos
end
return res
end
local function findWord(position, text)
local word = text
for i = position, 1, -1 do
local c = text:sub(i, i)
if not c:find '[%w_]' then
word = text:sub(i+1, position)
break
end
end
return word:match('^([%w_]*)')
end
local function fastCompletion(lsp, params, lines)
local uri = params.textDocument.uri
local text, oldText = lsp:getText(uri)
-- lua是从1开始的,因此都要+1
local position = lines:positionAsChar(params.position.line + 1, params.position.character)
local word = findWord(position, text)
local startPos = findStartPos(position, text)
local vm = lsp:getVM(uri)
if not vm or not startPos then
vm = lsp:loadVM(uri)
if not vm then
return nil
end
end
startPos = startPos or position
local items = core.completion(vm, text, startPos, word, oldText)
if not items or #items == 0 then
vm = lsp:loadVM(uri)
if not vm then
return nil
end
startPos = startPos or position
items = core.completion(vm, text, startPos, word)
if not items or #items == 0 then
return nil
end
end
return items
end
local function finishCompletion(lsp, params, lines)
local uri = params.textDocument.uri
local text = lsp:getText(uri)
-- lua是从1开始的,因此都要+1
local position = lines:positionAsChar(params.position.line + 1, params.position.character)
local word = findWord(position, text)
local startPos = findStartPos(position, text)
local vm = lsp:loadVM(uri)
if not vm then
return nil
end
startPos = startPos or position
local items = core.completion(vm, text, startPos, word)
if not items or #items == 0 then
return nil
end
return items
end
return function (lsp, params)
local uri = params.textDocument.uri
local text, oldText = lsp:getText(uri)
if not text then
return nil
end
local lines = parser:lines(text, 'utf8')
local items = fastCompletion(lsp, params, lines)
--local items = finishCompletion(lsp, params, lines)
if not items then
return nil
end
for i, item in ipairs(items) do
item.sortText = ('%04d'):format(i)
if item.textEdit then
item.textEdit.range = posToRange(lines, item.textEdit.start, item.textEdit.finish)
item.textEdit.start = nil
item.textEdit.finish = nil
end
if item.additionalTextEdits then
for _, textEdit in ipairs(item.additionalTextEdits) do
textEdit.range = posToRange(lines, textEdit.start, textEdit.finish)
textEdit.start = nil
textEdit.finish = nil
end
end
end
local response = {
isIncomplete = true,
items = items,
}
return response
end
|