Skip to content

Commit 585cc20

Browse files
authored
Merge branch 'master' into inconsistent-behavior-(missing-fields)
2 parents 3b5947f + ed8559e commit 585cc20

File tree

8 files changed

+154
-512
lines changed

8 files changed

+154
-512
lines changed

changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
* `FIX` Improve the `missing-fields` logic to be able to correctly handle classes defined several times [#22770](https://github.com/LuaLS/lua-language-server/pull/2770)
1717
* `FIX` Typos in annotation descriptions
1818
* `NEW` You can now click on "References" in CodeLen to display the reference list
19+
* `FIX` incorrect `CompletionItemKind` for postfix snippets [#2773](https://github.com/LuaLS/lua-language-server/pull/2773)
20+
* `NEW` You can now click on "References" in CodeLen to display the reference list(VSCode)
21+
* `NEW` Improved behavior for inserting new lines:
22+
+ When inside an annotation, an annotation tag will be added at the beginning of the line (VSCode).
23+
+ When between `function () end` or similar constructs, the format will be adjusted to a more reasonable one (VSCode) and leading/trailing spaces will be removed (generic).
24+
+ Attempts to semantically fix improper indentation (generic).
1925

2026
## 3.9.3
2127
`2024-6-11`

script/core/completion/postfix.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ local function checkPostFix(state, word, wordPosition, position, symbol, results
353353
end):gsub('%$%{?%d+%}?', '')
354354
results[#results+1] = {
355355
label = action.key,
356-
kind = define.CompletionItemKind.Event,
356+
kind = define.CompletionItemKind.Snippet,
357357
description = markdown()
358358
: add('lua', descText)
359359
: string(),

script/core/fix-indent.lua

Lines changed: 130 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,152 @@
11
local files = require 'files'
22
local guide = require 'parser.guide'
3-
local lookBackward = require 'core.look-backward'
43
local proto = require 'proto.proto'
4+
local lookBackward = require 'core.look-backward'
5+
local util = require 'utility'
56

67
---@param state parser.state
7-
local function insertIndentation(state, position, edits)
8-
local text = state.originText or state.lua
9-
local lines = state.originLines or state.lines
10-
local row = guide.rowColOf(position)
11-
if not lines or not text then
12-
return
13-
end
14-
local offset = lines[row]
15-
local indent = text:match('^%s*', offset)
16-
for _, edit in ipairs(edits) do
17-
edit.text = edit.text:gsub('\n', '\n' .. indent)
8+
---@param change table
9+
local function removeSpacesAfterEnter(state, change)
10+
if not change.text:match '^\r?\n[\t ]+\r?\n$' then
11+
return false
1812
end
19-
end
20-
21-
---@param state parser.state
22-
local function findForward(state, position, ...)
2313
local lines = state.originLines or state.lines
24-
local offset = guide.positionToOffsetByLines(lines, position)
25-
local firstOffset = state.originText:match('^[ \t]*()', offset + 1)
26-
if not firstOffset then
27-
return nil
28-
end
29-
for _, symbol in ipairs { ... } do
30-
if state.originText:sub(firstOffset, firstOffset + #symbol - 1) == symbol then
31-
return guide.offsetToPositionByLines(lines, firstOffset - 1), symbol
14+
local text = state.originText or state.lua
15+
---@cast text -?
16+
17+
local edits = {}
18+
-- 清除前置空格
19+
local startPos = guide.positionOf(change.range.start.line, change.range.start.character)
20+
local startOffset = guide.positionToOffsetByLines(lines, startPos)
21+
local leftOffset
22+
for offset = startOffset, lines[change.range.start.line], -1 do
23+
leftOffset = offset
24+
local char = text:sub(offset, offset)
25+
if char ~= ' ' and char ~= '\t' then
26+
break
3227
end
3328
end
34-
return nil
35-
end
3629

37-
---@param state parser.state
38-
local function findBackward(state, position, ...)
39-
local text = state.originText or state.lua
40-
local lines = state.originLines or state.lines
41-
if not text or not lines then
42-
return nil
30+
if leftOffset and leftOffset < startOffset then
31+
edits[#edits+1] = {
32+
start = leftOffset,
33+
finish = startOffset,
34+
text = '',
35+
}
4336
end
44-
local offset = guide.positionToOffsetByLines(lines, position)
45-
local lastOffset = lookBackward.findAnyOffset(text, offset)
46-
if not lastOffset then
37+
38+
-- 清除后置空格
39+
local endOffset = startOffset + #change.text
40+
local _, rightOffset = text:find('^[\t ]+', endOffset + 1)
41+
if rightOffset then
42+
edits[#edits+1] = {
43+
start = endOffset,
44+
finish = rightOffset,
45+
text = '',
46+
}
47+
end
48+
49+
if #edits == 0 then
4750
return nil
4851
end
49-
for _, symbol in ipairs { ... } do
50-
if text:sub(lastOffset - #symbol + 1, lastOffset) == symbol then
51-
return guide.offsetToPositionByLines(lines, lastOffset)
52+
53+
return edits
54+
end
55+
56+
local function getIndent(state, row)
57+
local offset = state.lines[row]
58+
local indent = state.lua:match('^[\t ]*', offset)
59+
return indent
60+
end
61+
62+
local function isInBlock(state, position)
63+
local block = guide.eachSourceContain(state.ast, position, function(source)
64+
if source.type == 'ifblock'
65+
or source.type == 'elseifblock' then
66+
if source.keyword[4] and source.keyword[4] <= position then
67+
return true
68+
end
5269
end
53-
end
54-
return nil
70+
if source.type == 'else' then
71+
if source.keyword[2] and source.keyword[2] <= position then
72+
return true
73+
end
74+
end
75+
if source.type == 'while' then
76+
if source.keyword[4] and source.keyword[4] <= position then
77+
return true
78+
end
79+
end
80+
if source.type == 'repeat' then
81+
if source.keyword[2] and source.keyword[2] <= position then
82+
return true
83+
end
84+
end
85+
if source.type == 'loop' then
86+
if source.keyword[4] and source.keyword[4] <= position then
87+
return true
88+
end
89+
end
90+
if source.type == 'in' then
91+
if source.keyword[6] and source.keyword[6] <= position then
92+
return true
93+
end
94+
end
95+
if source.type == 'do' then
96+
if source.keyword[2] and source.keyword[2] <= position then
97+
return true
98+
end
99+
end
100+
if source.type == 'function' then
101+
if source.args and source.args.finish <= position then
102+
return true
103+
end
104+
if not source.keyword[3] or source.keyword[3] >= position then
105+
return true
106+
end
107+
end
108+
if source.type == 'table' then
109+
if source.start + 1 == position then
110+
return true
111+
end
112+
end
113+
end)
114+
return block ~= nil
55115
end
56116

57-
---@param state parser.state
58-
---@param change table
59-
---@param result any[]
60-
local function checkSplitOneLine(state, change, result)
61-
if change.text ~= '\r\n'
62-
and change.text ~= '\n' then
117+
local function fixWrongIdent(state, change)
118+
if not change.text:match '^\r?\n[\t ]+$' then
119+
return false
120+
end
121+
local position = guide.positionOf(change.range.start.line, change.range.start.character)
122+
local row = guide.rowColOf(position)
123+
local myIndent = getIndent(state, row + 1)
124+
local lastIndent = getIndent(state, row)
125+
if #myIndent <= #lastIndent then
63126
return
64127
end
65-
66-
local lines = state.originLines or state.lines
67-
local position = lines[change.range.start.line + 1]
68-
69-
local fPosition, fSymbol = findForward(state, position, 'end', '}')
70-
if not fPosition or not fSymbol then
128+
if not util.stringStartWith(myIndent, lastIndent) then
129+
return
130+
end
131+
local lastOffset = lookBackward.findAnyOffset(state.lua, guide.positionToOffset(state, position))
132+
if not lastOffset then
71133
return
72134
end
73-
local bPosition = findBackward(state, position, 'then', 'do', ')', '{')
74-
if not bPosition then
135+
local lastPosition = guide.offsetToPosition(state, lastOffset)
136+
if isInBlock(state, lastPosition) then
75137
return
76138
end
139+
140+
local endOffset = guide.positionToOffset(state, position) + #change.text
141+
77142
local edits = {}
78143
edits[#edits+1] = {
79-
start = bPosition,
80-
finish = position,
81-
text = '\n\t',
82-
}
83-
edits[#edits+1] = {
84-
start = position,
85-
finish = fPosition + 1,
144+
start = endOffset - #myIndent + #lastIndent,
145+
finish = endOffset,
86146
text = '',
87147
}
88-
edits[#edits+1] = {
89-
start = fPosition + 1,
90-
finish = fPosition + 1,
91-
text = '\n' .. fSymbol:sub(1, 1)
92-
}
93-
insertIndentation(state, bPosition, edits)
94-
for _, edit in ipairs(edits) do
95-
result[#result+1] = edit
96-
end
148+
149+
return edits
97150
end
98151

99152
---@param state parser.state
@@ -129,42 +182,24 @@ local function applyEdits(state, edits)
129182
label = 'Fix Indent',
130183
edit = {
131184
changes = {
132-
[state.uri] = {
133-
{
134-
range = {
135-
start = {
136-
line = 1,
137-
character = 0,
138-
},
139-
['end'] = {
140-
line = 1,
141-
character = 0,
142-
}
143-
},
144-
newText = '\t',
145-
},
146-
}
185+
[state.uri] = results
147186
}
148187
},
149188
})
150-
proto.notify('$/command', {
151-
command = 'cursorMove',
152-
})
153189
end
154190

155191
return function (uri, changes)
156-
do return end
157192
local state = files.compileState(uri)
158193
if not state then
159194
return
160195
end
161196

162-
local edits = {}
163-
for _, change in ipairs(changes) do
164-
if change.range then
165-
checkSplitOneLine(state, change, edits)
197+
local firstChange = changes[1]
198+
if firstChange.range then
199+
local edits = removeSpacesAfterEnter(state, firstChange)
200+
or fixWrongIdent(state, firstChange)
201+
if edits then
202+
applyEdits(state, edits)
166203
end
167204
end
168-
169-
applyEdits(state, edits)
170205
end

0 commit comments

Comments
 (0)