summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelog.md6
-rw-r--r--script/core/completion/postfix.lua2
-rw-r--r--script/core/fix-indent.lua225
-rw-r--r--script/core/type-formatting.lua195
-rw-r--r--script/parser/guide.lua2
-rw-r--r--test.lua1
-rw-r--r--test/completion/common.lua26
-rw-r--r--test/type_formatting/init.lua209
8 files changed, 154 insertions, 512 deletions
diff --git a/changelog.md b/changelog.md
index 2d44a81e..d92faf22 100644
--- a/changelog.md
+++ b/changelog.md
@@ -16,6 +16,12 @@
* `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)
* `FIX` Typos in annotation descriptions
* `NEW` You can now click on "References" in CodeLen to display the reference list
+* `FIX` incorrect `CompletionItemKind` for postfix snippets [#2773](https://github.com/LuaLS/lua-language-server/pull/2773)
+* `NEW` You can now click on "References" in CodeLen to display the reference list(VSCode)
+* `NEW` Improved behavior for inserting new lines:
+ + When inside an annotation, an annotation tag will be added at the beginning of the line (VSCode).
+ + 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).
+ + Attempts to semantically fix improper indentation (generic).
## 3.9.3
`2024-6-11`
diff --git a/script/core/completion/postfix.lua b/script/core/completion/postfix.lua
index b5f33315..46c24b8e 100644
--- a/script/core/completion/postfix.lua
+++ b/script/core/completion/postfix.lua
@@ -353,7 +353,7 @@ local function checkPostFix(state, word, wordPosition, position, symbol, results
end):gsub('%$%{?%d+%}?', '')
results[#results+1] = {
label = action.key,
- kind = define.CompletionItemKind.Event,
+ kind = define.CompletionItemKind.Snippet,
description = markdown()
: add('lua', descText)
: string(),
diff --git a/script/core/fix-indent.lua b/script/core/fix-indent.lua
index 9389072d..f9564dd8 100644
--- a/script/core/fix-indent.lua
+++ b/script/core/fix-indent.lua
@@ -1,99 +1,152 @@
local files = require 'files'
local guide = require 'parser.guide'
-local lookBackward = require 'core.look-backward'
local proto = require 'proto.proto'
+local lookBackward = require 'core.look-backward'
+local util = require 'utility'
---@param state parser.state
-local function insertIndentation(state, position, edits)
- local text = state.originText or state.lua
- local lines = state.originLines or state.lines
- local row = guide.rowColOf(position)
- if not lines or not text then
- return
- end
- local offset = lines[row]
- local indent = text:match('^%s*', offset)
- for _, edit in ipairs(edits) do
- edit.text = edit.text:gsub('\n', '\n' .. indent)
+---@param change table
+local function removeSpacesAfterEnter(state, change)
+ if not change.text:match '^\r?\n[\t ]+\r?\n$' then
+ return false
end
-end
-
----@param state parser.state
-local function findForward(state, position, ...)
local lines = state.originLines or state.lines
- local offset = guide.positionToOffsetByLines(lines, position)
- local firstOffset = state.originText:match('^[ \t]*()', offset + 1)
- if not firstOffset then
- return nil
- end
- for _, symbol in ipairs { ... } do
- if state.originText:sub(firstOffset, firstOffset + #symbol - 1) == symbol then
- return guide.offsetToPositionByLines(lines, firstOffset - 1), symbol
+ local text = state.originText or state.lua
+ ---@cast text -?
+
+ local edits = {}
+ -- 清除前置空格
+ local startPos = guide.positionOf(change.range.start.line, change.range.start.character)
+ local startOffset = guide.positionToOffsetByLines(lines, startPos)
+ local leftOffset
+ for offset = startOffset, lines[change.range.start.line], -1 do
+ leftOffset = offset
+ local char = text:sub(offset, offset)
+ if char ~= ' ' and char ~= '\t' then
+ break
end
end
- return nil
-end
----@param state parser.state
-local function findBackward(state, position, ...)
- local text = state.originText or state.lua
- local lines = state.originLines or state.lines
- if not text or not lines then
- return nil
+ if leftOffset and leftOffset < startOffset then
+ edits[#edits+1] = {
+ start = leftOffset,
+ finish = startOffset,
+ text = '',
+ }
end
- local offset = guide.positionToOffsetByLines(lines, position)
- local lastOffset = lookBackward.findAnyOffset(text, offset)
- if not lastOffset then
+
+ -- 清除后置空格
+ local endOffset = startOffset + #change.text
+ local _, rightOffset = text:find('^[\t ]+', endOffset + 1)
+ if rightOffset then
+ edits[#edits+1] = {
+ start = endOffset,
+ finish = rightOffset,
+ text = '',
+ }
+ end
+
+ if #edits == 0 then
return nil
end
- for _, symbol in ipairs { ... } do
- if text:sub(lastOffset - #symbol + 1, lastOffset) == symbol then
- return guide.offsetToPositionByLines(lines, lastOffset)
+
+ return edits
+end
+
+local function getIndent(state, row)
+ local offset = state.lines[row]
+ local indent = state.lua:match('^[\t ]*', offset)
+ return indent
+end
+
+local function isInBlock(state, position)
+ local block = guide.eachSourceContain(state.ast, position, function(source)
+ if source.type == 'ifblock'
+ or source.type == 'elseifblock' then
+ if source.keyword[4] and source.keyword[4] <= position then
+ return true
+ end
end
- end
- return nil
+ if source.type == 'else' then
+ if source.keyword[2] and source.keyword[2] <= position then
+ return true
+ end
+ end
+ if source.type == 'while' then
+ if source.keyword[4] and source.keyword[4] <= position then
+ return true
+ end
+ end
+ if source.type == 'repeat' then
+ if source.keyword[2] and source.keyword[2] <= position then
+ return true
+ end
+ end
+ if source.type == 'loop' then
+ if source.keyword[4] and source.keyword[4] <= position then
+ return true
+ end
+ end
+ if source.type == 'in' then
+ if source.keyword[6] and source.keyword[6] <= position then
+ return true
+ end
+ end
+ if source.type == 'do' then
+ if source.keyword[2] and source.keyword[2] <= position then
+ return true
+ end
+ end
+ if source.type == 'function' then
+ if source.args and source.args.finish <= position then
+ return true
+ end
+ if not source.keyword[3] or source.keyword[3] >= position then
+ return true
+ end
+ end
+ if source.type == 'table' then
+ if source.start + 1 == position then
+ return true
+ end
+ end
+ end)
+ return block ~= nil
end
----@param state parser.state
----@param change table
----@param result any[]
-local function checkSplitOneLine(state, change, result)
- if change.text ~= '\r\n'
- and change.text ~= '\n' then
+local function fixWrongIdent(state, change)
+ if not change.text:match '^\r?\n[\t ]+$' then
+ return false
+ end
+ local position = guide.positionOf(change.range.start.line, change.range.start.character)
+ local row = guide.rowColOf(position)
+ local myIndent = getIndent(state, row + 1)
+ local lastIndent = getIndent(state, row)
+ if #myIndent <= #lastIndent then
return
end
-
- local lines = state.originLines or state.lines
- local position = lines[change.range.start.line + 1]
-
- local fPosition, fSymbol = findForward(state, position, 'end', '}')
- if not fPosition or not fSymbol then
+ if not util.stringStartWith(myIndent, lastIndent) then
+ return
+ end
+ local lastOffset = lookBackward.findAnyOffset(state.lua, guide.positionToOffset(state, position))
+ if not lastOffset then
return
end
- local bPosition = findBackward(state, position, 'then', 'do', ')', '{')
- if not bPosition then
+ local lastPosition = guide.offsetToPosition(state, lastOffset)
+ if isInBlock(state, lastPosition) then
return
end
+
+ local endOffset = guide.positionToOffset(state, position) + #change.text
+
local edits = {}
edits[#edits+1] = {
- start = bPosition,
- finish = position,
- text = '\n\t',
- }
- edits[#edits+1] = {
- start = position,
- finish = fPosition + 1,
+ start = endOffset - #myIndent + #lastIndent,
+ finish = endOffset,
text = '',
}
- edits[#edits+1] = {
- start = fPosition + 1,
- finish = fPosition + 1,
- text = '\n' .. fSymbol:sub(1, 1)
- }
- insertIndentation(state, bPosition, edits)
- for _, edit in ipairs(edits) do
- result[#result+1] = edit
- end
+
+ return edits
end
---@param state parser.state
@@ -129,42 +182,24 @@ local function applyEdits(state, edits)
label = 'Fix Indent',
edit = {
changes = {
- [state.uri] = {
- {
- range = {
- start = {
- line = 1,
- character = 0,
- },
- ['end'] = {
- line = 1,
- character = 0,
- }
- },
- newText = '\t',
- },
- }
+ [state.uri] = results
}
},
})
- proto.notify('$/command', {
- command = 'cursorMove',
- })
end
return function (uri, changes)
- do return end
local state = files.compileState(uri)
if not state then
return
end
- local edits = {}
- for _, change in ipairs(changes) do
- if change.range then
- checkSplitOneLine(state, change, edits)
+ local firstChange = changes[1]
+ if firstChange.range then
+ local edits = removeSpacesAfterEnter(state, firstChange)
+ or fixWrongIdent(state, firstChange)
+ if edits then
+ applyEdits(state, edits)
end
end
-
- applyEdits(state, edits)
end
diff --git a/script/core/type-formatting.lua b/script/core/type-formatting.lua
index 419cb56b..f6080650 100644
--- a/script/core/type-formatting.lua
+++ b/script/core/type-formatting.lua
@@ -4,187 +4,6 @@ local guide = require 'parser.guide'
local config = require 'config'
local util = require 'utility'
-
-local function insertIndentation(uri, position, edits)
- local text = files.getText(uri)
- local state = files.getState(uri)
- local row = guide.rowColOf(position)
- if not state or not text then
- return
- end
- local offset = state.lines[row]
- local indent = text:match('^%s*', offset)
- for _, edit in ipairs(edits) do
- edit.text = edit.text:gsub('\n', '\n' .. indent)
- end
-end
-
-local function findForward(uri, position, ...)
- local text = files.getText(uri)
- local state = files.getState(uri)
- if not state or not text then
- return nil
- end
- local offset = guide.positionToOffset(state, position)
- local firstOffset = text:match('^[ \t]*()', offset + 1)
- if not firstOffset then
- return nil
- end
- for _, symbol in ipairs { ... } do
- if text:sub(firstOffset, firstOffset + #symbol - 1) == symbol then
- return guide.offsetToPosition(state, firstOffset - 1), symbol
- end
- end
- return nil
-end
-
-local function findBackward(uri, position, ...)
- local text = files.getText(uri)
- local state = files.getState(uri)
- if not state or not text then
- return nil
- end
- local offset = guide.positionToOffset(state, position)
- local lastOffset = lookBackward.findAnyOffset(text, offset)
- for _, symbol in ipairs { ... } do
- if text:sub(lastOffset - #symbol + 1, lastOffset) == symbol then
- return guide.offsetToPosition(state, lastOffset)
- end
- end
- return nil
-end
-
-local function checkSplitOneLine(results, uri, position, ch)
- if ch ~= '\n' then
- return
- end
-
- local fPosition, fSymbol = findForward(uri, position, 'end', '}')
- if not fPosition or not fSymbol then
- return
- end
- local bPosition = findBackward(uri, position, 'then', 'do', ')', '{')
- if not bPosition then
- return
- end
- local edits = {}
- edits[#edits+1] = {
- start = bPosition,
- finish = position,
- text = '\n\t',
- }
- edits[#edits+1] = {
- start = position,
- finish = fPosition + 1,
- text = '',
- }
- edits[#edits+1] = {
- start = fPosition + 1,
- finish = fPosition + 1,
- text = '\n' .. fSymbol:sub(1, 1)
- }
- insertIndentation(uri, bPosition, edits)
- for _, edit in ipairs(edits) do
- results[#results+1] = edit
- end
-end
-
-local function getIndent(state, row)
- local offset = state.lines[row]
- local indent = state.lua:match('^[\t ]*', offset)
- return indent
-end
-
-local function isInBlock(state, position)
- local block = guide.eachSourceContain(state.ast, position, function(source)
- if source.type == 'ifblock'
- or source.type == 'elseifblock' then
- if source.keyword[4] and source.keyword[4] <= position then
- return true
- end
- end
- if source.type == 'else' then
- if source.keyword[2] and source.keyword[2] <= position then
- return true
- end
- end
- if source.type == 'while' then
- if source.keyword[4] and source.keyword[4] <= position then
- return true
- end
- end
- if source.type == 'repeat' then
- if source.keyword[2] and source.keyword[2] <= position then
- return true
- end
- end
- if source.type == 'loop' then
- if source.keyword[4] and source.keyword[4] <= position then
- return true
- end
- end
- if source.type == 'in' then
- if source.keyword[6] and source.keyword[6] <= position then
- return true
- end
- end
- if source.type == 'do' then
- if source.keyword[2] and source.keyword[2] <= position then
- return true
- end
- end
- if source.type == 'function' then
- if source.args and source.args.finish <= position then
- return true
- end
- if not source.keyword[3] or source.keyword[3] >= position then
- return true
- end
- end
- if source.type == 'table' then
- if source.start + 1 == position then
- return true
- end
- end
- end)
- return block ~= nil
-end
-
-local function checkWrongIndentation(results, uri, position, ch)
- if ch ~= '\n' then
- return
- end
- local state = files.getState(uri)
- if not state then
- return
- end
- local row = guide.rowColOf(position)
- if row <= 0 then
- return
- end
- local myIndent = getIndent(state, row)
- local lastIndent = getIndent(state, row - 1)
- if #myIndent <= #lastIndent then
- return
- end
- if not util.stringStartWith(myIndent, lastIndent) then
- return
- end
- local lastOffset = lookBackward.findAnyOffset(state.lua, guide.positionToOffset(state, position) - 1)
- if not lastOffset then
- return
- end
- local lastPosition = guide.offsetToPosition(state, lastOffset)
- if isInBlock(state, lastPosition) then
- return
- end
- results[#results+1] = {
- start = position - #myIndent + #lastIndent,
- finish = position,
- text = '',
- }
-end
-
local function typeFormat(results, uri, position, ch, options)
if ch ~= '\n' then
return
@@ -218,22 +37,12 @@ return function (uri, position, ch, options)
return nil
end
- local results = {}
- -- split `function () $ end`
- checkSplitOneLine(results, uri, position, ch)
- if #results > 0 then
- return results
- end
-
- checkWrongIndentation(results, uri, position, ch)
- if #results > 0 then
- return results
- end
-
if TEST then
return nil
end
+ local results = {}
+
typeFormat(results, uri, position, ch, options)
if #results > 0 then
return results
diff --git a/script/parser/guide.lua b/script/parser/guide.lua
index e42f2acd..768d7dec 100644
--- a/script/parser/guide.lua
+++ b/script/parser/guide.lua
@@ -105,6 +105,8 @@ local blockTypes = {
['main'] = true,
}
+m.blockTypes = blockTypes
+
local topBlockTypes = {
['while'] = true,
['function'] = true,
diff --git a/test.lua b/test.lua
index fa49655f..986b0a06 100644
--- a/test.lua
+++ b/test.lua
@@ -66,7 +66,6 @@ local function testAll()
test 'command'
test 'document_symbol'
test 'code_action'
- test 'type_formatting'
test 'other'
end
diff --git a/test/completion/common.lua b/test/completion/common.lua
index ec2372a0..30350642 100644
--- a/test/completion/common.lua
+++ b/test/completion/common.lua
@@ -3235,7 +3235,7 @@ xx@pcall<??>
{
[1] = {
label = 'pcall',
- kind = define.CompletionItemKind.Event,
+ kind = define.CompletionItemKind.Snippet,
textEdit = {
start = 3,
finish = 8,
@@ -3257,7 +3257,7 @@ xx()@pcall<??>
{
[1] = {
label = 'pcall',
- kind = define.CompletionItemKind.Event,
+ kind = define.CompletionItemKind.Snippet,
textEdit = {
start = 5,
finish = 10,
@@ -3279,7 +3279,7 @@ xx(1, 2, 3)@pcall<??>
{
[1] = {
label = 'pcall',
- kind = define.CompletionItemKind.Event,
+ kind = define.CompletionItemKind.Snippet,
textEdit = {
start = 12,
finish = 17,
@@ -3301,7 +3301,7 @@ xx@xpcall<??>
{
[1] = {
label = 'xpcall',
- kind = define.CompletionItemKind.Event,
+ kind = define.CompletionItemKind.Snippet,
textEdit = {
start = 3,
finish = 9,
@@ -3323,7 +3323,7 @@ xx()@xpcall<??>
{
[1] = {
label = 'xpcall',
- kind = define.CompletionItemKind.Event,
+ kind = define.CompletionItemKind.Snippet,
textEdit = {
start = 5,
finish = 11,
@@ -3345,7 +3345,7 @@ xx(1, 2, 3)@xpcall<??>
{
[1] = {
label = 'xpcall',
- kind = define.CompletionItemKind.Event,
+ kind = define.CompletionItemKind.Snippet,
textEdit = {
start = 12,
finish = 18,
@@ -3367,7 +3367,7 @@ xx@function<??>
{
[1] = {
label = 'function',
- kind = define.CompletionItemKind.Event,
+ kind = define.CompletionItemKind.Snippet,
textEdit = {
start = 3,
finish = 11,
@@ -3389,7 +3389,7 @@ xx.yy@method<??>
{
[1] = {
label = 'method',
- kind = define.CompletionItemKind.Event,
+ kind = define.CompletionItemKind.Snippet,
textEdit = {
start = 6,
finish = 12,
@@ -3411,7 +3411,7 @@ xx:yy@method<??>
{
[1] = {
label = 'method',
- kind = define.CompletionItemKind.Event,
+ kind = define.CompletionItemKind.Snippet,
textEdit = {
start = 6,
finish = 12,
@@ -3433,7 +3433,7 @@ xx@insert<??>
{
[1] = {
label = 'insert',
- kind = define.CompletionItemKind.Event,
+ kind = define.CompletionItemKind.Snippet,
textEdit = {
start = 3,
finish = 9,
@@ -3455,7 +3455,7 @@ xx++<??>
{
[1] = {
label = '++',
- kind = define.CompletionItemKind.Event,
+ kind = define.CompletionItemKind.Snippet,
textEdit = {
start = 2,
finish = 4,
@@ -3471,7 +3471,7 @@ xx++<??>
},
[2] = {
label = '++?',
- kind = define.CompletionItemKind.Event,
+ kind = define.CompletionItemKind.Snippet,
textEdit = {
start = 2,
finish = 4,
@@ -3495,7 +3495,7 @@ end)
{
[1] = {
label = 'xpcall',
- kind = define.CompletionItemKind.Event,
+ kind = define.CompletionItemKind.Snippet,
textEdit = {
start = 10007,
finish = 10013,
diff --git a/test/type_formatting/init.lua b/test/type_formatting/init.lua
deleted file mode 100644
index 4e9ce556..00000000
--- a/test/type_formatting/init.lua
+++ /dev/null
@@ -1,209 +0,0 @@
-local core = require 'core.type-formatting'
-local files = require 'files'
-local util = require 'utility'
-local catch = require 'catch'
-
-rawset(_G, 'TEST', true)
-
-function TEST(script)
- return function(expect)
- local newScript, catched = catch(script, '?')
- files.setText(TESTURI, newScript)
- local edits = core(TESTURI, catched['?'][1][1], expect.ch)
- if edits then
- assert(expect.edits)
- assert(util.equal(edits, expect.edits))
- else
- assert(expect.edits == nil)
- end
- files.remove(TESTURI)
- end
-end
-
-TEST [[
-if true then <??> end
-]]
-{
- ch = '\n',
- edits = {
- {
- start = 12,
- finish = 13,
- text = '\n\t',
- },
- {
- start = 13,
- finish = 15,
- text = '',
- },
- {
- start = 15,
- finish = 15,
- text = '\ne',
- },
- }
-}
-
-TEST [[
-if true then <??>end
-]]
-{
- ch = '\n',
- edits = {
- {
- start = 12,
- finish = 13,
- text = '\n\t',
- },
- {
- start = 13,
- finish = 14,
- text = '',
- },
- {
- start = 14,
- finish = 14,
- text = '\ne',
- },
- }
-}
-
-TEST [[
-if true then<??>end
-]]
-{
- ch = '\n',
- edits = {
- {
- start = 12,
- finish = 12,
- text = '\n\t',
- },
- {
- start = 12,
- finish = 13,
- text = '',
- },
- {
- start = 13,
- finish = 13,
- text = '\ne',
- },
- }
-}
-
-TEST [[
- if true then<??>end
-]]
-{
- ch = '\n',
- edits = {
- {
- start = 16,
- finish = 16,
- text = '\n \t',
- },
- {
- start = 16,
- finish = 17,
- text = '',
- },
- {
- start = 17,
- finish = 17,
- text = '\n e',
- },
- }
-}
-
-TEST [[
-local x = 1
-<??>
-]]
-{
- ch = '\n',
- edits = nil,
-}
-
-TEST [[
-local x = 'if 1 then'
- <??>
-]]
-{
- ch = '\n',
- edits = {
- {
- start = 10000,
- finish = 10004,
- text = '',
- }
- }
-}
-
-TEST [[
-local x = 'do'
- <??>
-]]
-{
- ch = '\n',
- edits = {
- {
- start = 10000,
- finish = 10004,
- text = '',
- }
- }
-}
-
-TEST [[
-local x = 'function'
- <??>
-]]
-{
- ch = '\n',
- edits = {
- {
- start = 10000,
- finish = 10004,
- text = '',
- }
- }
-}
-
-TEST [[
-do
- <??>
-]]
-{
- ch = '\n',
- edits = nil
-}
-
-TEST [[
-do
- <??>
-end
-]]
-{
- ch = '\n',
- edits = nil
-}
-
-TEST [[
-function ()
- <??>
-]]
-{
- ch = '\n',
- edits = nil
-}
-
-TEST [[
-function ()
- <??>
-end
-]]
-{
- ch = '\n',
- edits = nil
-}